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的实现去处理完成视图渲染。
image.png

问题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下的资源自然也就无法加载到了。
image.png

查看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 {
//省略...
}