Theme, click to change a theme for the site, I believe we have used a similar function, this is actually very similar to the internationalization function, the code is actually very similar, today we will run through it.
Considering that some of you may not have used Theme yet, let’s talk about the usage here first, and then we will do the source code analysis.
1. One click to switch themes
Let’s do a simple requirement, suppose I have three buttons on the page, after clicking on them, I can switch themes with one click, like the following.
blue.css:
green.css:
red.css:
The definition of a theme is often a set of styles, so we generally configure the styles of the same theme together in a properties file, which makes it easier to load later.
So next we create a new theme directory in the resources directory, and then create three files in the theme directory with the following contents.
blue.properties:
|
|
green.properties:
|
|
red.properties:
|
|
Introduce different styles in different properties configuration files, but the key of the style definition is index.body, so that it is convenient to introduce in the page later.
Next, configure the three beans in the SpringMVC container as follows.
|
|
-
First configure the interceptor ThemeChangeInterceptor, this interceptor is used to parse the theme parameter, the key of the parameter is theme, for example, the request address is
/index?theme=blue
, the interceptor will automatically set the system theme to blue. Provide an interface to modify the theme, and then manually modify the theme, similar to the following.1 2 3 4 5 6 7
@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 is the new theme name, just configure it to themeResolver.
-
Next configure ResourceBundleThemeSource, this bean is mainly for loading theme files, you need to configure a basenamePrefix property, if our theme files are placed in a folder, the value of this basenamePrefix is
folderName
. -
There are three kinds of theme resolvers, namely CookieThemeResolver, FixedThemeResolver, SessionThemeResolver, here we use SessionThemeResolver, the theme information will be saved in Session As long as the Session does not change, the theme will always be valid.These three theme resolvers will be carefully analyzed in the next subsection.
Once the configuration is complete, we will then provide a test page, as follows.
|
|
The most critical point is.
|
|
The css styles are not written directly, but refer to the index.body we defined in the properties file, so that a different css file will be loaded depending on the current theme.
Finally a handler is provided, as follows.
This one is very simple, nothing more to say.
Finally start the project for testing, you can see the picture given at the beginning of our article, click on the different buttons to achieve the background switch.
Is it very easy!
2. Principle analysis
The main thing involved in this piece of theme is the theme resolver, which is very similar to the internationalized resolver we mentioned earlier, but simpler than it, so let’s analyze it together.
First, let’s look at the ThemeResolver interface.
There are just two methods in this interface.
- resolveThemeName: resolve the name of the theme from the current request.
- setThemeName: Set the current theme.
ThemeResolver has three main implementation classes with the following inheritance relationships.
Let’s analyze these implementation classes one by one.
2.1 CookieThemeResolver
Let’s go straight to the source code.
|
|
Let’s start with the resolveThemeName method.
- First it tries to get the theme name directly from the request, if it gets it, it returns it directly.
- If the theme name is not retrieved in the first step, then it will try to get the theme name from the cookie, which is also extracted from the current request and parsed using WebUtils tool.
- If the theme name is not retrieved, the default theme name is used, and the developer can configure the default theme name, if not, it is theme.
- Save the parsed theme to the request for subsequent use.
Let’s look at the setThemeName method.
- If themeName exists, set it, and add themeName to the cookie.
- If themeName does not exist, set a default theme name and remove the cookie from the response.
As you can see, the whole idea is very simple.
2.2 AbstractThemeResolver
|
|
AbstractThemeResolver mainly provides the ability to configure the default theme.
2.3 FixedThemeResolver
|
|
FixedThemeResolver just uses the default theme name and doesn’t allow to modify the theme.
2.4 SessionThemeResolver
|
|
- resolveThemeName: retrieve the theme name from the session and return it, or return the default theme name if the theme name in the session is null.
- setThemeName: configure the theme into the request.
Don’t want to say more because it’s simple.
2.5 ThemeChangeInterceptor
Finally, let’s take a look at the ThemeChangeInterceptor interceptor, which automatically extracts the theme parameters from the request and sets them to the request, with the core part in the preHandle method.
|
|
Extracts the theme parameter from the request and sets it to the themeResolver.