今天把公司的一个项目(该项目是其他部门开发的的一个工作流平台)部署到服务器上去,
发现有一个接口报错,但是本地 idea 运行不会报错
该项目是打包为 war 包的,所以我是部署到一个 tomcat8.5 里面
排查过程如下
一、先开启远程调试
在 start.sh 里面第一行添加
declare -x CATALINA_OPTS="-server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8888"
8888是远程调试监听端口,不是tomcat端口
然后运行远程调试
二、问题原因排查
根据调试,我发现了一个很严重的问题
JSONObject.parseObject 是错误的
我们看下这个类的定义
在 application.yml 里室友对 uums.code 等属性的配置的,这点放心
至于这个属性的值是什么时候注入进去的呢?
没有注解配置,应该是不会自动注入值的
三、发现答案
我尝试把上面 ${} 里的都写死,不用占位符,重新打包部署到服务器
结果就没有报错了,说明问题原因是这个 ${} 没有被成功赋值
但是本地idea启动就会赋值,说明是有哪个地方会在项目启动的时候手动赋值的
通过在这个项目里搜索 JSONField 注解代码,我们找到了
在启动类里
然后我不经要怀疑了,是不是部署到 tomcat 该段代码没有执行
很有可能,因为上面 loadSuccessMessage() 会打印启动成功的日志信息的,我在 tomcat 日志里也没有看到
四、解决办法
方法一、把上面那段代码放到某个配置文件里
如放到 @Bean 的一个方法里,让它项目启动时执行
像这样
方法二、实现 ServletContextListener,监听Tomcat启动成功
像这样
import com.alibaba.fastjson.annotation.JSONField;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.WebApplicationContextUtils;
@Component
public class ProviderContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent event) {
WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext()).getAutowireCapableBeanFactory().autowireBean(this);
System.out.println("这是tomcat启动后执行的代码");
// 修改EosDataTransferObject注解属性值
try {
// 更改EosDataTransferObject对象的JSONField的注解属性值value
AnnotationUtils.changeAnnotationValueOfClassByProperties(EosDataTransferObject.class, JSONField.class, "name");
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("这是tomcat销毁后执行的代码");
}
}
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏