16、springboot——错误处理原理+定制错误页面(1)

 


一、springboot默认的处理机制

  1.浏览器返回一个错误的页面
  默认处理错误:返回一个错误的页面:
  包括错误类型、时间......

 

 

  2.其他客户端访问
  默认响应一个json数据

 

 

 

原理:

错误自动配置的类:ErrorMvcAutoConfiguration.java

 

 

 默认配置:

复制代码
@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);
}

@Bean
public ErrorMvcAutoConfiguration.ErrorPageCustomizer errorPageCustomizer() {
    return new ErrorMvcAutoConfiguration.ErrorPageCustomizer(this.serverProperties, this.dispatcherServletPath);
}

@Bean
@ConditionalOnBean({DispatcherServlet.class})
@ConditionalOnMissingBean
public DefaultErrorViewResolver conventionErrorViewResolver() {
    return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties);
}
复制代码

 1、DefaultErrorAttributes:

复制代码
在页面共享信息
public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
    Map<String, Object> errorAttributes = new LinkedHashMap();
    errorAttributes.put("timestamp", new Date());
    errorAttributes.put("path", request.path());
    Throwable error = this.getError(request);
    HttpStatus errorStatus = this.determineHttpStatus(error);
    errorAttributes.put("status", errorStatus.value());
    errorAttributes.put("error", errorStatus.getReasonPhrase());
    errorAttributes.put("message", this.determineMessage(error));
    this.handleException(errorAttributes, this.determineException(error), includeStackTrace);
    return errorAttributes;
}
复制代码

 

2、BasicErrorController:处理默认/error请求

复制代码
@Controller
@RequestMapping({"${server.error.path:${error.path:/error}}"})
public class BasicErrorController extends AbstractErrorController {

@RequestMapping(
    produces = {"text/html"}//产生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);
}

@RequestMapping   //产生json数据,其他客户端来到这个方法处理;
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
    Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
    HttpStatus status = this.getStatus(request);
    return new ResponseEntity(body, status);
}
...
}
复制代码

 

3、ErrorPageCustomizer:

public class ErrorProperties {
@Value("${error.path:/error}")
private String path = "/error";
public String getPath() {
    return this.path;
}
...
}

 

4、DefaultErrorViewResolver:

复制代码
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
    ModelAndView modelAndView = this.resolve(String.valueOf(status.value()), model);
    if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
        modelAndView = this.resolve((String)SERIES_VIEWS.get(status.series()), model);
    }

    return modelAndView;
}

private ModelAndView resolve(String viewName, Map<String, Object> model) {
    //默认springboot会找到某个页面   error/404
    String errorViewName = "error/" + viewName;
    //模板引擎可以解析页面地址就使用模板引擎解析
    TemplateAvailabilityProvider provider = 
                this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext);
    //模板引擎不可用,就在静态资源文件夹下找errorViewName对应的页面
    return provider != null ? new ModelAndView(errorViewName, model) :
 this.resolveResource(errorViewName, model);
}
复制代码

 

步骤:

一但系统出现4xx或者5xx之类的错误;ErrorPageCustomizer就会生效(定制错误的响应规则);
就会来到/error请求,就会被BasicErrorController进行处理
1)响应页面(resolveErrorView方法)去哪个页面是由DefaultErrorViewResolver解析得到的
复制代码
protected ModelAndView resolveErrorView(HttpServletRequest request, 
HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
    //所有的ErrorViewResolver得到ModelAndView
    Iterator var5 = this.errorViewResolvers.iterator();
    ModelAndView modelAndView;
    do {
        if (!var5.hasNext()) {
            return null;
        }
        ErrorViewResolver resolver = (ErrorViewResolver)var5.next();
        modelAndView = resolver.resolveErrorView(request, status, model);
    } while(modelAndView == null);
    return modelAndView;
}
复制代码

 


 

posted @   Arbitrary233  阅读(250)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示