springboot配thymeleaf资源加载问题

问题背景

最近开发一个新的系统,web 这一块使用 thymeleaf 遇到了一些资源加载相关的问题。

问题 1:thymeleaf 无法正常渲染 index.html

thymeleaf 默认配置即会从 classpath:/templates 中读取页面。在确认依赖的前端资源的目录结构没有问题的情况下,正常应该可以自动读取到页面。但是按照如下配置 controller 后,仍然无法正确渲染页面,访问网站时只显示空白页,并返回 index 的字符串

1
2
3
4
5
6
7
8
9
@RestController
@RequestMapping("/")
public class HomeController {

@RequestMapping(value = "/")
public String home(HttpServletRequest request, Model model) {
return "index";
}
}

解法

@RestController 替换为@Controller

原理解读

@RestController 注解等于@Controller+@ResponseBody ,由于使用@ResponseBody 注解,返回内容直接经过 HttpMessageConverter 写入 HTTP response body,这样 thymeleaf 的 VewResolVer 就不会进行渲染的工作。如果只使用@Controller 注解,则会返回 ModelAndView 对象,然后通过模板引擎 view resolver 的实现去处理完成视图渲染。

问题 2:static 下资源无法加载到 404

看后台日志可以看到 no mapping for get 的报错信息。

常见原因分析

一般常见的原因有如下几种,一般通过仔细检查都好比较定位:

  • 资源目录结构不正确
  • js 文件中对静态资源的路径引用不正确

而我这次碰到的原因比较特殊,是由于@EnableWebMvc 注解和@WebMvcAutoConfiguration 冲突导致后者不工作导致资源没法被正确接在。

解法

代码中去掉@EnableWebMvc 注解

原理分析

@EnableWebMvc 注解直接注入了代理的 mvc configuration 类,导致 WebMvcAutoConfiguration 的自动注入不奏效(WebMvcConfigurationSupport 的子类)。

1
2
@Configuration
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration

WebMvcAutoConfiguration 的自动配置中提供了一个关键能力就是默认的 resource handler 注册,如果这个自动配置没有工作,那对应 classpath 下的资源自然也就无法加载到了。

查看 WebMvcAutoConfiguration 源码,可以发现当缺失 WebMvcConfigurationSupport 的时候会注入。当有@EnableWebMvc 的时候不满足注入条件,也就不会执行相关逻辑。

1
2
3
4
5
6
7
8
9
10
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
//省略...
}