SpringBoot支持JSP简介
前言:
这篇文章中, 我们将使用IntelliJ IDEA开发一个带有Spring Boot所提供的内嵌tomcat的Spring MVC 应用程序示例。 示例源码是官网下载下来。记录一下所踩过的坑。有什么疑问可以在评论区提问,谢谢。环境:
JDK1.8
IntelliJ IDEA/Eclipse
Maven
Spring Boot 1.5.6
Spring Boot与Apache Maven 3.2兼容。
Maven 依赖
spring-boot-starter-parent:
提供了依赖关系管理,可以省略已存在依赖的版本标签。
并声明一个或多个“启动器”的依赖关系。Spring Boot还提供了一个可选的 Maven插件来创建可执行的jar。
spring-boot-starter-parent
是使用Spring Boot的好方法,但它可能不适合所有的时间。有时您可能需要从不同的父POM
继承,或者您可能不喜欢我们的默认设置。请参见 第13.2.2节“使用不带父POM的Spring Boot”作为使用import
范围的替代解
决方案。
spring-boot-starter-web: 包括了创建一个web应用程序的所有依赖。 这将避免列出不同的Spring常见的项目的版本(译注:项Web项目可能需要添加大量的依赖)。
spring-boot-starter-tomcat:默认情况下,启用一个内嵌的Apache Tomcat 7实例。 我们使用了我们定义的版本重写了这一点。 如果你需要部署War包在其他独立版本的Tomcat服务器上也可以标明。
tomcat-embed-jasper: 提供.jsp文件加载。
项目介绍:
首先,去官网翻阅了一下文档找到如下介绍,已经翻译过来,如下:
使用SpringBoot时对JSP有一些限制,然后官网有一个JSP示例,试着跑起来,目前官网推荐的springboot版本是1.5.6,
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
其它依赖:
<!-- JSP文件需要的依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- Provided -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope><!--由JDK或者容器提供-->
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope><!--在IntellijIDEA中为provided时不会加入到Classpath中,这是IDEA的BUG->
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
然后试着去执行官网的JSP示例,使用的开发工具是IntellJ IDEA遇到了几个问题,如下介绍:
1、运行项目遇到了如下错误:
Caused by: java.lang.IllegalStateException: Failed to introspect annotated methods on class
org.springframework.boot.web.support.SpringBootServletInitializer
at org.springframework.core.type.StandardAnnotationMetadata.
getAnnotatedMethods(StandardAnnotationMetadata.java:163) ~[spring-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.
retrieveBeanMethodMetadata(ConfigurationClassParser.java:380) ~[spring-context-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.
doProcessConfigurationClass(ConfigurationClassParser.java:314) ~[spring-context-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.
processConfigurationClass(ConfigurationClassParser.java:245) ~[spring-context-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.
parse(ConfigurationClassParser.java:198) ~[spring-context-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.
parse(ConfigurationClassParser.java:167) ~[spring-context-4.3.10.RELEASE.jar:4.3.10.RELEASE]
... 17 common frames omitted
Caused by: java.lang.NoClassDefFoundError: javax/servlet/ServletContext
at java.lang.Class.getDeclaredMethods0(Native Method) ~[na:1.8.0_111]
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[na:1.8.0_111]
at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[na:1.8.0_111]
at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods
(StandardAnnotationMetadata.java:152) ~[spring-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
... 22 common frames omitted
Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletContext
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_111]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_111]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_111]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_111]
... 26 common frames omitted
google一番,查到了一些原因。
注意:
在Intellij IDEA中所有 scope 为 provided 的依赖都是不会被加入到 classpath 中的,目前该bug尚未被修复((bug report)。
如果你的web应用是部署到容器中的,那么这个bug不会影响使用,因为web应用中provided的依赖在容器运行时会被提供。
如果你做spring Boot开发,有带provided的依赖时,直接在IntellIJ IDEA中运行项目会导致ClassNotFound异常。
所以当jar需要被加入到classpath中需要注释<scope>provided</scope>,或者更改为:<scope>compile</scope>
Intellij Idea下运行Spring Boot关于provided依赖不加入classpath的bug与解决方案。其实这个错误有多种解决方案,下面就简单介绍一下最简单的解决方案:
插件赖如下:
<plugin>如运行报错,指定版本<version>version number</version>版本号显示红色说明插件相关文件没有下载下来或者没有下载完整。找到maven repository删除之前不完整或者文件夹即可,重新下载。这样就完美解决了之前的问题。
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
指定Application的working directory:
如上述还是不能访问jsp文件,或者报错404,原因如下,继续如下操作,指定working directory:
问题:在使用Intellij idea 时,如果配置文件放在project根目录下或者其他位置,往往会出现找不到配置文件的问题,而eclipse却不会出现这种问题。 解决方: 导致此问题的原因是因为Intellij idea 默认的根目录project的目录,而不是要运行的module目录。
选择Edit Configurations–》Configuration–》Working directory,选择当前的module或者$MODULE_DIR$,即可解决。详情如下图:
注意:
spring-boot-starter-web
包括spring-boot-starter-tomcat
。你可以在这里查看
在spring-boot-starter-tomcat
包括tomcat-embed-core
。你可以在这里查看
但是,似乎tomcat-embed-core
不包括tomcat-embed-jasper
。其实是tomcat-embed-jasper
谁包括依赖tomcat-embed-core
。在这里检查
无论如何,tomcat-embed-jasper
标记为provided
,所以表示您期望JDK或容器在运行时提供依赖关系。此范围仅适用于编译和测试类路径,不可传递。
总而言之,spring-boot-starter-web
包括tomcat嵌入式的依赖关系,但它不包括jasper嵌入依赖关系,所以应该是单独声明的原因。