【问题解决】Tomcat启动服务时提示Filter初始化或销毁出现java.lang.AbstractMethodError错误
问题背景
最近在开发项目接口,基于SpringBoot 2.6.8,最终部署到外置Tomcat 8.5.85 下,开发过程中写了一个CookieFilter,实现javax.servlet.Filter接口,代码编译期正常。部署到外置Tomcat 8.5.85 下,在控制台上报错:
16-Jan-2023 16:11:07.756 严重 [localhost-startStop-1] org.apache.catalina.core.StandardContext.filterStart 启动过滤器异常[cookieFilter]
java.lang.AbstractMethodError
at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:281)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:109)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4604)
...省略其他输出...
日志截图如下:
除了初始化错误还有销毁错误,异常类型与以下的错误类型一致:
16-Jan-2023 16:11:07.876 严重 [localhost-startStop-1] org.apache.catalina.core.ApplicationFilterConfig.release 失败的销毁过滤器类型为[xx.CookieFilter]名称为[CookieFilter]
java.lang.AbstractMethodError
at org.apache.catalina.core.ApplicationFilterConfig.release(ApplicationFilterConfig.java:312)
at org.apache.catalina.core.StandardContext.filterStop(StandardContext.java:4638)
...省略其他输出...
日志截图如下:
我的代码差不多长这样:
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class CookieFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
//做一些处理...
filterChain.doFilter(request, response);
}
}
反复分析
- 首先要知道这个异常(java.lang.AbstractMethodError)是什么?
- 也就是说父子两个类编译时机不同,先编译父类,在编译子类前对父子类方法定义做了不兼容的修改,编译子类通过后,让子类与先编译的父类一起运行,导致运行期实例化子类时找不到父类定义抽象方法的实现,从而抛出AbstractMethodError错误。
- 根据Filter的生命周期,初始化init,运行期doFilter,销毁destroy,我们可以推测出是CookieFilter没有实现init方法与destroy方法
- 这里问题就来了:这里的父(接口)是javax.servlet.Filter,实现的CookieFilter只是一个Filter实现类,我们并没有办法修改Filter接口,按理说编译期就应该报错才对嘛,为啥能编译成功呢?
- 原因就在于在SpringBoot上使用Filter接口需要引用
javax.servlet:javax.servlet-api
依赖包,这个包里定义的Filter接口的init()与destroy()是有默认实现的,代码如图: - 也就是说,我们编译期不重写init()与destroy()其实是可以的;
- 原因就在于在SpringBoot上使用Filter接口需要引用
- 但是运行在外置Tomcat8.5.x上的时候,这两个方法却要求必须实现了么?
- 有两种可能,一是Tomcat 8.5.x的共享库中有Filter定义,与我们需要的Filter不同,没有默认实现init与destroy方法;另一个可能是我们打的包中有两个包包含javax.servlet.Filter,运行期JVM加载顺序不一致就会引出不同的问题!
- 根据上边的猜测一,我找到了Tomcat 8.5.85的Filter源码https://github.com/apache/tomcat/blob/8.5.85/java/javax/servlet/Filter.java,我们发现在第67行init方法的确没有default关键字修饰,destroy方法也是这样的,第一个猜测是成立的
- 根据猜测二,我在程序War包中找到了两个servlet-api包:javax.servlet-api与servlet-api,前者版本较后者新。问题分析到这里就可以做解决方案了。
解决方案
- 方案一:不管新旧servlet-api包,所有Filter都添加默认init与destroy方法
- 方案二:升级外置Tomcat版本到9.x,原因是9.x的Tomcat的共享库Filter有默认实现init与destroy方法
- 方案三:构建排除较新的javax.servlet-api包,继续使用Tomcat 8.5.x,同样地所有Filter都要添加init与destroy方法,空的方法也可以。
- 方案四:使用内嵌Tomcat9.x部署,构建排除旧版servlet-api包
- 方案五:构建排除javax.servlet-api包与旧版servlet-api包,代码改造添加init与destroy方法,以共享库定义Filter为主
- 方案六:不大推荐。构建排除旧版servlet-api包,仍部署在Tomcat 8.5.x,有可能会加载到共享库里的Filter
这几种方案中对于研发层面最简单避免这个问题的就是方案一,这里的解决方案是抛砖引玉,欢迎大家评论给出更优解。我是Hellxz,下次博客见。
【问题解决】Tomcat启动服务时提示Filter初始化或销毁出现java.lang.AbstractMethodError错误的更多相关文章
- Struts2环境下Tomcat启动异常:Exception starting filter struts2,报了一个java.lang.ClassNotFoundException
在写一个struts2+hibernate整合的小例子时,启动Tomcat服务器,报了一个: 严重: Exception starting filter struts2java.lang.ClassN ...
- mysql启动服务时提示"服务名无效"
1,首先说明一下我的环境,我刚开始是用的XAMPP这个集成的软件,里面安装了apache, mysql,tomcat这些软件,然后通过控制面板对其进行启动关闭的操作,这些操作很方便,但是我就用net ...
- Mysql----mysql启动服务时提示"服务名无效"
1,首先说明一下我的环境,我刚开始是用的XAMPP这个集成的软件,里面安装了apache, mysql,tomcat这些软件,然后通过控制面板对其进行启动关闭的操作,这些操作很方便,但是我就用net ...
- eclipse中启动服务时提示端口被占的2种解决方案
出现类似这样的:port '19001' at localhost are already in use 第一种:在任务管理器中关闭相关eclipse进程,然后重启eclipse.这种方法可能有时候会 ...
- Tomcat连HBase报错: HTTP Status 500 - java.lang.AbstractMethodError: javax.servlet.jsp.JspFactory.getJspApplicationContext
Tomcat中连接HBase数据库,启动的时候报错: HTTP Status 500 - java.lang.AbstractMethodError: javax.servlet.jsp.JspFac ...
- 使用 ServerSocket 进行文件上传,以及用Tomcat启动ServerSocket时,会卡死解决
服务器端代码 import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOExcept ...
- PLSQL往Oracle数据库插入中文后变为问号 和 启动PLSQL时提示NLS_LANG在客户端不能确定的解决办法
PLSQL往Oracle数据库插入中文后变为问号 和 启动PLSQL时提示NLS_LANG在客户端不能确定的解决办法 1.检查服务器的字符编码 Select * from V$NLS_PARAMETE ...
- 启动Oracle时提示:ORA-01078:failure in processing system parameters
一.使用环境操作系统:CentOS release 6.2 (Final) 数据库:Oracle 12g数据库主目录:/ora12/product/product/12.1.0/db_1 二.问题描述 ...
- SpringBoot启动项目时提示:Error:java: 读取***.jar时出错;
场景 在IDEA中新建SpringBoot项目后,修改了默认的Maven仓库和配置文件,然后在启动项目时提示: Error:java: 读取\org\assertj\assertj-core\3.11 ...
- SpringBoot启动项目时提示:Error:(3, 32) java: 程序包org.springframework.boot不存在
场景 在IDEA中新建SpringBoot项目,后启动项目时提示: Error:(3, 32) java: 程序包org.springframework.boot不存在 实现 将pom.xml中par ...
随机推荐
- 一天十道Java面试题----第三天(对线程安全的理解------>线程池中阻塞队列的作用)
这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 21.对线程安全的理解 22.Thread和Runnable的区别 23.说说你对守护线程的理解 24.ThreadLoc ...
- mybatisPlus在Springboot中的使用
文章目录 1.简介 2.支持的数据库 3.框架 4.创建一个springboot项目 4.1 .pom文件中加入依赖 4.2.yml文件的配置 4.3 .数据库脚本 4.4.实体类 4.5 .启动类添 ...
- 空链接的作用以及<a href="#"></a>和<a href="javascript:;"></a>的区别
空链接的作用以及<a href="#"></a>和<a href="javascript:;"></a>的区别在 ...
- pinpoint部署
pinpoint是一个分析大型分布式系统的平台,提供解决方案来处理海量跟踪数据,主要面向基于tomcat的Java 应用. pinpoint使用HBASE储存数据. 下面介绍pinpoint部署及应用 ...
- 嵌入式-C语言基础:二级指针
二级指针:可以理解为指向指针的指针,存放的是指针变量的地址. 下面用一级指针来保存一个指针变量的地址: #include<stdio.h> int main() { int *p1; in ...
- C++期末考试题库
哈尔滨商业大学计算机专业C++期末考试题库 下载:题库 示例: 一.单选题:1.能作为 C ++程序的基本单位是( C )A .字符 B .语句 C .函数 D .源程序文件2.程序中主函数的名字为( ...
- vscode分级文件夹
如果vscode不小心设置成文件独立展开,一堆文件看着很乱 这样设置 首选项-设置-功能-资源管理器-compack folders 就可以折叠文件夹了
- 关于linux建立u盘legacy启动方式引导
前言 我一直在用linux,但是我在linux制作pe启动盘无法实现,windows有很多制作pe启动盘的软件,如大白菜,u深度什么的,但是linux没有对应的软件,所以我想写一个类似的工具,那么就有 ...
- 初始化一个ArrayList的多种方式
序言 本片文章用于归纳java中初始化一个ArrayList的几种方式 add方法添加 最基础的方式就是我们在new一个ArrayList之后使用add方法添加元素 /** * 第一种方式,通过add ...
- 【Shell脚本案例】案例1:服务器系统配置初始化
〇.目录 一.背景 新购买10台服务器,并安装Linux系统 目的:对操作系统进行配置的初始化 二.需求 1.设置时区并同步时间 2.禁用selinux安全机制 3.关闭防火墙(清空防火墙的默认策略, ...