HandlerExceptionResolver的使用,返回前端相对友好的异常信息

首先 新建一个类  AppHandlerExceptionResolver 继承 DefaultErrorAttributes, 类DefaultErrorAttributes是实现接口HandlerExceptionResolver的。

然后 需要在 tomcat等容器启动时 加载类  AppHandlerExceptionResolver的bean, 采用类注解的模式(@Configuration和@Bean):

新建类:  WebMvcConfig :

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

@Bean
public DefaultErrorAttributes get() {
  AppHandlerExceptionResolver resolver = new AppHandlerExceptionResolver();
return resolver;
}

在 容器启动时,会加载 类 WebMvcConfig 到Spring容器; 

重写  AppHandlerExceptionResolver 方法中的  

resolveException(HttpServletRequest request, HttpServletResponse response,Object handler, Exception e)

容器启动完成之后,调用Controller方法,此时会调用到 接口HandlerExceptionResolver的方法resolveException(HttpServletRequest request, HttpServletResponse response,Object handler, Exception e)的方法实现,

自然会调用到 子类 AppHandlerExceptionResolver中的  resolveException(HttpServletRequest request, HttpServletResponse response,Object handler, Exception e)方法:

此时处理的异常是非业务异常:  包括参数类型不匹配,参数绑定失败,参数格式校验失败, 容器运行时异常(包括outOfMemory,数组越界等);

对方法resolveException 捕获到的 Exception e 异常进行 类型判断; 针对不同的类型,返回对应的信息:

代码如下:

@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception e) {

ModelAndView mv = new ModelAndView();

View view = createView(e);

mv.setView(view);

return mv;
}

private View createView(Exception e) {
MappingJackson2JsonView view = new MappingJackson2JsonView();

String message = "";
String code = "";

//如果是系统自定义异常
if (e instanceof BusinessException) {
BusinessException ae = (BusinessException) e;

message = ae.getMessage();
code = ae.getCode();

} else if (e instanceof ConstraintViolationException) {
ConstraintViolationException cve = (ConstraintViolationException) e;
ConstraintViolation<?> error = cve.getConstraintViolations().iterator().next();

code = "500";
message = error.getMessage();
e = new RuntimeException(message);
} else if(e instanceof BindException) {
// message = "上送参数"+((BindException) e).getBindingResult().getObjectName()+"字段类型匹配失败";
message = "上送参数"+((BindException) e).getBindingResult().getObjectName()+"字段类型匹配失败";

code = "100102005";
}else{
//如果是未知异常
// TODO 硬编码
code = "500";
message = "服务器繁忙, 请稍后再试";
}

e.printStackTrace();

view.addStaticAttribute("success", false);
view.addStaticAttribute("message", message);
view.addStaticAttribute("code", code);

// 如果不是生产环境
// if (!appEnvironment.getEnvironment().isProdEnv()) {
// view.addStaticAttribute("trace", ExceptionUtils.getStackTrace(e));
// }

return view;
}
 
原文地址:https://www.cnblogs.com/tuyf/p/7457116.html