SpringBoot-ErrorController 落日映苍穹つ 2022-05-21 01:51 53阅读 0赞 ### Springboot默认的错误处理 ### SpringBoot源代码中有这样一个ErrorController,针对SpringMvc错误的Mapping进行处理,很多的时候我们写了一个Controller,在浏览器上访问的时候经常会出现如下情况: Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Fri Aug 04 17:49:02 HKT 2017 There was an unexpected error (type=Not Found, status=404). No message available * 1 * 2 * 3 * 4 * 5 * 6 * 7 其实这是由于springmvc在发起http请求的时候,后台没有找到相应的RequestHandleMapping,springBoot默认返回一个错误的页面,对错误的一种默认处理 2017-08-04 17:49:02.201 DEBUG org.springframework.web.servlet.DispatcherServlet Line:869 - DispatcherServlet with name 'dispatcherServlet' processing GET request for [/error] 2017-08-04 17:49:02.201 DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping Line:310 - Looking up handler method for path /error 2017-08-04 17:49:02.202 DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping Line:317 - Returning handler method [public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)] 2017-08-04 17:49:02.202 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory Line:251 - Returning cached instance of singleton bean 'basicErrorController' 2017-08-04 17:49:02.202 DEBUG org.springframework.web.servlet.DispatcherServlet Line:955 - Last-Modified value for [/error] is: -1 2017-08-04 17:49:02.202 DEBUG org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor Line:85 - Opening JPA EntityManager in OpenEntityManagerInViewInterceptor 2017-08-04 17:49:02.204 DEBUG org.springframework.web.servlet.view.ContentNegotiatingViewResolver Line:263 - Requested media types are [text/html, text/html;q=0.8] based on Accept header types and producible media types [text/html]) 2017-08-04 17:49:02.204 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory Line:251 - Returning cached instance of singleton bean 'error' * 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 从上面的日志中,我们可以看到真正起到作用的是BasicErrorController.查看源代码可以发现: @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?new ModelAndView("error", model):modelAndView; } * 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 spring boot默认指定返回的内容类型为text/html,当request请求头中的(Accept)类型中包含该指定类型才返回; ### 自定义JSON格式返回数据 ### 实现ErrorController接口即可, package com.minlia.cloud.exception.handler; import com.minlia.cloud.body.StatefulBody; import com.minlia.cloud.body.impl.FailureResponseBody; import com.minlia.cloud.utils.EnvironmentUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.web.ErrorAttributes; import org.springframework.boot.autoconfigure.web.ErrorController; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Map; /** * 返回Rest错误信息 * * @author will * @author qianyi * @since 1.0 */ @RestController public class RestErrorEndpoint implements ErrorController { private static final String PATH = "/error"; @Autowired private ErrorAttributes errorAttributes; // @RequestMapping(value = PATH) @RequestMapping(value = PATH, produces = {MediaType.APPLICATION_JSON_VALUE}) StatefulBody error(HttpServletRequest request, HttpServletResponse response) { if(!EnvironmentUtils.isProduction()) { return buildBody(request,true); }else{ return buildBody(request,false); } } private StatefulBody buildBody(HttpServletRequest request,Boolean includeStackTrace){ Map<String,Object> errorAttributes = getErrorAttributes(request, includeStackTrace); Integer status=(Integer)errorAttributes.get("status"); String path=(String)errorAttributes.get("path"); String messageFound=(String)errorAttributes.get("message"); String message=""; String trace =""; if(!StringUtils.isEmpty(path)){ message=String.format("Requested path %s with result %s",path,messageFound); } if(includeStackTrace) { trace = (String) errorAttributes.get("trace"); if(!StringUtils.isEmpty(trace)) { message += String.format(" and trace %s", trace); } } return FailureResponseBody.builder().code(0).status(status).message(message).build(); } @Override public String getErrorPath() { return PATH; } private Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) { RequestAttributes requestAttributes = new ServletRequestAttributes(request); return errorAttributes.getErrorAttributes(requestAttributes, includeStackTrace); } } * 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21 * 22 * 23 * 24 * 25 * 26 * 27 * 28 * 29 * 30 * 31 * 32 * 33 * 34 * 35 * 36 * 37 * 38 * 39 * 40 * 41 * 42 * 43 * 44 * 45 * 46 * 47 * 48 * 49 * 50 * 51 * 52 * 53 * 54 * 55 * 56 * 57 * 58 * 59 * 60 * 61 * 62 * 63 * 64 * 65 * 66 * 67 * 68 * 69 * 70 * 71 * 72 * 73 * 74 再次请求则返回的是,这样就不会出现错误页面 { "timestamp":1501841693729, "requestId":"4bzKFSZ45gMyiAB9U808gDkplVM1RAJe20170804181453211403", "code":0, "status":404, "message":"Requested path /asfa with result Not Found" }
还没有评论,来说两句吧...