方式一
/*** 自定义异常处理器,处理请求产生的异常。在这里即可封装返回的json数据。* 但是没有自适应效果,即浏览器端访问和其他客户端访问均返回json数据。**/@ControllerAdvicepublic class MyExceptionHandler {@ResponseBody// 请求抛出自定义的UserNotExistException异常,在这里声明专门捕获该异常@ExceptionHandler(UserNotExistException.class)public Map<String,Object> handleException(Exception e){Map<String,Object> map = new HashMap<>();map.put("code","user.notexist");map.put("message",e.getMessage());return map;}}
通过上述自定义异常处理器的方式,无法实现自适应的效果。因此,不能通过直接拦截异常处理的方式来定制返回的json数据。
因此,我们需要进行优化,可以通过转发到/error,进而被BasicErrorController处理的方式,来进行自适应响应的效果处理。
方式二
/*** 自定义异常处理器,不再直接返回json数据,而是重定向到 /error,进而被BasicErrorController处理,* 再通过自定义的ErrorAttributes来处理json。**/@ControllerAdvicepublic class MyExceptionHandler {@ExceptionHandler(UserNotExistException.class)public String handleException(Exception e, HttpServletRequest request){/*** 传入我们自己的错误状态码,并且保证该状态码有对应的错误页面和解析流程,* 否则就不会进入定制错误页面的解析流程**/request.setAttribute("javax.servlet.error.status_code", 504);Map<String,Object> map = new HashMap<>();map.put("code","user.notexist");map.put("message",e.getMessage());// 重定向到/errorreturn "forward:/error";}}
接下来就需要将我们的定制数据携带出去。出现错误以后,会来到/error请求,会被BasicErrorController处理,响应出去可以获取的数据是由getErrorAttributes得到的(是AbstractErrorController(ErrorController)规定的方法)。
思路:
1、完全来编写一个ErrorController的实现类或者是编写AbstractErrorController的子类,放在容器中。
2、页面上能获取的数据或者是json返回的数据都是通过errorAttributes.getErrorAttributes()得到。
容器中DefaultErrorAttributes.getErrorAttributes()用于数据处理。
// 给容器中加入自定义的ErrorAttributes,通过定制ErrorAttributes改变需要返回的内容@Componentpublic class MyErrorAttributes extends DefaultErrorAttributes {@Overridepublic Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes,boolean includeStackTrace) {Map<String, Object> map = super.getErrorAttributes(requestAttributes, includeStackTrace);map.put("company","atguigu");return map;}}
最终的效果:响应是自适应的,浏览器访问返回定制的错误页面,其他客户端访问返回定制的json数据。
