部署在Tomcat的Web应用使用Filter时的注意点

部署在Tomcat的Web应用使用Filter时的注意点

如果有遇到java.lang.AbstractMethodError异常而且是执行init时抛出的,要注意了。

推测

从报错点看,在执行Filter的init时发生异常,应该排查Filter的实现,以及查看该异常的注释描述是怎样的。

探索

AbstractMethodError

先查看该异常的描述信息

1
2
3
4
5
6
7
8
9
10
/**
* Thrown when an application tries to call an abstract method.
* Normally, this error is caught by the compiler; this error can
* only occur at run time if the definition of some class has
* incompatibly changed since the currently executing method was last
* compiled.
*
* @author unascribed
* @since JDK1.0
*/

注释中说了调用抽象方法时抛出的运行时异常,也就是说Filter的init是抽象方法。

Filter

查看Filter的源码

1
2
3
4
5
6
7
8
9
public interface Filter {

public default void init(FilterConfig filterConfig) throws ServletException {}

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;

public default void destroy() {}
}

这里可以看到init并不是抽象方法,而是作为一个默认方法,这样就跟抛出该异常的描述不相符,也不应该抛出异常。

查看提供Filter的包,看到是tomcat-embed-core-9.0.37.jar,嗯,version为9,但部署的Tomcat版本是8。

我们切换到tomcat-embed-core-8.5.46.jar查看version为8的版本源码

1
2
3
4
5
6
7
public interface Filter {
void init(FilterConfig var1) throws ServletException;

void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

void destroy();
}

这里就可以看出问题所在了,Tomcat8和Tomcat9关于Filter的源码是不一样的,我们使用spring-boot-starter-web依赖提供的是Tomcat9的代码,Tomcat9对init和destroy方法处理成了默认方法不需要我们提供实现,但Tomcat8必须要我们提供实现。

解决

有三种解决方案,可以挑选其中一个觉得合适的方案。

升级Tomcat版本

将Tomcat8升级到Tomcat9可以解决这个问题,保持开发环境与部署环境一致。

兼容Tomcat版本

提供init和destroy方法的实现,即使是空方法。这样可以部署在Tomcat8也可以部署在Tomcat9都没问题。

调整Tomcat依赖

引入tomcat-embed-core的依赖调整为与实际部署的Tomcat版本保持一致,这样做就可以在编码与编译时触发检查机制。


部署在Tomcat的Web应用使用Filter时的注意点
https://blog.gugu.dev/2024-02-21/部署在Tomcat的Web应用使用Filter时的注意点/
作者
MinMin
发布于
2024年2月21日
许可协议