Maven内置tomcat启动的相关bug以及引申知识
这部分困扰了我一段时间,主要有两个地方的错误
-
下面简单讲解我出错的地方
-
配置问题:我的maven项目的pom.xml配置出错(通过IDEA的maven–>maven-archetype-webapp骨架创建,并加上了javax.servlet-api和jsp-api的包依赖—>这两个包没有添加scope标签配置provided元素)
-
启动方式问题:通过mvn tomcat:run启动---->与jdk版本出问题,应使用tomcat7插件启动
-
忘记终止项目就启动新项目,端口正在使用,启动失败
下面是我的pom.xml配置(出错版)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>priv.test</groupId> <artifactId>MavenTest</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>MavenTest Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>2.0</version> </dependency> </dependencies> <build> <finalName>MavenTest</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
包冲突问题
-
在访问的页面提示如下:空指针异常(以下截取部分错误信息)
HTTP Status 500 - type Exception report message description The server encountered an internal error () that prevented it from fulfilling this request. exception org.apache.jasper.JasperException: Unable to compile class for JSP: An error occurred at line: 1 in the generated java file The type java.io.ObjectInputStream cannot be resolved. It is indirectly referenced from required .class files An error occurred at line: 22 in the generated java file The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory Stacktrace: org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:92) org.apache.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:330) org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:439)
- 错误原因: 这种情况就是最常见的包依赖冲突问题----->pom.xml中依赖的javax.servlet-api和jsp-api的版本和maven内置tomcat的lib目录下的javax.servlet-api和jsp-api的版本不同
- 解决方法: 在我上面的pom.xml中的javax.servlet-api和jsp-api依赖中加上provided即可解决
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope><!--这个scope的配置--> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>2.0</version> <scope>provided</scope><!--这个scope的配置--> </dependency>
内置Tomcat版本和JDK版本冲突问题
-
按照我一开始操作后,我们其实发现不仅仅是访问页面出现了HTTP 500,在运行maven项目的提示框下(IDE下面的运行提示,或者cmd中运行提示),也出现了如下打印的错误信息
org.apache.jasper.compiler.JDTCompiler$1 findType 严重: Compilation error org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException at org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.<init>(ClassFileReader.java:342) at org.apache.jasper.compiler.JDTCompiler$1.findType(JDTCompiler.java:206) at org.apache.jasper.compiler.JDTCompiler$1.findType(JDTCompiler.java:163) org.apache.catalina.core.StandardWrapperValve invoke 严重: Servlet.service() for servlet jsp threw exception org.apache.jasper.JasperException: Unable to compile class for JSP: An error occurred at line: 1 in the generated java file The type java.io.ObjectInputStream cannot be resolved. It is indirectly referenced from required .class files An error occurred at line: 22 in the generated java file The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory Stacktrace: at org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:92) at org.apache.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:330) at org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:439) at
-
出错原因:jdk版本与tomcat版本不兼容
-
**解决方法:**添加tomcat7插件并运行该插件
<plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin>
-
**注意:**使用的命令不再是mvn tomcat:run!!!<---->此时应该使用的命令为tomcat7:run
-
端口占用问题
严重: Failed to initialize end point associated with ProtocolHandler ["http-bio-8080"]
java.net.BindException: Address already in use: JVM_Bind <null>:8080
Caused by: java.net.BindException: Address already in use: JVM_Bind
at java.net.DualStackPlainSocketImpl.bind0(Native Method)
Failed to initialize connector [Connector[HTTP/1.1-8080]]
org.apache.catalina.LifecycleException: Failed to initialize component [Connector[HTTP/1.1-8080]]
- 看到上面这几段就要知道是端口占用了,关闭之前启动的进程再重新启动
进行更改后的pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>priv.test</groupId>
<artifactId>MavenTest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>MavenTest Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>MavenTest</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
引申简单知识----标签下的几种元素
- complie:此元素为默认scope,表示dependency的使用范围为编译、测试、运行,适用于所有阶段,一般会随项目一起发布(即一起被打包)
- provided:该依赖一般在JDK或一个容器已提供该依赖才使用,provided表示dependency只作用于编译和测试,在运行时不使用—>如这篇文章的servlet api已被tomcat容器提供
- runtime:表示该dependency的作用范围在运行和测试时,在编译时不使用,如JDBC驱动,一般随项目一起发布
- test:表示该dependency作用在测试阶段,运行和编译阶段都不需要。如junit,一般不随项目一起发布
- system:适用于所有阶段,但是需要显式的提供一个绝对路径,指定该依赖的路径,即maven不在库中查找它,而是以外部包的形式接入