一、简介
最近写了一个项目,然后想利用TemplateEngine实现thymeleaf的手动渲染,将生成的html页面加入Redis缓存,提高项目访问速度。
二、SpringBoot 1.x实现
以前使用的maven版本如下所示:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
可以看出是springboot1.x版本。
附上该版本thymeleaf手动渲染的实现。
@RequestMapping(value = "/to_list", produces = "text/html")
@ResponseBody
public String toGoods(Model model, MiaoshaUser user,
final HttpServletRequest request,
final HttpServletResponse response) {
//取缓存
String html;
html = redisService.get(GoodsKey.getGoodsList(), "", String.class);
if (html != null) {//如果缓存有这个页面
return html;
} else {//如果没有这个页面
//访问数据库获取商品数据
List<GoodsVo> goodsList = goodsService.listGoodsVo();
if (user != null) {
//如果有用户信息,则保存在Model中
model.addAttribute("user", user);
}
//将商品数据保存在Model中
model.addAttribute("goodsList", goodsList);
//手动渲染
SpringWebContext springWebContext = new SpringWebContext(request, response, request.getServletContext(), request.getLocale(), model.asMap(), context);
html = viewResolver.getTemplateEngine().process("goods_list", springWebContext);
if (!StringUtils.isEmpty(html)) {
//保存到缓存
redisService.set(GoodsKey.getGoodsList(), "", html);
}
//返回到浏览器
return html;
}
}
需要依赖两个类:ThymeleafViewResolver以及ApplicationContext
这两个类都可以通过Spring容器注入进去,如下所示:
@Autowired
private ThymeleafViewResolver viewResolver;
@Autowired
private ApplicationContext context;
将上面手动渲染流程代码抽离出来,使用模版如下:
//首先创建一个上下文容器,context是Spring的ApplicationContext
SpringWebContext springWebContext = new SpringWebContext(request, response, request.getServletContext(), request.getLocale(), model.asMap(), context);
//获取模版引擎,进行使用process方法解析
//第一个参数"goods_list"指需要解析的thymeleaf模版,一般在template目录下
//第二个参数就是上下文容器
html = viewResolver.getTemplateEngine().process("goods_list", springWebContext);
if (!StringUtils.isEmpty(html)) {
//保存到缓存
redisService.set(GoodsKey.getGoodsList(), "", html);
}
//返回到浏览器
return html;
三、Springboot 2.x实现
pom.xml如下所示:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.17.RELEASE</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
首先如果直接使用上面的方式,会发现找不到SpringWebContext这个类,这个类是Spring4下的,在Spring5如移除掉了。
那么我们可以使用其他的类进行代替。
1. 第一个是Context
这个是很多博主使用的方式,我最初也采用了这种,这种文章比较多,博主就不再演示了。
当页面在渲染@{}标签时,就会报错,如下所示:
Caused by: org.attoparser.ParseException: Link base “/css/global.css” cannot be context relative (/…) unless the context used for executing the engine implements the org.thymeleaf.context.IWebContext interface (template: “/mail/activation” - line 6, col 25)
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Link base “/css/global.css” cannot be context relative (/…) unless the context used for executing the engine implements the org.thymeleaf.context.IWebContext interface (template: “/mail/activation” - line 6, col 25)
这个是因为没有使用IWebContext 的接口容器所导致
2. 第二个是WebContext类
使用方式如下:
IWebContext webContext = new WebContext(request,response,request.getServletContext(),response.getLocale(),model.asMap());
String cacheHtml = templateEngine.process("/index", webContext);
此时就不会报错,相比Spring4或者Springboot1.x而言,剔除了ApplicationContext 过多的依赖,现在thymeleaf渲染不再过多依赖spring容器