全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

详解Springboot自定义异常处理

背景

Springboot 默认把异常的处理集中到一个ModelAndView中了,但项目的实际过程中,这样做,并不能满足我们的要求。具体的自定义异常的处理,参看以下

具体实现

如果仔细看完spring boot的异常处理详解,并且研究过源码后,我觉得具体的实现可以不用看了。。。

重写定义错误页面的url,默认只有一个/error

@Bean
  public EmbeddedServletContainerCustomizer containerCustomizer(){
    return new EmbeddedServletContainerCustomizer(){
      @Override
      public void customize(ConfigurableEmbeddedServletContainer container) {
        container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"));
        container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500"));
        container.addErrorPages(new ErrorPage(java.lang.Throwable.class,"/error/500"));
      }
    };
  }

重写通过实现ErrorController,重写BasicErrorController的功能实现

/**
 * 重写BasicErrorController,主要负责系统的异常页面的处理以及错误信息的显示
 * @see org.springframework.boot.autoconfigure.web.BasicErrorController
 * @see org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration
 *
 * @author Jonathan
 * @version 2016/5/31 11:22
 * @since JDK 7.0+
 */
@Controller
@RequestMapping(value = "error")
@EnableConfigurationProperties({ServerProperties.class})
public class ExceptionController implements ErrorController {

  private ErrorAttributes errorAttributes;

  @Autowired
  private ServerProperties serverProperties;


  /**
   * 初始化ExceptionController
   * @param errorAttributes
   */
  @Autowired
  public ExceptionController(ErrorAttributes errorAttributes) {
    Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
    this.errorAttributes = errorAttributes;
  }


  /**
   * 定义404的ModelAndView
   * @param request
   * @param response
   * @return
   */
  @RequestMapping(produces = "text/html",value = "404")
  public ModelAndView errorHtml404(HttpServletRequest request,
                 HttpServletResponse response) {
    response.setStatus(getStatus(request).value());
    Map<String, Object> model = getErrorAttributes(request,
        isIncludeStackTrace(request, MediaType.TEXT_HTML));
    return new ModelAndView("error/404", model);
  }

  /**
   * 定义404的JSON数据
   * @param request
   * @return
   */
  @RequestMapping(value = "404")
  @ResponseBody
  public ResponseEntity<Map<String, Object>> error404(HttpServletRequest request) {
    Map<String, Object> body = getErrorAttributes(request,
        isIncludeStackTrace(request, MediaType.TEXT_HTML));
    HttpStatus status = getStatus(request);
    return new ResponseEntity<Map<String, Object>>(body, status);
  }

  /**
   * 定义500的ModelAndView
   * @param request
   * @param response
   * @return
   */
  @RequestMapping(produces = "text/html",value = "500")
  public ModelAndView errorHtml500(HttpServletRequest request,
                 HttpServletResponse response) {
    response.setStatus(getStatus(request).value());
    Map<String, Object> model = getErrorAttributes(request,
        isIncludeStackTrace(request, MediaType.TEXT_HTML));
    return new ModelAndView("error/500", model);
  }


  /**
   * 定义500的错误JSON信息
   * @param request
   * @return
   */
  @RequestMapping(value = "500")
  @ResponseBody
  public ResponseEntity<Map<String, Object>> error500(HttpServletRequest request) {
    Map<String, Object> body = getErrorAttributes(request,
        isIncludeStackTrace(request, MediaType.TEXT_HTML));
    HttpStatus status = getStatus(request);
    return new ResponseEntity<Map<String, Object>>(body, status);
  }


  /**
   * Determine if the stacktrace attribute should be included.
   * @param request the source request
   * @param produces the media type produced (or {@code MediaType.ALL})
   * @return if the stacktrace attribute should be included
   */
  protected boolean isIncludeStackTrace(HttpServletRequest request,
                     MediaType produces) {
    ErrorProperties.IncludeStacktrace include = this.serverProperties.getError().getIncludeStacktrace();
    if (include == ErrorProperties.IncludeStacktrace.ALWAYS) {
      return true;
    }
    if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM) {
      return getTraceParameter(request);
    }
    return false;
  }


  /**
   * 获取错误的信息
   * @param request
   * @param includeStackTrace
   * @return
   */
  private Map<String, Object> getErrorAttributes(HttpServletRequest request,
                          boolean includeStackTrace) {
    RequestAttributes requestAttributes = new ServletRequestAttributes(request);
    return this.errorAttributes.getErrorAttributes(requestAttributes,
        includeStackTrace);
  }

  /**
   * 是否包含trace
   * @param request
   * @return
   */
  private boolean getTraceParameter(HttpServletRequest request) {
    String parameter = request.getParameter("trace");
    if (parameter == null) {
      return false;
    }
    return !"false".equals(parameter.toLowerCase());
  }

  /**
   * 获取错误编码
   * @param request
   * @return
   */
  private HttpStatus getStatus(HttpServletRequest request) {
    Integer statusCode = (Integer) request
        .getAttribute("javax.servlet.error.status_code");
    if (statusCode == null) {
      return HttpStatus.INTERNAL_SERVER_ERROR;
    }
    try {
      return HttpStatus.valueOf(statusCode);
    }
    catch (Exception ex) {
      return HttpStatus.INTERNAL_SERVER_ERROR;
    }
  }

  /**
   * 实现错误路径,暂时无用
   * @see ExceptionMvcAutoConfiguration#containerCustomizer()
   * @return
   */
  @Override
  public String getErrorPath() {
    return "";
  }

}

总结

第一步,通过定义containerCustomizer,重写定义了异常处理对应的视图。目前定义了404和500,可以继续扩展。

第二步,重写BasicErrorController,当然可以直接定义一个普通的controller类,直接实现第一步定义的视图的方法。重写的目的是重用ErrorAttributes。这样在页面,直接可以获取到status,message,exception,trace等内容。

如果仅仅是把异常处理的视图作为静态页面,不需要看到异常信息内容的话,直接第一步后,再定义error/404,error/500等静态视图即可。

ErrorController根据Accept头的内容,输出不同格式的错误响应。比如针对浏览器的请求生成html页面,针对其它请求生成json格式的返回

以上两步的操作,比网上流传的更能实现自定义化。希望对大家的学习有所帮助,也希望大家多多支持。


# springboot自定义异常  # spring自定义异常处理  # spring  # boot  # 异常处理  # Spring Boot 中的默认异常处理机制解析(如 /error&n  # SpringBoot实现全局异常处理方法总结  # Spring Boot全局异常处理解析  # Spring Boot统一异常处理详解  # Springboot之自定义全局异常处理的实现  # springboot全局异常处理详解  # SpringBoot中默认异常处理机制的实现  # 重写  # 自定义  # 看了  # 我觉得  # 不需要  # 这样做  # 看完  # 仅仅是  # 可以直接  # 只有一个  # 中了  # 更能  # 等内容  # 错误信息  # 两步  # 能满足  # 第二步  # 一个普通  # 大家多多  # 过程中 


相关文章: 建站10G流量真的够用吗?如何应对访问高峰?  MySQL查询结果复制到新表的方法(更新、插入)  香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化  如何通过虚拟主机空间快速建站?  C++中引用和指针有什么区别?(代码说明)  北京制作网站的公司排名,北京三快科技有限公司是做什么?北京三快科技?  昆明高端网站制作公司,昆明公租房申请网上登录入口?  宝塔面板如何快速创建新站点?  如何快速搭建虚拟主机网站?新手必看指南  建站中国必看指南:CMS建站系统+手机网站搭建核心技巧解析  建站主机功能解析:服务器选择与快速搭建指南  免费视频制作网站,更新又快又好的免费电影网站?  网站网页制作专业公司,怎样制作自己的网页?  制作充值网站的软件,做人力招聘为什么要自己交端口钱?  教学网站制作软件,学习*后期制作的网站有哪些?  高端建站如何打造兼具美学与转化的品牌官网?  北京建设网站制作公司,北京古代建筑博物馆预约官网?  制作农业网站的软件,比较好的农业网站推荐一下?  湖州网站制作公司有哪些,浙江中蓝新能源公司官网?  平台云上自助建站如何快速打造专业网站?  已有域名和空间如何快速搭建网站?  岳西云建站教程与模板下载_一站式快速建站系统操作指南  如何在宝塔面板中创建新站点?  建站之星下载版如何获取与安装?  如何在橙子建站中快速调整背景颜色?  动图在线制作网站有哪些,滑动动图图集怎么做?  Python lxml的etree和ElementTree有什么区别  b2c电商网站制作流程,b2c水平综合的电商平台?  php8.4新语法match怎么用_php8.4match表达式替代switch【方法】  淘宝制作网站有哪些,淘宝网官网主页?  如何通过远程VPS快速搭建个人网站?  如何在阿里云香港服务器快速搭建网站?  建站主机选虚拟主机还是云服务器更好?  网站专业制作公司有哪些,做一个公司网站要多少钱?  ui设计制作网站有哪些,手机UI设计网址吗?  如何配置FTP站点权限与安全设置?  宝塔新建站点报错如何解决?  如何通过虚拟主机快速搭建个人网站?  网站制作和推广的区别,想自己建立一个网站做推广,有什么快捷方法马上做好一个网站?  公司网站设计制作厂家,怎么创建自己的一个网站?  官网建站费用明细查询_企业建站套餐价格及收费标准指南  javascript中的try catch异常捕获机制用法分析  建站主机助手选型指南:2025年热门推荐与高效部署技巧  中山网站推广排名,中山信息港登录入口?  如何通过wdcp面板快速创建网站?  如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?  魔毅自助建站系统:模板定制与SEO优化一键生成指南  建站之星安装需要哪些步骤及注意事项?  移民网站制作流程,怎么看加拿大移民官网?  建站主机如何选?高性价比方案全解析 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。