一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring Boot一鍵換膚,so easy!

Spring Boot一鍵換膚,so easy!

2021-04-24 01:09江南一點雨 Java教程

Theme,就是主題,點一下就給網站更換一個主題,相信大家都用過類似功能,這個其實和前面所說的國際化功能很像,代碼其實也很像,今天我們就來捋一捋Spring Boot一鍵換膚功能的實現方法

Spring Boot一鍵換膚,so easy!

SpringMVC 源碼分析系列最后一篇,和大家聊一聊 Theme。

Theme,就是主題,點一下就給網站更換一個主題,相信大家都用過類似功能,這個其實和前面所說的國際化功能很像,代碼其實也很像,今天我們就來捋一捋。

考慮到有的小伙伴可能還沒用過 Theme,所以這里松哥先來說下用法,然后我們再進行源碼分析。

1.一鍵換膚

來做一個簡單的需求,假設我的頁面上有三個按鈕,點擊之后就能一鍵換膚,像下面這樣:

Spring Boot一鍵換膚,so easy!

我們來看下這個需求怎么實現。

首先三個按鈕分別對應了三個不同的樣式,我們先把這三個不同的樣式定義出來,分別如下:

blue.css:

  1. body{ 
  2.     background-color: #05e1ff; 

green.css:

  1. body{ 
  2.     background-color: #aaff9c; 

red.css:

  1. body{ 
  2.     background-color: #ff0721; 

主題的定義,往往是一組樣式,因此我們一般都是在一個 properties 文件中將同一主題的樣式配置在一起,這樣方便后期加載。

所以接下來我們在 resources 目錄下新建 theme 目錄,然后在 theme 目錄中創建三個文件,內容如下:

blue.properties:

  1. index.body=/css/blue.css 

green.properties:

  1. index.body=/css/green.css 

red.properties:

  1. index.body=/css/red.css 

在不同的 properties 配置文件中引入不同的樣式,但是樣式定義的 key 都是 index.body,這樣方便后期在頁面中引入。

接下來在 SpringMVC 容器中配置三個 Bean,如下:

  1. <mvc:interceptors> 
  2.     <mvc:interceptor> 
  3.         <mvc:mapping path="/**"/> 
  4.         <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"
  5.             <property name="paramName" value="theme"/> 
  6.         </bean> 
  7.     </mvc:interceptor> 
  8. </mvc:interceptors> 
  9. <bean id="themeSource" class="org.springframework.ui.context.support.ResourceBundleThemeSource"
  10.     <property name="basenamePrefix" value="theme."/> 
  11. </bean> 
  12. <bean id="themeResolver" class="org.springframework.web.servlet.theme.SessionThemeResolver"
  13.     <property name="defaultThemeName" value="blue"/> 
  14. </bean> 

 

 

 

 

 

首先配置攔截器 ThemeChangeInterceptor,這個攔截器用來解析主題參數,參數的 key 為 theme,例如請求地址是 /index?theme=blue,該攔截器就會自動設置系統主題為 blue。當然也可以不配置攔截器,如果不配置的話,就可以單獨提供一個修改主題的接口,然后手動修改主題,類似下面這樣:

  1. @Autowired 
  2. private ThemeResolver themeResolver; 
  3. @RequestMapping(path = "/01/{theme}",method = RequestMethod.GET) 
  4. public String theme1(@PathVariable("theme") String themeStr, HttpServletRequest request, HttpServletResponse response){ 
  5.     themeResolver.setThemeName(request,response, themeStr); 
  6.     return "redirect:/01"

themeStr 就是新的主題名稱,將其配置給 themeResolver 即可。

接下來配置 ResourceBundleThemeSource,這個 Bean 主要是為了加載主題文件,需要配置一個 basenamePrefix 屬性,如果我們的主題文件放在文件夾中,這個 basenamePrefix 的值就是 文件夾名稱.。

接下來配置主題解析器,主題解析器有三種,分別是 CookieThemeResolver、FixedThemeResolver、SessionThemeResolver,這里我們使用的是 SessionThemeResolver,主題信息將被保存在 Session 中,只要 Session 不變,主題就一直有效。這三個主題解析器松哥會在下一小節中和大家仔細分析。

配置完成后,我們再來提供一個測試頁面,如下:

  1. <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> 
  2. <%@ page contentType="text/html;charset=UTF-8" language="java" %> 
  3. <html> 
  4. <head> 
  5.     <title>Title</title> 
  6.     <link rel="stylesheet" href="<spring:theme code="index.body" />" > 
  7. </head> 
  8. <body> 
  9. <div> 
  10.     一鍵切換主題:<br/> 
  11.     <a href="/index?theme=blue">托帕藍</a> 
  12.     <a href="/index?theme=red">多巴胺紅</a> 
  13.     <a href="/index?theme=green">石竹青</a> 
  14. </div> 
  15. <br/> 
  16. </body> 
  17. </html> 

最關鍵的是:

  1. <link rel="stylesheet" href="<spring:theme code="index.body" />" > 

css 樣式不直接寫,而是引用我們在 properties 文件中定義的 index.body,這樣將根據當前主題加載不同的 css 文件。

最后再提供一個處理器,如下:

  1. @GetMapping(path = "/index"
  2. public  String getPage(){ 
  3.     return "index"

這個就很簡單了,沒啥好說的。

最后啟動項目進行測試,大家就可以看到我們文章一開始給出的圖片了,點擊不同的按鈕就可以實現背景的切換。

是不是非常 Easy!

2.原理分析

主題這塊涉及到的東西主要就是主題解析器,主題解析器和我們前面所說的國際化的解析器非常類似,但是比它更簡單,我們一起來分析下。

先來看下 ThemeResolver 接口:

  1. public interface ThemeResolver { 
  2.  String resolveThemeName(HttpServletRequest request); 
  3.  void setThemeName(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName); 

這個接口中就兩個方法:

  • resolveThemeName:從當前請求中解析出主題的名字。
  • setThemeName:設置當前主題。

ThemeResolver 主要有三個實現類,繼承關系如下:

Spring Boot一鍵換膚,so easy!

接下來我們對這幾個實現類來逐個分析。

2.1 CookieThemeResolver

直接上源碼吧:

  1. @Override 
  2. public String resolveThemeName(HttpServletRequest request) { 
  3.  String themeName = (String) request.getAttribute(THEME_REQUEST_ATTRIBUTE_NAME); 
  4.  if (themeName != null) { 
  5.   return themeName; 
  6.  } 
  7.  String cookieName = getCookieName(); 
  8.  if (cookieName != null) { 
  9.   Cookie cookie = WebUtils.getCookie(request, cookieName); 
  10.   if (cookie != null) { 
  11.    String value = cookie.getValue(); 
  12.    if (StringUtils.hasText(value)) { 
  13.     themeName = value; 
  14.    } 
  15.   } 
  16.  } 
  17.  if (themeName == null) { 
  18.   themeName = getDefaultThemeName(); 
  19.  } 
  20.  request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName); 
  21.  return themeName; 
  22. @Override 
  23. public void setThemeName(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) { 
  24.  if (StringUtils.hasText(themeName)) { 
  25.   request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName); 
  26.   addCookie(response, themeName); 
  27.  } else { 
  28.   request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, getDefaultThemeName()); 
  29.   removeCookie(response); 
  30.  } 

先來看 resolveThemeName 方法:

  • 首先會嘗試直接從請求中獲取主題名稱,如果獲取到了,就直接返回。
  • 如果第一步沒有獲取到主題名稱,接下來就嘗試從 Cookie 中獲取主題名稱,Cookie 也是從當前請求中提取,利用 WebUtils 工具進行解析,如果解析到了主題名稱,就賦值給 themeName 變量。
  • 如果前面沒有獲取到主題名稱,就使用默認的主題名稱,開發者可以自行配置默認的主題名稱,如果不配置,就是 theme。
  • 將解析出來的 theme 保存到 request 中,以備后續使用。

再來看 setThemeName 方法:

  • 如果存在 themeName 就進行設置,同時將 themeName 添加到 Cookie 中。
  • 如果不存在 themeName,就設置一個默認的主題名,同時從 response 中移除 Cookie。

可以看到,整個實現思路還是非常簡單的。

2.2 AbstractThemeResolver

  1. public abstract class AbstractThemeResolver implements ThemeResolver { 
  2.  public static final String ORIGINAL_DEFAULT_THEME_NAME = "theme"
  3.  private String defaultThemeName = ORIGINAL_DEFAULT_THEME_NAME; 
  4.  public void setDefaultThemeName(String defaultThemeName) { 
  5.   this.defaultThemeName = defaultThemeName; 
  6.  } 
  7.  public String getDefaultThemeName() { 
  8.   return this.defaultThemeName; 
  9.  } 

AbstractThemeResolver 主要提供了配置默認主題的能力。

2.3 FixedThemeResolver

  1. public class FixedThemeResolver extends AbstractThemeResolver { 
  2.  
  3.  @Override 
  4.  public String resolveThemeName(HttpServletRequest request) { 
  5.   return getDefaultThemeName(); 
  6.  } 
  7.  
  8.  @Override 
  9.  public void setThemeName( 
  10.    HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) { 
  11.  
  12.   throw new UnsupportedOperationException("Cannot change theme - use a different theme resolution strategy"); 
  13.  } 
  14.  

FixedThemeResolver 就是使用默認的主題名稱,并且不允許修改主題。

2.4 SessionThemeResolver

  1. public class SessionThemeResolver extends AbstractThemeResolver { 
  2.  public static final String THEME_SESSION_ATTRIBUTE_NAME = SessionThemeResolver.class.getName() + ".THEME"
  3.  @Override 
  4.  public String resolveThemeName(HttpServletRequest request) { 
  5.   String themeName = (String) WebUtils.getSessionAttribute(request, THEME_SESSION_ATTRIBUTE_NAME); 
  6.   return (themeName != null ? themeName : getDefaultThemeName()); 
  7.  } 
  8.  @Override 
  9.  public void setThemeName( 
  10.    HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) { 
  11.   WebUtils.setSessionAttribute(request, THEME_SESSION_ATTRIBUTE_NAME, 
  12.     (StringUtils.hasText(themeName) ? themeName : null)); 
  13.  } 

resolveThemeName:從 session 中取出主題名稱并返回,如果 session 中的主題名稱為 null,就返回默認的主題名稱。

setThemeName:將主題配置到請求中。

不想多說,因為很簡單。

2.5 ThemeChangeInterceptor

最后我們再來看一看 ThemeChangeInterceptor 攔截器,這個攔截器會自動從請求中提取出主題參數,并設置到請求中,核心部分在 preHandle 方法中:

  1. @Override 
  2. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
  3.   throws ServletException { 
  4.  String newTheme = request.getParameter(this.paramName); 
  5.  if (newTheme != null) { 
  6.   ThemeResolver themeResolver = RequestContextUtils.getThemeResolver(request); 
  7.   if (themeResolver == null) { 
  8.    throw new IllegalStateException("No ThemeResolver found: not in a DispatcherServlet request?"); 
  9.   } 
  10.   themeResolver.setThemeName(request, response, newTheme); 
  11.  } 
  12.  return true

從請求中提取出 theme 參數,并設置到 themeResolver 中。

3.小結

好啦,這就是今天和小伙伴們分享的一鍵換膚!無論是功能性還是源碼,都和國際化非常類似,但是比國際化簡單很多,不知道小伙伴們有沒有 GET 到呢?

原文地址:https://mp.weixin.qq.com/s/epVIGcCAZdW3vS80XG_duQ

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久青草国产观看在线视频 | 成人α片 | 欧美最猛性xxxxx男男 | 清纯漂亮女友初尝性过程 | 亚洲AV久久无码精品九号软件 | 97啪啪| 亚洲理论视频 | 精品国产免费第一区二区三区日韩 | 亚洲精品国产一区二区第一页 | 国产精品xxxav免费视频 | 亚洲AV 日韩 国产 有码 | 美女国内精品自产拍在线播放 | sao虎在线精品永久 s0e一923春菜花在线播放 | 亚洲国产精品久久无套麻豆 | 国产成人高清精品免费5388密 | 性福演算法 | 韩国伊人 | 免费观看在线永久免费xx视频 | 欧美夜夜精品一级爽 | 亚洲 欧美 国产 综合久久 | 爱福利一区二区 | 小鸟酱喷水 | 四虎国产视频 | 午夜无码片在线观看影院 | 久久精品免视看国产 | 国产拍拍 | 亚洲欧美日韩精品 | 日韩精品成人 | 草久热| 欧美亚洲一区二区三区在线 | 婷婷精品进入 | 色噜噜亚洲男人的天堂www | 日本护士xxxx视频 | 亚洲福利天堂网福利在线观看 | 久久re这里精品在线视频7 | 国产日本久久久久久久久婷婷 | 免费一级毛片在线播放放视频 | 毛片群 | chinaese中国女人厕所小便 | 亚洲AV蜜桃永久无码精品红樱桃 | 国产91精选在线观看麻豆 |