问题描述:xxjob调度的异常错误进入了正常app请求的线程中,导致app正常返回报文中加入了xxjob的异常信息。
代码场景:在xml中配置了一个mvc:interceptor(代码图片一),并过滤掉scheduler(调度接口),因为在调度代码中使用了threadlocal方法,所以在XML配置的aop中做了threadLocalUthis.remveAll()(图片二);代码中有拦截器MessageInterceptor实现了HandlerInterceptor方法(图片三)。
图片一
图片二
图片三
排查发现:在xml配置的aop拦截器中,新增打印日志,发现代码异常之后切点调用的方法是errorHtml,请求路径是ydqdceis/error,代码中是没有配置相关接口和代码。所以在一顿百度之后,发现了errorHtml是由springboot框架制定的一个异常。(在SpringBoot中,常用的异常处理有两种:一种是 BasicErrorController,另一种是 @ControllerAdvice。BasicErrorController 用于处理非Controller抛出的异常,而@ControllerAdvice 用于处理Controller抛出的异常,对于非Controller抛出的异常它是不会管的。但是,如果是Controller层调用Service层,从Service层抛出,依然会抛到Controller,所以还是会调用@ControllerAdvice进行处理(我们的xxjob调度也是controller的,但是为什么会触发BasicErrorController,这里自己想的是估计是xml配置的aop,所以触发的是BasicErrorController异常)。Springboot框架在出现错误时有一个默认的错误请求 /error;出现异常之后执行/error请求之前框架会判断出现异常的请求类型,然后根据请求类型判断是返回一个HTML页面还是JSON格式的错误信息BasicErrorController主要处理 /error 请求,该类中有两个处理 /error 请求的方法,分别是 errorHtml 和 error,前者返回的是HTML页面后者返回的是JSON格式的数据。BasicErrorController 中有两个标注了 @RequestMapping 的方法,当请求头的 Accept 中包含 text/html 时,会调用 public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response)方法,其他情况则会调用 public ResponseEntity<Map<String, Object>> error(HttpServletRequest request)方法。通过断点调试可以看到,这个 request 对象中封装了很多有用的信息,我们可以利用这些信息来定义自己的信息体。)
解决方案:
第一种:在实现MessageInterceptor拦截器中的preHandler方法中的第一步就先进行threadlocalUtils.removeAll()方法,然后再存储当前线程的数据。
第二种:在xml配置的aop中,过滤掉error和errorHtml两个接口方法。
第三种(没去写过,不知道行不行):重写BasicErrorController类,和error,errorHtml方法。