首页 > 编程语言 >【问题解决】Tomcat启动服务时提示Filter初始化或销毁出现java.lang.AbstractMethodError错误

【问题解决】Tomcat启动服务时提示Filter初始化或销毁出现java.lang.AbstractMethodError错误

时间:2023-01-16 20:12:51浏览次数:45  
标签:lang java Tomcat Filter init api servlet javax

问题背景

最近在开发项目接口,基于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()其实是可以的;
  • 但是运行在外置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,下次博客见。

标签:lang,java,Tomcat,Filter,init,api,servlet,javax
From: https://www.cnblogs.com/hellxz/p/17056222.html

相关文章

  • golang 结构体
    结构体与JSON序列化JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。JSON键值对是用来保存JS对象的一......
  • 【Javaweb】tomcat目录介绍
    bin专门用来存放tomcat服务器的可执行程序conf专门用来存放tomcat服务器的配置文件lib专门用来存放tomcat服务器的jar包logs专门用来存放tomcat服务器运行时输出的......
  • 过滤器Filter
       ......
  • (转)Golang中自动“取引用”和“解引用”对原值的影响
    原文:https://blog.csdn.net/u014633283/article/details/839020201.写在前面我们知道Golang在调用方法时,会自动对实参进行“取引用”或“解引用”操作。我们在前面的博客......
  • golang map的定义与使用
    Mapmap是一堆键值对的未排序集合,比如以身份证号作为唯一键来标识一个人的信息。map是引用类型,键必须支持相等运算符(==,!=)类型,比如:int,string,float等内建类型,只含......
  • golang 的fmt 包实现了格式化I/O函数,类似于C的 printf 和 scanf。
      #定义示例类型和变量typeHumanstruct{Namestring}varpeople=Human{Name:"zhangsan"} 普通占位符占位符说明......
  • 图片上传报错 java.lang.IllegalArgumentException: image == null!
    记录一次报错java.lang.IllegalArgumentException:image==null!jdk版本:openjdk1.8问题复现:使用  ImageIO.read(newFileInputStream(imgPath)) 进行图片读取时,......
  • golang切片
    切片切片并不是数组或者数组指针,切片只是对数组中连续片断的引用,这个片断可以是整个数组,也可以是由起始索引和终止索引标识的数组,所以切片是一个引用类型。//切......
  • Servlet1 - Servlet&Tomcat配置与启动
    Servlethtml中,form表单的method=post|action=add发送到服务器后根据add映射到相对应的服务器需要在web.xml中配置服务器映射用户发送请求,action=add,项......
  • python filter
    a=[1,2,3,4,5,6]b=filter(lambdax:x%2==1,a)print(list(b))[1,3,5]......