最近有在尝试使用 SpringBoot 整合JSP完成动态页面展示,在我搭建好框架并且编写了基本的JSP页面之后.在调试的时候却出现了一个问题,SpringBoot并没有正常的渲染我的页面而是直接将我的JSP页面当做静态资源给我返回了,这样就导致了每当我想访问我的 JSP页面的时候,总是在下载文件.最终导致的结果如下图:

事实上我犯了一个很常见的新手错误,搞错了SpringBoot与Tomcat之间的依赖关系,这里记录一下我是怎么犯错的.
过程复现
最开始的时候,我其实并没有直接尝试搭建 SpringBoot+JSP ,而是先尝试通过 Tomcat + Spring + SpringMVC 的方式实现相同的功能,为了使用 Spring + SpringMVC ,我再 pom.xml 中引入了相关依赖,然后编写了 JSP 文件,最终将写好的代码打包成 war 包部署到 Tomcat 上,最终展示的效果是和我预期的效果相同.
到目前为止一切进行顺利,之后我为了引入 SpringBoot ,开始在 pom.xml 文件中添加 SpringBoot 相关依赖,这部分比较简单,因为轻量是 SpringBoot 的宗旨.只需引入如下依赖即可:
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
接下来就是我犯错的地方了,在 SpringBoot 中并没有之间依赖模板引擎的东西.也就是没有 Jasper 编译引擎,因此我引入了下面相关依赖:
<!--用于编译jsp-->
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
最终我启动了 SpringBoot,然后就是上面所说的结果了,JSP页面并没有正常渲染,而是作为一个静态资源返回了.
关键之处在于<scope>provided</scope>,结果是,我并没有理解这里的作用范围到底是什么意思,最终导致我的JSP渲染失败.
这里说明一下作用域为 provided 的含义,表示这个资源包只会在编译阶段提供,在运行阶段是不提供的.在添加了这个依赖之后,原以为会在编译阶段实现对 JSP 动态页面的编译,但结果是我大错特错.
JSP的编译过程是在运行期间完成编译的,在第一次请求到达是,获取到为jsp页面后则会进行首次编译,因此 jasper 包的作用范围应该比编译期间更大,为运行期间.
所以在我移除<scope>provided</scope>后,JSP 页面开始能够正常渲染.
<!--用于编译jsp-->
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
总结
根据上面的调试现象我做出如下总结:

- 首先,Tomcat中的视图渲染器会根据资源的文件扩展名判断应该使用哪一种模板引擎
- 当对应的文件扩展名找不到对应的模板引擎时,Tomcat会将动态页面认为是一个静态资源返回,这里应该有一个优先级.
猜测
- 模板引擎的引入是无感的,即不需要做任何配置,那么是不是可以同时存在多种模板引擎,对应进行视图渲染的时候根据优先级进行查找模板引擎?
本文详述了在SpringBoot框架下整合JSP时,因误解依赖作用范围导致的JSP页面无法正常渲染的问题。作者分享了如何正确配置tomcat-embed-jasper依赖,以确保JSP页面在运行时被正确编译。

279

被折叠的 条评论
为什么被折叠?



