方式一

  1. /**
  2. * 自定义异常处理器,处理请求产生的异常。在这里即可封装返回的json数据。
  3. * 但是没有自适应效果,即浏览器端访问和其他客户端访问均返回json数据。
  4. **/
  5. @ControllerAdvice
  6. public class MyExceptionHandler {
  7. @ResponseBody
  8. // 请求抛出自定义的UserNotExistException异常,在这里声明专门捕获该异常
  9. @ExceptionHandler(UserNotExistException.class)
  10. public Map<String,Object> handleException(Exception e){
  11. Map<String,Object> map = new HashMap<>();
  12. map.put("code","user.notexist");
  13. map.put("message",e.getMessage());
  14. return map;
  15. }
  16. }

通过上述自定义异常处理器的方式,无法实现自适应的效果。因此,不能通过直接拦截异常处理的方式来定制返回的json数据。
因此,我们需要进行优化,可以通过转发到/error,进而被BasicErrorController处理的方式,来进行自适应响应的效果处理。

方式二

  1. /**
  2. * 自定义异常处理器,不再直接返回json数据,而是重定向到 /error,进而被BasicErrorController处理,
  3. * 再通过自定义的ErrorAttributes来处理json。
  4. **/
  5. @ControllerAdvice
  6. public class MyExceptionHandler {
  7. @ExceptionHandler(UserNotExistException.class)
  8. public String handleException(Exception e, HttpServletRequest request){
  9. /**
  10. * 传入我们自己的错误状态码,并且保证该状态码有对应的错误页面和解析流程,
  11. * 否则就不会进入定制错误页面的解析流程
  12. **/
  13. request.setAttribute("javax.servlet.error.status_code", 504);
  14. Map<String,Object> map = new HashMap<>();
  15. map.put("code","user.notexist");
  16. map.put("message",e.getMessage());
  17. // 重定向到/error
  18. return "forward:/error";
  19. }
  20. }

接下来就需要将我们的定制数据携带出去。出现错误以后,会来到/error请求,会被BasicErrorController处理,响应出去可以获取的数据是由getErrorAttributes得到的(是AbstractErrorController(ErrorController)规定的方法)。

思路:
1、完全来编写一个ErrorController的实现类或者是编写AbstractErrorController的子类,放在容器中。
2、页面上能获取的数据或者是json返回的数据都是通过errorAttributes.getErrorAttributes()得到。 容器中DefaultErrorAttributes.getErrorAttributes()用于数据处理。

  1. // 给容器中加入自定义的ErrorAttributes,通过定制ErrorAttributes改变需要返回的内容
  2. @Component
  3. public class MyErrorAttributes extends DefaultErrorAttributes {
  4. @Override
  5. public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes,
  6. boolean includeStackTrace) {
  7. Map<String, Object> map = super.getErrorAttributes(requestAttributes, includeStackTrace);
  8. map.put("company","atguigu");
  9. return map;
  10. }
  11. }

最终的效果:响应是自适应的,浏览器访问返回定制的错误页面,其他客户端访问返回定制的json数据。
定制错误JSON数据 - 图1