环境:Spring4 + Jdk1.8
模板:Thymeleaf(ver 3),FreeMarker(ver 2.3),Beetl(2.7)
注意:除了 Thymeleaf 需要依赖包(下载的Thymeleaf 包里面自带有),其他两个不需要。
===========================================================
Spring MVC基本配置:
RootConfig.java
/**
* 非 Web 组件配置类
* conf/system.properties 系统相关的配置文件,这儿主要是为了切换模板用。
* 不需要切换模板的可以去掉 @PropertySource("classpath:conf/system.properties")
*/
@Configuration
@PropertySource("classpath:conf/system.properties")
@ComponentScan(basePackages = { "app" },
excludeFilters = {
@Filter( type = FilterType.ANNOTATION, value = EnableWebMvc.class)
})
public class RootConfig {
}
system.properties(不需要就不配置)
# 支持的模板
web.theme = Thymeleaf, FreeMarker, Beetl
# 启用的模板,必须在 web.theme 定义的范围内
web.theme.active = beetl
WebConfig.java
/**
* Web Spring 配置类
* 这儿导入模板的配置文件,根据模板配置文件中的注解判断应该导入哪个
*/
@Configurable
@EnableWebMvc
@Import({FreeMarkerConfig.class, ThymeleafConfig.class, BeeTemplateConfig.class, JspViewConfig.class})
@ComponentScan(basePackages = { "app.web" })
public class WebConfig extends WebMvcConfigurerAdapter {
}
WebAppInitializer.java
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
public static final String CHARACTER_ENCODING = "UTF-8";
@Override
protected Class>[] getRootConfigClasses() {
return new Class>[] { RootConfig.class };
}
@Override
protected Class>[] getServletConfigClasses() {
return new Class>[] { WebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected Filter[] getServletFilters() {
final CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding(CHARACTER_ENCODING);
encodingFilter.setForceEncoding(true);
return new Filter[] { encodingFilter };
}
}
==============================================================
模板配置类:
/**
* Jsp 视图配置类,@ThemeActive 这个是自己定义的注解,不需要切换可以去掉
*
* 注解 @ThemeActive 表示该文件是 jsp模板视图的配置文件,作为默认视图
* 当属性文件中 web.theme.active 的值无效时,该配置启用生效
*/
@Configuration
@ThemeActive(value = "jsp", defaultActive = true)
public class JspViewConfig {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
// 模板位置
resolver.setPrefix("/WEB-INF/templates/jsp/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
}
/**
* 建议自己查看 Thymeleaf 官方的文档说明,很全面,这儿只是基础配置
* 只是这儿要注意要设置两处的编码
*
* 注解 @ThemeActive 表示该文件是 Thymeleaf 模板的配置文件
* 当属性文件中 web.theme.active = Thymeleaf 时启用生效
*/
@Configuration
@ThemeActive("Thymeleaf")
public class ThymeleafConfig {
@Bean
public SpringResourceTemplateResolver templateResolver(){
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
// 模板位置
templateResolver.setPrefix("/WEB-INF/templates/thymeleaf/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
// 设置编码,否则中文乱码
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setCacheable(true);
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine(SpringResourceTemplateResolver templateResolver){
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Bean
public ThymeleafViewResolver viewResolver(SpringTemplateEngine templateEngine) {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine);
// 设置编码,否则中文乱码
viewResolver.setCharacterEncoding("UTF-8");
return viewResolver;
}
}
/**
* 注意设置编码
*
* 注解 @ThemeActive 表示该文件是 FreeMarker 模板的配置文件
* 当属性文件中 web.theme.active = FreeMarker 时启用生效
*/
@Configuration
@ThemeActive("FreeMarker")
public class FreeMarkerConfig {
@Bean
public FreeMarkerViewResolver freemarkerViewResolver() {
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
// 设置编码,否则中文乱码
resolver.setContentType("text/html;charset=UTF-8");
resolver.setCache(true);
resolver.setPrefix("");
resolver.setSuffix(".ftl");
return resolver;
}
@Bean
public FreeMarkerConfigurer freemarkerConfig() {
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
// 设置编码,否则中文乱码
freeMarkerConfigurer.setDefaultEncoding("UTF-8");
freeMarkerConfigurer.setTemplateLoaderPath("/WEB-INF/templates/freemarker/");
return freeMarkerConfigurer;
}
}
/**
* 注意 beetl 模板默认位置在网站根目录,如更改有两个配置方式:
* 1、在配置文件中配置,需要传入配置文件位置
* 2、直接 setRoot 配置模板位置
*
* 注解 @ThemeActive 表示该文件是 beetl 模板的配置文件
* 当属性文件中 web.theme.active = beetl 时启用生效
*/
@Configuration
@ThemeActive("beetl")
public class BeeTemplateConfig {
@Bean(initMethod = "init")
public BeetlGroupUtilConfiguration beetlConfig() {
BeetlGroupUtilConfiguration beetlGroupUtilConfiguration = new BeetlGroupUtilConfiguration();
// 如果需要配置 beetl 相关功能,就传入beetl的配置文件
// 模板的位置就在 beetl.properties 中配置
// 如 RESOURCE.root=/WEB-INF/templates/beetl/
beetlGroupUtilConfiguration.setConfigFileResource(new ClassPathResource("conf/beetl.properties"));
// 或简单的方式就是使用默认配置文件,用下面的代码设置模板位置
//beetlGroupUtilConfiguration.setRoot("/WEB-INF/templates/beetl/");
return beetlGroupUtilConfiguration;
}
@Bean
public BeetlSpringViewResolver beetlViewResolver(BeetlGroupUtilConfiguration beetlConfig) {
BeetlSpringViewResolver beetlSpringViewResolver = new BeetlSpringViewResolver();
// 设置编码
beetlSpringViewResolver.setContentType("text/html;charset=UTF-8");
beetlSpringViewResolver.setSuffix(".btl");
beetlSpringViewResolver.setConfig(beetlConfig);
return beetlSpringViewResolver;
}
}
#conf/beetl.properties
RESOURCE.root=/WEB-INF/templates/beetl/
==============================================================
@ThemeActive 注解,不需要切换模板视图的不需要设置,在代码中去掉该注解
/**
* 是否启用模板,定义在 ThemeActiveConditional 中
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Conditional(ThemeActiveConditional.class)
public @interface ThemeActive {
// 指定该配置属于哪个模板
String value();
// 指定是否默认模板
boolean defaultActive() default false;
}
/**
* 决定启用哪个模板配置
*
* 如果 web.theme.active 定义的值不在 web.theme 范围内,就启用默认模板(defaultActive = true);
* 否则启用注解 value 的值等于 web.theme.active 值的模板配置
*/
public class ThemeActiveConditional implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
Map attributes = metadata.getAnnotationAttributes(ThemeActive.class.getName());
// 获取该配置模板名称
String themeName = (String) attributes.get("value");
// 是否默认模板
boolean isDefault = (boolean) attributes.get("defaultActive");
// 启用的模板,在配置文件中设置 web.theme.active
String themeActiveFromProps = env.getProperty("web.theme.active", "");
// 获取定义的模板,在配置文件 web.theme 中
String[] themesFromProps = env.getProperty("web.theme").split(",");
// 启用的模板是否在定义模板范围内
boolean valid = isDefined(themesFromProps, themeActiveFromProps);
return !valid && isDefault || valid && themeActiveFromProps.equalsIgnoreCase(themeName);
}
private boolean isDefined(String[] themes, String findTheme) {
for(String theme : themes) {
if(theme.trim().equalsIgnoreCase(findTheme.trim())) return true;
}
return false;
}
}
===============================================================
测试代码:
/**
* Test
*/
public class Account {
private int id;
private String displayName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
}
@Controller
public class ThemeRunController {
@ModelAttribute("account")
public Account adminAccount() {
Account user = new Account();
user.setDisplayName("测试用户");
return user;
}
@RequestMapping(value = "/test", method = GET)
public String index() {
return "index";
}
}
模板文件:(/WEB-INF/templates/)
FreeMarker:index.ftl
测试 FreeMarkerFreeMarker 欢迎 ${account.displayName}
Thymeleaf:index.html (注意空间命名)
测试 thymeleafthymeleaf 欢迎 默认文本
beetl:index.btl
测试 BeetlBeetl 欢迎 ${account.displayName} !
JSP:index.jsp
测试 JSPJSP 欢迎
==========================================================
root
|---- src/
| |----- conf/
| | |------ system.properties
| | |------ beetl.properties
| |----- app/
| | |------ config/
| | | |------ RootConfig.java
| | | |------ WebAppInitializer.java
| | |------ web/
| | | |------ config/
| | | | |------ BeeTemplateConfig.java
| | | | |------ FreeMarkerConfig.java
| | | | |------ JspViewConfig.java
| | | | |------ ThymeleafConfig.java
| | | | |------ WebConfig.java
| | | |------ annotation/
| | | | |------ ThemeActive.java
| | | |------ condition/
| | | | |------ ThemeActiveConditional.java
| | | |------ domain/
| | | | |------ Account.java
| | | |------ controller/
| | | | |------ ThemeRunController.java
|---- web/
| |----- WEB-INF/
| | |------ templates/
| | | |------ beetl/
| | | | |------ index.btl
| | | |------ freemarker/
| | | | |------ index.ftl
| | | |------ thymeleaf/
| | | | |------ index.html
| | | |------ jsp/
| | | | |------ index.jsp
写下来,做备份,就是怕以后忘记了!