把基于web.xml的应用迁移到Spring Boot

最近解决了以下几个问题,于是在这里记下,毕竟好记性不如烂笔头。

一、在spring boot配置web.xml中的默认欢迎页面welcome.do。

通过在标有@Configuration的配置类中新增registry.addViewController("/").setViewName("forward:/welcome.do");语句来设置自动跳转。

二、将转发的welcome.do映射到对应的@RequestMapping上。

试了很久不都行,心情有点烦躁,大神的一句“先把SSO的拦截器注释掉,单纯调试welcome.do的转发”启发了我,于是我造作了,发现还是不行,说明和SSO没有关心,于是专心看自己的配置,发现在application.properties文件中进行了这个配置server.servlet-path=*.do,发现去掉后就可以了。

但是网上说这样可以自定义配置DispatcherServlet中的mapping映射路径,我这么配置是为了让DispatcherServlet中的ViewResolver只去拦截并解析以.do为后缀的请求,为什么在我这里不行,目前还不知道原因,等待研究清楚后再说明。

https://segmentfault.com/q/1010000008113802

三、@RequestMapping处理完后return到welcome视图页面时,找不到对应的welcome.jsp页面。

Spring在加在MVC组件时会自动在dispatcherServlet中加载多个ViewResolver,我们可以在DispatcherServlet类中的resolveViewName上设置断点来单步调试看到所加载的ViewResolver。

把基于web.xml的应用迁移到Spring Boot

其中前三个都是spring自动加载的ViewResolver,而最后一个才是我手动加载的用来支持JSP页面的InternalResourceViewResolver,网上文章说这个Resolver要放在整个链中的最后,故通过viewResolver.setOrder(Ordered.LOWEST_PRECEDENCE);将其设为最后一个。

把基于web.xml的应用迁移到Spring Boot

但尝试后发现还是不行。通过在上面的断点反复调试后发现,转发的welcome.do请求被第一个ThymleafViewResolver匹配上了,Spring在启动时发现我引入了Thymleaf依赖,所以通过ThymeleafAutoConfiguration自动加载了Thymleaf相关的Resolver,官网说Spring Boot提供了Thymeleaf、FreeMarker、Velocity、Groovy、Mustache默认配置的模板引擎,看下就是只要引入起步依赖的jar包就可以直接使用了,这样的确大大地节省了开发者的心力。

同时因为Spring自动加载的ThymleafViewResolver会默认匹配所有的请求,于是把我*.do的请求也匹配上了,匹配上后也会转发到对应的@RequestMapping上,但最后却默认添加上了.html的后缀,而我的资源是welcome.jsp,于是就寻找不到对应的资源了。

在网上差了一些资料后,自己新建了一个ThymeleafViewResolver,通过viewResolver.setViewNames(new String[] {"*.thymeleaf"});特意将此Resolver中匹配的ViewNames(视图名称/路径名称)改为以.thymeleaf结尾,这样就不会匹配到我*.do的请求了,满怀着信心尝试后发现还是不行,原来之前的4个Resolver还在,只不过新增了一个我新加的ThymeleafViewResolver,虽然我这个新加的Resolver不会被*.do的请求匹配到,但Spring自动加载的ThymleafViewResolver还是会默认匹配所有的请求。

那么我们可不可以让Spring不去自动加载默认的那个ThymleafViewResolver呢?于是我尝试在Spring Boot的启动类上稍微修改**解,变成@SpringBootApplication(exclude = {ThymeleafAutoConfiguration.class}),然后就只剩下我新加的ThymeleafViewResolver了。

但试了之后发现还是不行,最后发现要application.properties文件中增加如下两行配置,告诉MVC的Resolver在拦截并解析后要加上.jsp的后缀,终于可以请求到welcome.jsp了。

spring.mvc.view.prefix=/WEB-INF/jsp/ 

spring.mvc.view.suffix=.jsp

四、DispatcherServlet中的ViewResolver只拦截并解析welcome.do后转发到对应的@RequestMapping响应方法上,不再次进行拦截并解析@RequestMapping响应方法处理完后return到welcome视图页面。

我尝试了如下三种方式都不行,等待以后继续尝试。

1、通过@SpringBootApplication(exclude = {DispatcherServletAutoConfiguration.class})的方式取消Spring自动注入DispatcherServlet的功能,然后自己生成并注册一个DispatcherServlet,发现会报错,可能是我注入的姿势不对,毕竟Spring自动注入的源码还是很多的,有空可以研究下。

把基于web.xml的应用迁移到Spring Boot

2、保留Spring自动注入的DispatcherServlet,同时自己引用Spring自动诸如的DispatcherServlet dispatcherServlet和MultipartConfigElement multipartConfigElement在注册一个ServletRegistrationBean,发现的确新增了一个我的ServletRegistrationBean,但Spring自动注入的DispatcherServlet还是存在,结果还是会自动拦截。

把基于web.xml的应用迁移到Spring Boot

3、在application.properties文件中进行了这个配置server.servlet-path=*.do,在文章刚开始就说了加上就不会将转发的welcome.do映射到对应的@RequestMapping上,目前原因不明。


最后再梳理下目前系统中的Spring MVC请求流程。

1、网页上发起Request请求。

2、通过转发将“/”请求转发为“/welcome.do”。

3、注入的DispatcherServlet(自动/手动)根据配置去拦截特定请求,譬如拦截以*.do为后缀的请求。

4、DispatcherServlet拦截到的请求交给ViewResolver链来匹配,若ViewResolver中没有设置ViewNames(视图名称/路径名称),则默认匹配所有的请求。

5、匹配上的ViewResolver将请求转发到对应的@RequestMapping上。

6、@RequestMapping响应方法处理完后return到welcome视图页面。

7、DispatcherServlet拦截到的请求交给ViewResolver链来匹配,若ViewResolver中没有设置ViewNames(视图名称/路径名称),则默认匹配所有的请求。

8、ViewResolver在拦截并解析了welcome请求后,加上配好/WEB-INF/jsp/前缀和.jsp的后缀,于是请求到了/WEB-INF/jsp/welcome.jsp页面。