金蝶Apusic9.0部署springboot,HttpServletResponse.setContentLengthLong方法去哪了?
摘要:问题背景 项目有需要使用AAS9.0(即,金蝶天燕)web中间件部署springboot程序,服务正常启动后,只要访问应用就出现报错提示java.lang.NoSuchMethodError: javax.servlet.http.Http
问题背景
项目有需要使用AAS9.0(即,金蝶天燕)web中间件部署springboot程序,服务正常启动后,只要访问应用就出现报错提示java.lang.NoSuchMethodError: javax.servlet.http.HttpServletResponse.setContentLengthLong(J)V,导致大部分请求都有问题
详细报错如下:
25-05-20 11:15:00.770 [HTTPHandler-6-50|MAVXY1OF] ERROR - Forwarding to error page from request [/output/@xx/login/dist/app.bundle.js] due to exception [javax.servlet.http.HttpServletResponse.setContentLengthLong(J)V]
java.lang.NoSuchMethodError: javax.servlet.http.HttpServletResponse.setContentLengthLong(J)V
at org.springframework.http.server.ServletServerHttpResponse.writeHeaders(ServletServerHttpResponse.java:130)
at org.springframework.http.server.ServletServerHttpResponse.getBody(ServletServerHttpResponse.java:96)
at org.springframework.http.converter.ResourceHttpMessageConverter.writeContent(ResourceHttpMessageConverter.java:143)
at org.springframework.http.converter.ResourceHttpMessageConverter.writeInternal(ResourceHttpMessageConverter.java:114)
at org.springframework.http.converter.ResourceHttpMessageConverter.writeInternal(ResourceHttpMessageConverter.java:45)
at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:227)
查看方法栈可以看到是spring-web包中的ServletServerHttpResponse.writeHeaders()调用了javax.servlet.http.HttpServletResponse.setContentLengthLong()最终导致的报错。
排查解决
API不兼容
借助arthas来查出为啥会报错,servletResponse变量对应的是javax.servlet.http.HttpServletResponse接口,直接反编译看下方法是不是没定义
jad javax.servlet.http.HttpServletResponse
发现的确没定义,不过不急,该接口继承了javax.servlet.ServletResponse,再往上查一层
jad javax.servlet.ServletResponse
发现的确没有setContentLengthLong(),这说明大概率是API不兼容。用问小白查了下发现是Servlet 3.1之后就添加了这个方法。
优先加载高版本servlet-api包
既然中间件中的javax.servlet.ServletResponse版本低,根据JVM类加载机制,可以调整classpath让JVM优先加载 javax.servlet-api新版本包。
怎么调呢?查了AAS部署位置docs目录中的文档,可以将javax.servlet-api放到AAS部署目录下的lib/endorsed中。
