在spring boot中定制一下应景的错误页面,要比不定制的来说,视觉效果好很多,不进行定制的话,spring boot就会默认的返回一个白底黑字的错误页面给我买,如图:

springboot json传递特殊字符被转义 springboot json接收数据_spring boot

         这样给用户的体验当然是不好的,我们自然是想要一个视觉效果良好的错误页面,让用户体验更好,如图:

springboot json传递特殊字符被转义 springboot json接收数据_错误页面_02

 

         这样一个好看的页面也要比spring boot默认的错误页面好很多。

         如何配置错误页面呢?在spring boot中,通过ErrorMvcAutoConfiguration类来,这个类中,有着如下的配置:

@ConditionalOnClass({Servlet.class, DispatcherServlet.class})
@AutoConfigureBefore({WebMvcAutoConfiguration.class})
@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
public class ErrorMvcAutoConfiguration { 
    @Bean
    @ConditionalOnMissingBean(
        value = {ErrorAttributes.class},
        search = SearchStrategy.CURRENT
    )
    public DefaultErrorAttributes errorAttributes() {
        return new DefaultErrorAttributes(this.serverProperties.getError().isIncludeException());
    }

    @Bean
    @ConditionalOnMissingBean(
        value = {ErrorController.class},
        search = SearchStrategy.CURRENT
    )
    public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
        return new BasicErrorController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers);
    }

BasicErrorController这个bean,查看BasicErrorController的源码:

@Controller
@RequestMapping({"${server.error.path:${error.path:/error}}"})
public class BasicErrorController extends AbstractErrorController {
    private final ErrorProperties errorProperties;

    @RequestMapping(
        produces = {"text/html"}
    )
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = this.getStatus(request);
        Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
        response.setStatus(status.value());
        ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
        return modelAndView != null?modelAndView:new ModelAndView("error", model);
    }

         在此类上,可以看到注解中有这样一段"${server.error.path:${error.path:/error}}",可以看出,默认的错误路径是在/error文件夹下,也可以自己在application.properties文件中进行配置修改,如果都找不到,就会调用spring boot的默认错误页面(为一段HTML代码片段)。

只需要在根目录下创建一个error文件夹,然后往其中添加一些HTML页面即可,其命名规则为 错误码.html(如:404.html),当然,也可以用4xx.html、5xx.html,这样的就是统一匹配错误码为4、5开头的错误页面。当然,都存在的话,会优先匹配精确的错误码页面。

定制错误的JSON数据用于返回给客户端。

@ControllerAdvice注解,再写一个方法,在方法体上添加@ExceptionHandler( Exception.class )注解,Exception.class表示处理所有的异常,如果只想处理自定义异常,换成对应的自定义异常即可。具体代码如下:

@ControllerAdvice
public class MyException {

    @ResponseBody
    @ExceptionHandler(Exception.class)
    public Map<String,Object> handlerException(Exception e){
        Map<String,Object> map = new HashMap<>();
        map.put("code","错误代码");
        map.put("message",e.getMessage());
        return map;
    }
}

定制ErrorAttributes改变需要返回的内容。

继承DefaultErrorAttributes类,重写getErrorAttributes方法,在处理错误的类中,用转发的方式,以及最重要的一点,向请求域中设置状态码。首先,改写MyException这个类,具体代码如下:

@ControllerAdvice
public class MyException {

//    @ResponseBody
//    @ExceptionHandler(Exception.class)
//    public Map<String,Object> handlerException(Exception e){
//        Map<String,Object> map = new HashMap<>();
//        map.put("code",1005);
//        map.put("message",e.getMessage());
//        return map;
//    }

    @ExceptionHandler(Exception.class)
    public String handlerException(Exception e, HttpServletRequest request){
        //这里设置状态码
        request.setAttribute("javax.servlet.error.status_code",500);
        Map<String,Object> map = new HashMap<>();
        map.put("code",1005);
        map.put("msg","这是 put 进来的异常!");
        //将自定义的信息set到request 域中
        request.setAttribute("me",map);
        //使用转发,交给spring boot进行处理
        return "forward:/error";
    }
}

         然后,编写定制错误类MyErrorAttributes,具体代码如下:

@Component
public class MyErrorAttributes extends DefaultErrorAttributes {

    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
        //调用父类方法
        Map<String,Object> map = super.getErrorAttributes(webRequest,includeStackTrace);
        //写自己额外的信息
        map.put("msg","这是自定义的错误消息");
        Map<String,Object> me = (Map<String, Object>) webRequest.getAttribute("me",0);
        map.put("me",me);
        return map;
    }
}

         代码中:Map<String,Object> me = (Map<String, Object>) webRequest.getAttribute("me",0);的作用是取得在MyException这个类中request进行set的值,第二参数为0,表示是request域中,原因如下:

public interface WebRequest extends RequestAttributes {
...
}
public interface RequestAttributes {
    int SCOPE_REQUEST = 0;
    int SCOPE_SESSION = 1;
...
}

         发送相同的错误请求,查看客户端(postman)和浏览器的响应结果:

springboot json传递特殊字符被转义 springboot json接收数据_自适应错误_03

springboot json传递特殊字符被转义 springboot json接收数据_自适应错误_04

         如图,自定义错误响应完成。