※推薦評價好的iphone維修中心
擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢
環境資訊中心綜合外電;姜唯 編譯;林大利 審校
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
※網頁設計最專業,超強功能平台可客製化
窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機。
※超省錢租車方案
商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!
摘錄自2020年4月20日自由時報報導
武漢肺炎疫情肆虐全球,「草泥馬」可望成為人類救星?比利時一項最新研究發現,駱馬血液中的抗體,可能有助人類消滅病毒!
駱馬(llama)又名大羊駝或美洲駝,是分布於南美洲的駱駝科動物,和多種相似動物合稱為駱馬或美洲駝,體型比羊駝(Alpaca)還大。
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。
英國《週日州泰晤士報》19日報導,比利時佛朗德生物技術研究院(Vlaams Instituut voor Biotechnologie Flanders Institute of Biotechnology)、與美國德州大學奧斯汀分校的研究團隊發現,駱馬血液中的抗體,可協助人類對抗病毒,讓特效藥研究不再限於現存藥物,更可跨物種進行。
這項研究成果刊登於生物學論文預印本文獻庫BioRxiv,將隨後正式發表。
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。
CES 2021 正式揭開序幕,今年以線上模式來進行展示,LG 打前鋒舉辦整個展會中的第一場發表會,其中在 2021 年的新電視陣容中花了很大的篇幅,這次最受關注的就是為自家 OLED 電視進步極具象徵性的 OLED Evo 面板,為消費者帶來更優質的視覺體驗。
多年以來,亮度一直是液晶電視領域的重點項目之一,OLED 電視一直有個大家努力想要克服的問題,儘管它具備有深邃的黑與令人讚嘆的可視角,但若是將 OLED 電視放置在非常明亮的環境中,在觀影上還是相當吃力。LG 最新的 OLED Evo 面板以更高的亮度和 HDR,使得其觀賞效果超越過去的 OLED 電視,而 LG 也將這項飛躍的進步視作等同於 4K HDR 與 8K 的歷史性意義。
2021 年的 G1 系列將有 55、65 與 75 吋三種尺寸,與 C1 同樣搭載第四代 LG Alpha9 處理器,具備更進化的圖像處理能力,可以分析所顯示的影像廠警並且相對應地最佳化影像呈現。
在去年推出後大受好評,還被許多玩家視為新一代遊戲機好伴侶的 CX OLED,今年得全新型號仍然可支援 VRR、G-Sync 及 FreeSync,並且內建一個遊戲調整功能,將對遊戲玩家來說最重要的所有選項匯集在一起,像是更新率、低延遲等,讓玩家可依照所玩的遊戲類型不同選擇預設數值,也能夠根據自己的喜好來自定所有參數。
但今次,LG 在 G1 系列上不僅設計,還放上了更亮的顯示面板,並且與 C1 系列同步支援全新設計的 Gallery Stand 支架,對不想將電視壁掛或放在電視櫃上的人來說又多了一個新選擇。
※別再煩惱如何寫文案,掌握八大原則!
什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。
在音訊方面,最新型號的電視具有虛擬 5.1.2 環繞立體聲功能,LG 表示在你觀賞影音時,可保持聽覺感受的整體性,無論是線上串流、電視頻道或應用程式皆能確保音量大小一致,不會讓你有切換時音量忽大忽小的困擾。
最入門的產品當屬最新的 A1 系列,可以將它視為去年 BX 系列的後繼者,也是大家想要進入 OLED 領域上價格最平價的方式。配備 LG a7 處理器,HDMI 連接埠較少,但還是可以擁有全部的重點功能,包含 D遭V、HDMI 2.1(支援 VRR、ALLM 等)。至於三種系列的最後定價方面,大家可能要等到春季時才會明朗。
【推爆】終身$0月租 打電話只要1元/分
立達合法徵信社-讓您安心的選擇
※教你寫出一流的銷售文案?
銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。
※想知道最厲害的網頁設計公司嚨底家"!
RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌
除了亮度更高的 OLED Evo 外,這次 LG 首款 QNED MiniLED 電視也在展會中亮相,而這也是 LG 在 2021 年推出的頂級 LCD 電視系列的代表作品,採用量子點與 1 奈米顯示技術,並搭配 MiniLED 作為光源,亮度與對比度的表現更勝傳統 LCD 電視。
以頂級電視之姿降臨的 LG 首款 QNED MiniLED 電視,2021 系列中總共有 3 款 4K 與 8K 機型,涵蓋消費者對各種大螢幕的選擇。全新 LCD 面板結構搭載 LG 進階 MiniLED 背光技術,視覺效果如臨實境。 LG QNED TV 也是首款結合量子點與 NanoCell 技術的產品,呈現令人驚豔的精準色彩,加上進階 LED 背光模組提供更好的對比度,更飽滿深邃的黑色,畫面動感逼真。新款電視更具備 120Hz高更新率,動作倍顯流暢自然。
LG MiniLED 背光模組由近 30,000 顆微型 LED 組成,多達 2,500 個調光分區與進階區域調光技術,創造超越以往的峰值亮度,使其達到 1,000,000 : 1 的高對比度。在上述條件的支援下,可呈現優異的 HDR 畫質與卓越的對比度和廣色域及出色的色彩準確度,讓觀影效果栩栩如生、活靈活現。
這裡提醒大家,不要把 MiniLED 與 MicroLED 之間混淆了,大家可以把 MiniLED 視為 LCD 電視的升級式發展,而 MicroLED 則是另一種完全消除背光的徹底提升,兩者相較之下當然前者的價格比後者便宜些,但這也只是兩相比較罷了,想必 LG QNED MiniLED 電視的售價也不會太容易入手。
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊
【推爆】終身$0月租 打電話只要1元/分
立達合法徵信社-讓您安心的選擇
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!
※別再煩惱如何寫文案,掌握八大原則!
什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。
本文是我在5月份看到的一些有趣的內容的集合。在這裏你可以找到許多有關Blazor、ASPNET Core的學習資源和示例項目,有關在Unity中使用Zenject進行單元測試的博客,有關Unity項目架構的討論,以及對依賴注入感興趣的人的必讀書籍。
※教你寫出一流的銷售文案?
銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。
等等功能。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!
原文地址:https://medium.com/volosoft/asp-net-core-dependency-injection-best-practices-tips-tricks-c6e9c67f9d96 [正(ke)確(xue)上(shang)網(wang)]
posted by Halil İbrahim Kalkan Jul 12, 2018 · 7 min read
在這篇文章中,我將分享一下在ASP.NET Core應用程序中使用依賴注入的經驗與建議。
主要分享的目的,基於以下幾點原則:
這篇文章的前提假設你已經對依賴注入和ASP.NET Core由基本的認識,如果還沒有,首先請閱讀ASP.NET Core Dependency Injection documentation。
構造函數注入(Constructor injection)用於聲明和獲取服務對服務構造的依賴關係。
public class ProductService
{
private readonly IProductRepository _productRepository;
public ProductService(IProductRepository productRepository)
{
_productRepository = productRepository;
}
public void Delete(int id)
{
_productRepository.Delete(id);
}
}
ProductService
在構造函數中注入了它的依賴IProductRepository
,然後使用了它的Delete
方法。
良好實踐
ASP.NET Core的標配的依賴注入容器並不支持屬性注入(property injection)。但是你可以使用其他的依賴注入容器支持屬性注入。。
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
namespace MyApp
{
public class ProductService
{
public ILogger<ProductService> Logger { get; set; }
private readonly IProductRepository _productRepository;
public ProductService(IProductRepository productRepository)
{
_productRepository = productRepository;
Logger = NullLogger<ProductService>.Instance;
}
public void Delete(int id)
{
_productRepository.Delete(id);
Logger.LogInformation(
$"Deleted a product with id = {id}");
}
}
}
ProductService
聲明了一個開放了Setter的日誌(Logger)屬性。依賴注入容器能賦值一個可用的值給這個日誌屬性(前提是已經在依賴注入容器內註冊過)。
良好實踐
服務定位(Service Locator)模式是另一種獲取依賴項的方式。
public class ProductService
{
private readonly IProductRepository _productRepository;
private readonly ILogger<ProductService> _logger;
public ProductService(IServiceProvider serviceProvider)
{
_productRepository = serviceProvider
.GetRequiredService<IProductRepository>();
_logger = serviceProvider
.GetService<ILogger<ProductService>>() ??
NullLogger<ProductService>.Instance;
}
public void Delete(int id)
{
_productRepository.Delete(id);
_logger.LogInformation($"Deleted a product with id = {id}");
}
}
ProductService
注入了IServiceProvider
,並使用它解析了ProdProductServiService
的依賴關係。如果在使用之前注入容器的話,使用GetRequiredService
方法會拋異常。另一邊,使用GetService
則返回NULL。
當你在構造函數中解析(resolve)依賴服務時,他們隨着服務本身的釋放而釋放,所以你大可不必關係構造函數注入的依賴項的釋放(就像構造函數和屬性注入一樣)。
良好實踐
IServiceProvider
的依賴++)。這意味着在創建服務實例時不能显示的看到服務的依賴項。而這對於單元測試尤其重要,因為你可能想要模擬服務的一些依賴項。在ASP.NET Core依賴注入概念裏面,有三種服務的生命周期:
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊
依賴注入容器會跟蹤所有解析出來的服務,在它們的生命周期結束後會釋放掉這些服務。
IDisposable
接口,在服務被釋放的時候也會自動調用Dispose
方法。良好實踐
在某些場景下,你可能需要在服務的方法中解析另外一個服務。這種情況下請確保在使用服務后及時釋放服務。這才是創建範圍作用域服務的最佳方式。
public class PriceCalculator
{
private readonly IServiceProvider _serviceProvider;
public PriceCalculator(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public float Calculate(Product product, int count,
Type taxStrategyServiceType)
{
using (var scope = _serviceProvider.CreateScope())
{
var taxStrategy = (ITaxStrategy)scope.ServiceProvider
.GetRequiredService(taxStrategyServiceType);
var price = product.Price * count;
return price + taxStrategy.CalculateTax(price);
}
}
}
PriceCalculator
在構造函數里注入了IServiceProvider
並賦值給以只讀字段。然後PriceCalculator
在Calculate
的方法內創建了一個子範圍作用域。使用scope.ServiceProvider
來解析服務依賴,而不是用_serviceProvider
實例。這樣,在子範圍作用域內被解析的所有服務會在using的聲明結束后自動釋放。
良好實踐
單例服務通常為了保持應用程序狀態而設計。緩存是一個應用程序狀態的最好示例。
public class FileService
{
private readonly ConcurrentDictionary<string, byte[]> _cache;
public FileService()
{
_cache = new ConcurrentDictionary<string, byte[]>();
}
public byte[] GetFileContent(string filePath)
{
return _cache.GetOrAdd(filePath, _ =>
{
return File.ReadAllBytes(filePath);
});
}
}
FileService
只是簡單的緩存了文件內容來減少磁盤讀取。像這樣的服務應該設計成單例服務。否則緩存將不能正常工作。
良好實踐
ConcurrentDictionary
而不是Dictionary
來確保線程安全。範圍作用域服務似乎是一個為每個web請求存儲數據的候選方式。因為ASP.NET Core為每一個Web請求都會創建一個服務範圍作用域。因此一個服務註冊成Scoped服務,在Web請求過程可以共享這個服務。
public class RequestItemsService
{
private readonly Dictionary<string, object> _items;
public RequestItemsService()
{
_items = new Dictionary<string, object>();
}
public void Set(string name, object value)
{
_items[name] = value;
}
public object Get(string name)
{
return _items[name];
}
}
如果RequestItemsService
註冊成範圍作用域的服務,並將RequestItemsService
注入到兩個不同的服務中,這兩個服務可以訪問到另外一個服務添加的數據,因為這兩個服務在一個Web請求中是共享RequestItemsService
實例的。
但是,現實情況可能不完全是這樣的。如果你創建了子範圍作用域並在子作用域範圍內解析RequestItemsService
,你會得到一個全新的RequestItemsService
,而這並非我們所期望的那樣。所有Scoped服務並非一個Web請求時共享一個服務實例。
你可能會認為你不會犯這樣明顯的錯誤(在子作用域內解析服務依賴)。但是這不是錯誤(一個常規用法而已)並且情況並沒有那麼簡單。假設在你的服務中有龐大的服務依賴關係,你可能不知道是否有人會這麼做(在子作用域內解析服務依賴)。
良好實踐
HttpContext
(通過IHttpContextAccessor
來訪問它)來存儲每一個Web請求需要存儲的數據,這是安全的處理方式。HttpContext
生命周期並不是Scoped。實際上並沒有注入到依賴注入的容器內(這是為什麼使用IHttpContextAccessor
訪問它而不是注入到容器內的原因)。++在一個Web請求中,HttpContextAccessor使用AsyncLocal
來共享相同的HttpContext++。依賴注入在最初使用的時候好像是挺簡單的。如果不遵循嚴格的使用原則,依然會有潛在的多線程和內存泄漏問題。我在開發ASP.NET Boilerplate框架過程中,基於我的實踐體會分享了這些實踐原則。
在使用ASP.NET Core 依賴注入時需要注意幾項:
- 在依賴關係眾多時,職責單一原則,考慮拆分職責
- 更有利於單元測試。
- 通常我們在設計框架/基類時,可以適當引入屬性注入,這樣可以使得繼承類代碼更簡潔。
- 必要時,屬性提供懶加載方式,提高服務啟動速度。
- Transient服務的生命周期短,可以有效的規避多線程和內存泄漏問題,同時也引起應用程序的內存使用量上升,帶了部分性能問題。
- 在Singleton服務中,禁止依賴Transient/Scoped服務,一方面,Transient/Scoped服務也會變成單例服務。另一方面,Transient/Scoped服務沒有考慮多線程問題。
- 在使用Singleton服務時,多注意潛在的線程安全和內存泄漏問題。
- 在非Web應用場景和子作用服務場景,Scoped服務,並不能正確處理一個線程內共享實例。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
※想知道最厲害的網頁設計公司嚨底家"!
RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌
※推薦評價好的iphone維修中心
擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢
knockout學過的當工具腳本用,就像jquery一樣使用,學習成本15分鐘,沒學過的可學可不學。
knockout 是上古神器,話說在遠古開天闢地,前端到處是飛禽走獸,一片混亂。
這時候人類開始人類開始誕生了,因為惡劣的環境備受煎熬,在生存角逐中,人們通過智慧寫了各種js腳本,進入了石器時代,但是人類只有兩條腿和兩隻手切換工具的速度限制了人類的發展。
這時候John Resig 整理了各種工具,注入熔爐,一件草莽神器誕生了,jquery。人們開始利用jquery,在html上開墾大地,馬力十足,這是一個被jquery奴隸的時代,史稱奴隸時代。
後來人們就發現了一個問題,在html中這塊廣袤的大地上,js不同腳本是衝突的,部落與聯盟之間的戰爭一觸即發。隨着因為衝突,調試繁瑣,js的部落與部落之間在戰爭中,被require.js等模塊管理所統治,不同的部落得到分封,進入了封建時代。
但是幾乎在同一時間,mvvm思想開始萌芽,他們提出有一個假設,如果可以修改數據就能對html產生驅動變化,那麼是不是可以解放生產力?這個實現不斷得到驗證與實際,工業革命誕生了。這是一次沒有流血的革命,因為以前的技術誕生往往充滿着爭議,這個是真的解放人類的雙手,蒸汽時代開始來臨。
knockout 就是蒸汽時代的產物,它是mvvm模式在js實現的前驅,是現在電力時代3大框架的基石。好了,故事模式結束。
首先說明一下什麼是mvvm,它是一種模式,還有一些其他模式比如說mvc,mvp等等。
他們其實是一個重的問題,偏向於哪一塊。
mvc的c很重,那麼它的重點功能在於控制器,可以說是c連接了視圖和model。
mvp的p很重,他們的視圖和model完全分離,中間p的其實相當於c,操作層,但是和mvc不同的是隔離了model層和視圖。比如說window form開發。
mvvm,偏向view,和mvp完全相反,他的視圖和數據層相當緊密,兩者不可分割。knockout就是一個例子,包括現在比較成熟的框架vue。
knockout它的作用就是一個重要功能在於監聽,監聽數據的變化,然後從新部分渲染。
※台北網頁設計公司這麼多該如何選擇?
網動是一群專業、熱情、向前行的工作團隊,我們擁有靈活的組織與溝通的能力,能傾聽客戶聲音,激發創意的火花,呈現完美的作品
那麼開始實踐一下吧:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
}
一個model類,裏面存放這id,name,category,price,對應數據庫。
然後編輯控制器:
public class HomeController : Controller
{
static List<Product> productsList = new List<Product>();
public IActionResult Index()
{
return View();
}
[HttpGet]
public IActionResult products() {
productsList = new List<Product>() {
new Product{Id=1,Category="哈哈",Name="張三",Price=10 },
new Product{Id=2,Category="哈哈",Name="李小二",Price=10 }
};
return Json(productsList);
}
}
這裏面只是提供一些數據:
前台:
html部分
<table id="products">
<thead>
<tr><th>ID</th><th>Name</th><th>Category</th><th>Price</th></tr>
</thead>
<tbody data-bind="foreach: products">
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: name"></td>
<td data-bind="text: category"></td>
<td data-bind="text: price"></td>
</tr>
</tbody>
</table>
js 部分:
function ViewModel() {
var self = this;
//創建綁定
self.products = ko.observableArray(); // 創建數組綁定。
self.product = ko.observable();//單個產品
self.status = ko.observable();//單個錯誤提示
// 得到全部的產品
self.getAll = function () {
self.products.removeAll();
$.getJSON("/Home/products", function (products) {
self.products(products);
});
}
//更新
self.update = function () {
self.status("");
var id = $('#productId').val();
var product = {
Name: $('#name').val(),
Price: $('#price').val(),
Category: $('#category').val()
};
$.ajax({
url: '/Home/products/' + id,
cache: false,
type: 'PUT',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(product),
success: self.getAll
})
.fail(
function (xhr, textStatus, err) {
self.status(err);
});
}
//新增
self.create = function () {
self.status("");
var product = {
Name: $('#name2').val(),
Price: $('#price2').val(),
Category: $('#category2').val()
};
$.ajax({
url: '/Home/products',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(product),
statusCode: {
201 /*Created*/: function (data) {
//得到返回結果然後返回添加添加
self.products.push(data);
}
}
})
.fail(
function (xhr, textStatus, err) {
self.status(err);
});
}
//初始化
self.getAll();
}
$(function () {
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
})
在裏面配置增刪改查即可,裏面配置的方法可以在html這樣寫自動綁定:
<button data-bind="click: $root.create">添加</button>
就會觸發裏面的create 方法。
這裏只是作為一個綁定用例,其實在真正的編輯中是全部綁定的,不會出現這種$(‘#productName’).val();
而是使用:
<input data-bind="value: $root.Name" type="text" title="Name" />
在此就不多複述。
效果:
感覺 knockout 也不是完全過時,小型的開發速率還是非常快的,綁定就完事,源碼也少,vs 編輯器也支持提示。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
※網頁設計最專業,超強功能平台可客製化
窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機。
※超省錢租車方案
商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!
PS:此文章為系列文章,建議從第一篇開始閱讀。
在上面的資源服務器中,通過配置,我們了解到,當我們程序是前後端分離時,在拿着token去獲取資源時,程序會先去調用遠程認證服務器的端點去驗證解析token,這樣毫無疑問,當訪問量過大的時候,對認證服務器的壓力可想而知,所以為了解決上面的問題,我們採用JWT令牌格式,可以優化上面的問題。
令牌採用JWT格式即可解決上邊的問題,用戶認證通過會得到一個JWT令牌,JWT令牌中已經包括了用戶相關的信息,客戶端只需要攜帶JWT訪問資源服務,資源服務根據事先約定的算法自行完成令牌校驗,無需每次都請求認證服務完成授權。
@Configuration
public class TokenConfigure {
private static final String SIGNING_KEY = "dimples";
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
//對稱秘鑰,資源服務器使用該秘鑰來驗證
converter.setSigningKey(SIGNING_KEY);
return converter;
}
}
private TokenStore tokenStore;
private ClientDetailsService clientDetailsService;
private JwtAccessTokenConverter jwtAccessTokenConverter;
//通過構造方法注入
...
/**
* 令牌管理服務
*
* @return TokenServices
*/
@Bean
public AuthorizationServerTokenServices tokenServices() {
DefaultTokenServices services = new DefaultTokenServices();
// 客戶端詳情服務
services.setClientDetailsService(clientDetailsService);
// 支持令牌刷新
services.setSupportRefreshToken(true);
// 令牌存儲策略
services.setTokenStore(tokenStore);
// 配置令牌增強 JWT
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Collections.singletonList(jwtAccessTokenConverter));
services.setTokenEnhancer(tokenEnhancerChain);
// 令牌默認有效期2小時(如果客戶端設置了會覆蓋該值)
services.setAccessTokenValiditySeconds(7200);
// 刷新令牌默認有效期2天
services.setRefreshTokenValiditySeconds(259200);
return services;
}
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
測試結果如下:
可以使用OAuth的/oauth/check_token端點來解析驗證一下該token
但是我們需要明白一點的是,這種令牌還是存儲在內存中的,後期我們如何將其存儲到redis中是我們研究的方向。
當我們使用了JWT令牌以後,由於在JWT令牌中我們存儲了相應的用戶信息和權限,這時我們可以直接在資源服務器中直接去解析對應令牌,就不用每次都去請求認證服務器端點,加大認證服務器的壓力,下面我們開始改造資源服務器:
完整的配置如下:
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class DimplesResourceServerConfigurerAdapter extends ResourceServerConfigurerAdapter {
public static final String RESOURCE_ID = "dimples";
private TokenStore tokenStore;
@Autowired
public DimplesResourceServerConfigurerAdapter(TokenStore tokenStore) {
this.tokenStore = tokenStore;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID)
.tokenServices(tokenService())
.stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
// 配置客戶端權限scope
.antMatchers("/**").access("#oauth2.hasScope('all')")
.and().csrf().disable()
// 關閉session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
然後重啟服務,重新獲取令牌,然後訪問之前的測試接口:
在此處的JWT的配置中,我們獲取的令牌信息還是存在內存中的,這樣不利於我們程序的擴展。那麼我們如何將生產的令牌去存儲到數據庫中或者存儲到redis中呢?請關注後續的文章。
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污
在上面的jwt加密中,我們的JWT簽名是寫死的字符串,可能我們的項目為了安全考慮,需要使用非對稱的加密,我們該怎麼配置呢?
首先獲取加密文件的私鑰和公鑰,需要先安裝安裝OpenSSL工具,參考鏈接【https://blog.csdn.net/qq_39081974/article/details/81059022】
命令行執行:keytool -genkeypair -alias dimples -keyalg RSA -keypass dimples -keystore dimples.jks -storepass dimples
將生成一個名為medical.jks的文件,其中包含我們的密鑰 – 公鑰和私鑰。 還要確保keypass和storepass是一樣的
keytool -list -rfc –keystore dimples.jks | openssl x509 -inform pem -pubkey
或 keytool -importkeystore -srckeystore dimples.jks -destkeystore dimples.jks -deststoretype pkcs12
將其複製到我們的資源服務器 src/main/resources/public.txt 中
/**
* 配置jwt生成token的轉換
* 使用RSA Sign Key 進行加密
*
* @return JwtAccessTokenConverter
*/
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("medical.jks"), "medical".toCharArray());
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setKeyPair(keyStoreKeyFactory.getKeyPair("medical"));
return converter;
}
/**
* 配置jwt生成token的轉換
*
* @return JwtAccessTokenConverter
*/
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
Resource resource = new ClassPathResource("public.txt");
String publicKey;
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
publicKey = bufferedReader.lines().collect(Collectors.joining("\n"));
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setSigningKey(publicKey);
return converter;
}
當我們使用如上的配置獲取Token后,將access_token中的內容複製到https://jwt.io/網站解析下:
可以看到在jwt中只是保存了我們的user_name,那麼我們怎麼去擴展呢?讓其可以保存我們需要的用戶詳細信息,這裡有兩種方案:
public class JWTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
Map<String, Object> info = new HashMap<>();
info.put("other", "hello world");
((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(info);
return oAuth2AccessToken;
}
}
然後在TokenConfigure 中配置該Bean:
@Configuration
public class TokenConfigure {
......
@Bean
public TokenEnhancer tokenEnhancer() {
return new JWTokenEnhancer();
}
}
最後在認證服務器里配置該增強器:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private TokenEnhancer tokenEnhancer;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
.....
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
List<TokenEnhancer> enhancers = new ArrayList<>();
enhancers.add(tokenEnhancer);
enhancers.add(jwtAccessTokenConverter);
enhancerChain.setTokenEnhancers(enhancers);
endpoints.tokenEnhancer(enhancerChain);
}
......
}
比如存入json數據內容作為username的內容。相比較而言,方案二比較簡單還不用破壞UserDetails的結構
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//登錄賬號
System.out.println("username="+username);
//根據賬號去數據庫查詢...
UserDto user = userDao.getUserByUsername(username);
if(user == null){
return null;
}
//查詢用戶權限
List<String> permissions = userDao.findPermissionsByUserId(user.getId());
String[] perarray = new String[permissions.size()];
permissions.toArray(perarray);
//創建userDetails
//這裏將user轉為json,將整體user存入userDetails
String principal = JSON.toJSONString(user);
UserDetails userDetails = User.withUsername(principal).password(user.getPassword()).authorities(perarray).build();
return userDetails;
}
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。
88-20。18萬總結:今天所介紹的這兩個品牌的車型都是目前在自主品牌比較出色的。長安汽車從前幾年發力開始就慢慢顯露實力,悅翔V7是其在緊湊車出色的產品,不僅價格親民,近期推出的1。0T車型更是走在自主品牌的前面。睿騁熱度雖然低了一點,但無論顏值與配置都是相當出色的。
雖然中級車市場一直被合資品牌佔據,但自主品牌肯定不會眼睜睜地看着這塊蛋糕旁落;一旦在緊湊車市場中站穩腳跟,肯定會遇到天花板效應,向上延伸就無可厚非了。既然要跟合資品牌競爭,
※別再煩惱如何寫文案,掌握八大原則!
什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。
就要非常出色的產品力了,自主品牌的配置與性價比優勢仍然要堅持,這樣與緊湊車形成高低搭配才能更好地征戰市場。
吉利家族
緊湊車 帝豪(三廂燃油版)
售價:6.98-10.08萬
中型車 博瑞
售價:11.98-22.98萬
長安家族
緊湊車 悅翔V7
售價:5.99-8.79萬
中型車 睿騁
售價:10.88-20.18萬
總結:今天所介紹的這兩個品牌的車型都是目前在自主品牌比較出色的;長安汽車從前幾年發力開始就慢慢顯露實力,悅翔V7是其在緊湊車出色的產品,不僅價格親民,近期推出的1.0T車型更是走在自主品牌的前面;睿騁熱度雖然低了一點,但無論顏值與配置都是相當出色的。
吉利汽車自從收購了沃爾沃汽車之後就一發不可收拾了,帝豪這款緊湊車就是很好的證明;如今銷量已經突破百萬輛了;性價比與口碑並存;至於被譽為最美自主轎車的博瑞,上市以來就受到消費者的追捧;如今仍然是一車難求就知道這款車型非常出色了。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
※教你寫出一流的銷售文案?
銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!
仿皮縫線、木紋裝飾件以及適當鍍鉻裝飾件的存在營造出一種豪華高檔的氣氛,還有着一個可以調節角度的懸浮式中控屏幕,並且支持Carplay系統。紅色的一鍵啟動按鈕非常注目。動力方面採用的是與前紐北最速前驅王——本田思域 TYpE R同宗的2。
前言
隨着SUV在全球市場的大熱,本田也越發重視中國這個世界最大的汽車市場,先後在中國推出了CR-V、繽智、歌詩圖等車型,其中CR-V是最為成功的SUV,可以說是帶領了中國城市SUV市場的潮流,但是這麼多年過去,CR-V已經沒有過往那種驚艷的感覺,加上本田在中大型SUV上的缺席,本田(中國)為此在中國研發了一款中型SUV,在廣汽本田中它就是廣汽本田冠道。
本田冠道售價為26.98萬-32.98萬,車身尺寸為4816*1942*1669mm,軸距為2820mm,要比起豐田漢蘭達、別克昂科威都要大上一圈,定位是中型SUV。
冠道採用本田的家族式設計,前臉給人的感覺和本田思域有着很多的相似之處,一樣使用了更有科技感的LED大燈,只是橫貫於兩燈之間的鍍鉻中網裝飾條更為粗壯以及進氣格柵面積更大,而日間行車則是被放置在傳統霧燈位置上,在小編眼中感覺這樣的設計有種“汽配城”感覺。但整車前臉給人的感覺是比較厚重,給人一種寬大又不失精緻的感覺。
車身側面可以看到A柱下有着類似進氣口的裝飾件,非常的精緻,車頂使用了懸浮式設計+溜背造型,整體顏值比較高。全系標配的19英寸輪轂加上高高隆起的輪拱,讓冠道增加了一些力量感,加上車頂線條讓人覺得非常動感。
作為一部中型SUV,冠道的尾部卻是非常的精緻,尾燈的造型能讓你想到很多本田的車型。此外冠道還用着的是單邊共雙出的排氣管設計,營造出一種性能上的霸氣。
內飾方面則代表了廣汽本田最高的水平,
※想知道最厲害的網頁設計公司嚨底家"!
RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌
表現出冠道豪華SUV的身份,中控上使用了大量軟質材料,手感以及質感都非常出色。仿皮縫線、木紋裝飾件以及適當鍍鉻裝飾件的存在營造出一種豪華高檔的氣氛,還有着一個可以調節角度的懸浮式中控屏幕,並且支持Carplay系統。
紅色的一鍵啟動按鈕非常注目。
動力方面採用的是與前紐北最速前驅王——本田思域 TYpE R同宗的2.0T渦輪增壓發動機,最大功率200千瓦,最大扭矩370牛米,已經是性能車級別的發動機水平,在競爭對手中處於不敗地位,並且實測油耗能在10L左右,油耗表現非常出色。
變速箱方面採用了和寶馬一個供應商的ZF采埃孚的9AT自動變速箱,該變速箱也有使用在jeep 自由光以及路虎極光上,耐用度有待考驗,不過和它們不同的是本田對它進行了匹配以及換上了更顯檔次的按鈕式电子檔把。
底盤方面,採用了前麥費遜后多連桿式獨立懸架,值得一提的是后懸架下搖臂採用的是成本更高的鋁合金材料,相對於同級車常用的鑄鐵材料來得更強更輕,帶來更直接更佳的駕駛體驗。
配置方面,廣汽本田冠道表現出超高的水平,全系配備了無鑰匙進入、一鍵啟動、自動駐車、19英寸鋁合金輪轂、換擋撥片、定速巡航、座椅電動調節、自動空調、後排獨立空調以及發動機啟停技術等,即使是購買最低配也能滿足一般人的使用需求。高配車型還有抬頭显示,LED大燈,全景天窗、電動後備廂、座椅通風加熱、併線輔助、全景影像、主動剎車、併線輔助、車道偏離預警系統、自動泊車等配置。
對於推薦車型方面,筆者推薦的是次低配的兩驅豪華型,以着1萬的差價就有多了全景天窗、電動後備廂、真皮方向盤、倒車影像、前排座椅加熱、LED大燈、併線輔助等使用功能,性價比非常的高,而單單僅僅是全景天窗、LED大燈兩者相加就遠遠大於了一萬元,性價比不言而喻。而價格更高的四驅版筆者覺得是沒有必要的,城市使用中四驅系統使用的機會微乎其微,只能平白增加油耗以及稍微提高一點性能。而在後期,廣汽本田還會推出價格更低的1.5T車型,門檻更低。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊