Spring MVC Theme Switcher Example
In this tutorial we build a Spring MVC theme. You can apply a Spring MVC theme to set the overall look-and-feel of your web application. A theme is a collection of static resources like images, stylesheets etc.., that affect the look and feel of an application.
Project Structure
Make sure your project looks similar to the following structure.
src
|--main
| +--java
| +--com
| +--memorynotfound
| +--config
| |--ServletInitializer.java
| |--WebConfig.java
| +--controller
| |--HomeController.java
| +--resources
| +--themes
| |--bright.properties
| |--dark.properties
| +--webapp
| +--themes
| |--bright.css
| |--dark.css
| +--WEB-INF
| +--views
| |--index.jsp
pom.xml
Create Theme Files
A Spring MVC theme is a collection of static resources like images and stylesheets. We can optionally also add differentn properties to each theme. Below, we are creating two themes, one called bright and the other called dark.
Add the bright.properties file to the src/main/resources/themes folder.
stylesheet=themes/bright.css
Add the dark.properties file to the src/main/resources/themes folder.
stylesheet=themes/dark.css
Configure Spring MVC Theme Switcher
Because we are serving static resources, we need to add a ResourceHandler
. This resource handler will handle static resources from the theme folder. Optionally we can also add caching rules to these resources.
Next, we register a ResourceBundleThemeSource
, which is responsible for locating the themes. By setting the basenamePrefix, we can prefix the themes. The dot after the name indicates that this is a directory.
The CookieThemeResolver
uses a cookie to select the theme, with fallback to the default theme.
The ThemeChangeInterceptor
allows for changing the current theme on every request, via a configurable request parameter.
package com.memorynotfound.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.ui.context.support.ResourceBundleThemeSource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.theme.CookieThemeResolver;
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
@EnableWebMvc
@Configuration
@ComponentScan({"com.memorynotfound"})
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/themes/**").addResourceLocations("/themes/");
}
@Bean
public ResourceBundleThemeSource themeSource(){
ResourceBundleThemeSource themeSource = new ResourceBundleThemeSource();
themeSource.setDefaultEncoding("UTF-8");
themeSource.setBasenamePrefix("themes.");
return themeSource;
}
@Bean
public CookieThemeResolver themeResolver(){
CookieThemeResolver resolver = new CookieThemeResolver();
resolver.setDefaultThemeName("bright");
resolver.setCookieName("my-theme-cookie");
return resolver;
}
@Bean
public ThemeChangeInterceptor themeChangeInterceptor(){
ThemeChangeInterceptor interceptor = new ThemeChangeInterceptor();
interceptor.setParamName("theme");
return interceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(themeChangeInterceptor());
}
@Bean
public InternalResourceViewResolver viewResolver(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
You can find the equivallent Spring MVC theme configuration below.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd ">
<mvc:annotation-driven />
<context:component-scan base-package="com.memorynotfound" />
<mvc:resources mapping="/themes/**" location="/themes/"/>
<bean id="themeSource" class="org.springframework.ui.context.support.ResourceBundleThemeSource">
<property name="basenamePrefix" value="themes."/>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
<bean id="themeResolver" class="org.springframework.web.servlet.theme.CookieThemeResolver">
<property name="defaultThemeName" value="bright"/>
<property name="cookieName" value="my-theme-cookie"/>
</bean>
<mvc:interceptors>
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor">
<property name="paramName" value="theme"/>
</bean>
</mvc:interceptors>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
Creating the Stylesheets
We use a different stylesheet for every theme. The location of the stylesheet is registered in the properties file of the theme.
Add the bright.css file to the src/main/webapp/themes directory.
body {
color: blue;
background-color: white;
}
Add the dark.css file to the src/main/webapp/themes directory.
body {
color: white;
background-color: black;
}
Spring MVC Theme Switcher Example
This page includes two links to simply switch between different themes. The themes are included using the <spring:theme/>
element. This elements will display the current theme.
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<html>
<head>
<link rel="stylesheet" href="<spring:theme code='stylesheet'/>" type="text/css" />
<title>Spring MVC ThemeResolver Example</title>
</head>
<body>
<h3>Spring MVC ThemeResolver Example</h3>
theme: <a href="?theme=bright">bright</a> | <a href="?theme=dark">dark</a>
</body>
</html>
Demo
URL: http://localhost:8081/spring-mvc-theme/?theme=bright
URL: http://localhost:8081/spring-mvc-theme/?theme=dark
If you inspect the cookies, you can find the my-theme-cookie
with the correct value of the current theme.
References
- Spring MVC ThemeResolvers
- ResourceBundleThemeSource JavaDoc
- CookieThemeResolver JavaDoc
- ThemeChangeInterceptor JavaDoc
This tutorial actually got me to a working prototype. Thank you very much.