日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
SpringBoot一鍵換膚,soeasy!

???

成都創(chuàng)新互聯(lián)公司總部坐落于成都市區(qū),致力網(wǎng)站建設(shè)服務(wù)有網(wǎng)站制作、成都網(wǎng)站制作、網(wǎng)絡(luò)營銷策劃、網(wǎng)頁設(shè)計(jì)、網(wǎng)站維護(hù)、公眾號(hào)搭建、重慶小程序開發(fā)公司、軟件開發(fā)等為企業(yè)提供一整套的信息化建設(shè)解決方案。創(chuàng)造真正意義上的網(wǎng)站建設(shè),為互聯(lián)網(wǎng)品牌在互動(dòng)行銷領(lǐng)域創(chuàng)造價(jià)值而不懈努力!

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

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

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

1.一鍵換膚

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

???

我們來看下這個(gè)需求怎么實(shí)現(xiàn)。

首先三個(gè)按鈕分別對(duì)應(yīng)了三個(gè)不同的樣式,我們先把這三個(gè)不同的樣式定義出來,分別如下:

blue.css:

body{     background-color: #05e1ff; } 

green.css:

body{     background-color: #aaff9c; } 

red.css:

body{     background-color: #ff0721; } 

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

所以接下來我們在 resources 目錄下新建 theme 目錄,然后在 theme 目錄中創(chuàng)建三個(gè)文件,內(nèi)容如下:

blue.properties:

index.body=/css/blue.css 

green.properties:

index.body=/css/green.css 

red.properties:

index.body=/css/red.css 

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

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

                                                                  

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

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

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

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

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

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

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %>       Title     " >   
     一鍵切換主題:
     托帕藍(lán)     多巴胺紅     石竹青 
 
   

最關(guān)鍵的是:

" > 

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

最后再提供一個(gè)處理器,如下:

@GetMapping(path = "/index") public  String getPage(){     return "index"; } 

這個(gè)就很簡單了,沒啥好說的。

最后啟動(dòng)項(xiàng)目進(jìn)行測試,大家就可以看到我們文章一開始給出的圖片了,點(diǎn)擊不同的按鈕就可以實(shí)現(xiàn)背景的切換。

是不是非常 Easy!

2.原理分析

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

先來看下 ThemeResolver 接口:

public interface ThemeResolver {  String resolveThemeName(HttpServletRequest request);  void setThemeName(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName); } 

這個(gè)接口中就兩個(gè)方法:


  • resolveThemeName:從當(dāng)前請求中解析出主題的名字。
  • setThemeName:設(shè)置當(dāng)前主題。

ThemeResolver 主要有三個(gè)實(shí)現(xiàn)類,繼承關(guān)系如下:

???

接下來我們對(duì)這幾個(gè)實(shí)現(xiàn)類來逐個(gè)分析。

2.1 CookieThemeResolver

直接上源碼吧:

@Override public String resolveThemeName(HttpServletRequest request) {  String themeName = (String) request.getAttribute(THEME_REQUEST_ATTRIBUTE_NAME);  if (themeName != null) {   return themeName;  }  String cookieName = getCookieName();  if (cookieName != null) {   Cookie cookie = WebUtils.getCookie(request, cookieName);   if (cookie != null) {    String value = cookie.getValue();    if (StringUtils.hasText(value)) {     themeName = value;    }   }  }  if (themeName == null) {   themeName = getDefaultThemeName();  }  request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName);  return themeName; } @Override public void setThemeName(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {  if (StringUtils.hasText(themeName)) {   request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName);   addCookie(response, themeName);  } else {   request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, getDefaultThemeName());   removeCookie(response);  } } 

先來看 resolveThemeName 方法:


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

再來看 setThemeName 方法:


  • 如果存在 themeName 就進(jìn)行設(shè)置,同時(shí)將 themeName 添加到 Cookie 中。
  • 如果不存在 themeName,就設(shè)置一個(gè)默認(rèn)的主題名,同時(shí)從 response 中移除 Cookie。

可以看到,整個(gè)實(shí)現(xiàn)思路還是非常簡單的。

2.2 AbstractThemeResolver

public abstract class AbstractThemeResolver implements ThemeResolver {  public static final String ORIGINAL_DEFAULT_THEME_NAME = "theme";  private String defaultThemeName = ORIGINAL_DEFAULT_THEME_NAME;  public void setDefaultThemeName(String defaultThemeName) {   this.defaultThemeName = defaultThemeName;  }  public String getDefaultThemeName() {   return this.defaultThemeName;  } } 

AbstractThemeResolver 主要提供了配置默認(rèn)主題的能力。

2.3 FixedThemeResolver

public class FixedThemeResolver extends AbstractThemeResolver {   @Override  public String resolveThemeName(HttpServletRequest request) {   return getDefaultThemeName();  }   @Override  public void setThemeName(    HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {    throw new UnsupportedOperationException("Cannot change theme - use a different theme resolution strategy");  }  } 

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

2.4 SessionThemeResolver

public class SessionThemeResolver extends AbstractThemeResolver {  public static final String THEME_SESSION_ATTRIBUTE_NAME = SessionThemeResolver.class.getName() + ".THEME";  @Override  public String resolveThemeName(HttpServletRequest request) {   String themeName = (String) WebUtils.getSessionAttribute(request, THEME_SESSION_ATTRIBUTE_NAME);   return (themeName != null ? themeName : getDefaultThemeName());  }  @Override  public void setThemeName(    HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {   WebUtils.setSessionAttribute(request, THEME_SESSION_ATTRIBUTE_NAME,     (StringUtils.hasText(themeName) ? themeName : null));  } } 

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

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

不想多說,因?yàn)楹芎唵巍?/p>

2.5 ThemeChangeInterceptor

最后我們再來看一看 ThemeChangeInterceptor 攔截器,這個(gè)攔截器會(huì)自動(dòng)從請求中提取出主題參數(shù),并設(shè)置到請求中,核心部分在 preHandle 方法中:

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

從請求中提取出 theme 參數(shù),并設(shè)置到 themeResolver 中。

3.小結(jié)

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


文章標(biāo)題:SpringBoot一鍵換膚,soeasy!
網(wǎng)站URL:http://www.dlmjj.cn/article/dpcddej.html