SpringBoot支持JSP访问,启动报错java.lang.NoClassDefFoundError: javax/servlet/ServletContext

Spring Boot 专栏收录该内容
16 篇文章 0 订阅

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>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
如运行报错,指定版本<version>version number</version>版本号显示红色说明插件相关文件没有下载下来或者没有下载完整。找到maven repository删除之前不完整或者文件夹即可,重新下载。这样就完美解决了之前的问题。

指定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嵌入依赖关系,所以应该是单独声明的原因。

如有人遇到一样的问题,麻烦在评论区评论一下,谢谢。以上问题都是在使用IntelliJ IDEA的情况下所发生的错误及解决方案。项目也在eclipse运行过,没有以上问题出现。



  • 6
    点赞
  • 3
    评论
  • 4
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值