在处理异常时,我们需要对API请求抛出的异常时,我们要以JSON的形式返回错误信息。而在请求页面时报错的话,我们需要在跳转到相应的报错页面进行友好提示。
实现思路
在进入全局异常处理器之前,加一个拦截器,在preHandle中取得HandlerMethod,判断请求的Controller方法的返回类型,以及请求的Controller方法是否使用的@RestController
或者@ResponBody
注解。若满足以上条件则抛出异常时,应该返回json格式的报错信息,否则返回相应的错误页面。
拦截器
/**
* 判断Controller是返回json还是页面的拦截器,为统一异常处理返回结果做判断依据
*/
@Component
public class ExceptionPreHandleInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod hm = (HandlerMethod) handler;
Method method = hm.getMethod();
//Controller方法返回值是否为字符串
boolean b1 = method.getReturnType().equals(String.class);
//Controller方法是否使用@ResponseBody注解
boolean b2 = !method.isAnnotationPresent(ResponseBody.class);
//Controller是否使用@RestController注解
boolean b3 = !hm.getBeanType().isAnnotationPresent(RestController.class);
request.setAttribute("method_return_is_view", b1 && b2 && b3);
return true;
}
}
将该拦截器配置到SpringBoot中
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
ExceptionPreHandleInterceptor exceptionPreHandleInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 全局异常处理 前置处理拦截器
registry.addInterceptor(exceptionPreHandleInterceptor).addPathPatterns("/**");
}
}
全局异常处理器
@ControllerAdvice
public class BaseControllerAdvice {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@ExceptionHandler
public Object handleException(Exception e, HttpServletRequest request, HttpServletResponse response) throws Exception {
//获取拦截器判断的返回结果类型
Object o = request.getAttribute("method_return_is_view");
if (o == null) {
logger.error("", e);
throw e;
}
//是否是html/text
boolean isView = (Boolean) o;
//返回页面
if (isView) {
ModelAndView modelAndView = new ModelAndView("/error");//配置需要跳转的Controller方法
request.setAttribute("message", "系统异常");
return modelAndView;
} else {//返回json
ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
modelAndView.addObject("code", "500");
modelAndView.addObject("message", "系统异常");
modelAndView.addObject("data", );
return modelAndView;
}
}
}