Boot 內嵌的tomcat 是不支持jsp 的, jetty 也是。
雖然boot也是有默認配置一個InternalResourceViewResolver ,但是它並不像我們在springmvc 中熟悉的那樣, 它沒有解析 jsp 的功能。 其實InternalResourceViewResolver 的含義只是 內部資源的 視圖解析器, 更准確的說, 它是直接把 資源試圖的解析交給了 j2ee 容器。 在傳統的 springmvc + tomcat 項目中, 很明顯就是 tomcat, 具體的工作是我們熟悉的org.apache.jasper.servlet.JspServlet 完成的。但是在內嵌的tomcat環境中, 並沒有提供一個默認的jsp 解析器。因為, JspServlet 是 jasper. jar 的 內容。 如果我們想在boot 中使用jsp 的話, 我們需要引入類似的這么一個jar: tomcat-embed-jasper-xxx.jar , 對應的maven 是:
<dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency>
這里,我們同時引入了 jstl,standard 兩個jar ,因為他們常常是一起使用的。
boot提供了兩個mvc配置, 跟jsp 解析也有直接關系,他們默認是:
spring.mvc.view.prefix= spring.mvc.view.suffix=
WebMvcAutoConfiguration 的配置是這樣的:
@Bean @ConditionalOnMissingBean public InternalResourceViewResolver defaultViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix(this.mvcProperties.getView().getPrefix()); resolver.setSuffix(this.mvcProperties.getView().getSuffix()); return resolver; }
可見,很坑爹, 兩個都是空。 就是說,默認我們根本訪問不到 jsp !
因此, 我們至少需要把suffix 改一下吧:
spring.mvc.view.suffix=.jsp
But !這樣做, 我還是不能訪問到 jsp, public,static, resources各個目錄都放了相同文件,但都訪問不到。, 真是郁悶了。后面我發現這是boot 的一個坑, 貌似只有把 jsp 頁面 放到META-INF.resources 目錄下, 才能訪問。 也就是說,boot 只會 去META-INF.resources 目錄下查找jsp。 不知道為什么, 有誰知道了, 請告訴我。 除了META-INF.resources目錄, 傳統的 src/main/webapp/WEB-INF目錄 也是可以的。但不知道為什么一定要在WEB-INF 目錄下。
除了 修改application.properties 的mvc 配置項, 我們還可以手動的注冊一個InternalResourceViewResolver :
@Bean public InternalResourceViewResolver internalResourceViewResolver() { System.out.println("InternalResourceViewResolver 222."); InternalResourceViewResolver resourceViewResolver = new InternalResourceViewResolver(); resourceViewResolver.setSuffix(".jsp"); // resourceViewResolver.setPrefix("/"); resourceViewResolver.setViewClass(JstlView.class); return resourceViewResolver; }
效果是一樣的。 不同的是, 我們可以設置 viewclass :resourceViewResolver.setViewClass(JstlView.class); 默認它是空。