今日推荐程序猿惯用口头禅,你被击中了吗?
常见代码重构技巧(非常实用)
B站,牛啊。

程序员缺乏经验的 7 种表现

2021年4月程序员工资统计:平均14596元,南京程序员收入挤进一线。

作者:BNDong

www.cnblogs.com/bndong/p/10135370.html

在启动应用时会发现在控制台打印的日志中出现了两个路径为 {[/error]} 的访问地址,当系统中发送异常错误时,Spring Boot 会根据请求方式分别跳转到以 JSON 格式或以界面显示的 /error 地址中显示错误信息。

2018-12-18 09:36:24.627  INFO 19040 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" ...
2018-12-18 09:36:24.632  INFO 19040 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" ...

默认异常处理

使用 AJAX 方式请求时返回的 JSON 格式错误信息。

{"timestamp": "2018-12-18T01:50:51.196+0000","status": 404,"error": "Not Found","message": "No handler found for GET /err404","path": "/err404"
}

使用浏览器请求时返回的错误信息界面。

自定义异常处理

引入依赖

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.54</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

fastjson 是 JSON 序列化依赖, spring-boot-starter-freemarker 是一个模板引擎,用于我们设置错误输出模板。

增加配置

properties

# 出现错误时, 直接抛出异常(便于异常统一处理,否则捕获不到404)
spring.mvc.throw-exception-if-no-handler-found=true
# 不要为工程中的资源文件建立映射
spring.resources.add-mappings=false

yml

spring:# 出现错误时, 直接抛出异常(便于异常统一处理,否则捕获不到404)mvc:throw-exception-if-no-handler-found: true# 不要为工程中的资源文件建立映射resources:add-mappings: false

新建错误信息实体

/*** 信息实体*/
public class ExceptionEntity implements Serializable {private static final long serialVersionUID = 1L;private String message;private int    code;private String error;private String path;@JSONField(format = "yyyy-MM-dd hh:mm:ss")private Date timestamp = new Date();public static long getSerialVersionUID() {return serialVersionUID;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getError() {return error;}public void setError(String error) {this.error = error;}public String getPath() {return path;}public void setPath(String path) {this.path = path;}public Date getTimestamp() {return timestamp;}public void setTimestamp(Date timestamp) {this.timestamp = timestamp;}
}

新建自定义异常

/*** 自定义异常*/
public class BasicException extends RuntimeException {private static final long serialVersionUID = 1L;private int code = 0;public BasicException(int code, String message) {super(message);this.code = code;}public int getCode() {return this.code;}
}
/*** 业务异常*/
public class BusinessException extends BasicException {private static final long serialVersionUID = 1L;public BusinessException(int code, String message) {super(code, message);}
}

BasicException 继承了 RuntimeException ,并在原有的 Message 基础上增加了错误码 code 的内容。而 BusinessException 则是在业务中具体使用的自定义异常类,起到了对不同的异常信息进行分类的作用。

新建 error.ftl 模板文件

位置:/src/main/resources/templates/ 用于显示错误信息

<!DOCTYPE html>
<html>
<head><meta name="robots" content="noindex,nofollow" /><meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><style>h2{color: #4288ce;font-weight: 400;padding: 6px 0;margin: 6px 0 0;font-size: 18px;border-bottom: 1px solid #eee;}/* Exception Variables */.exception-var table{width: 100%;max-width: 500px;margin: 12px 0;box-sizing: border-box;table-layout:fixed;word-wrap:break-word;}.exception-var table caption{text-align: left;font-size: 16px;font-weight: bold;padding: 6px 0;}.exception-var table caption small{font-weight: 300;display: inline-block;margin-left: 10px;color: #ccc;}.exception-var table tbody{font-size: 13px;font-family: Consolas,"Liberation Mono",Courier,"微软雅黑";}.exception-var table td{padding: 0 6px;vertical-align: top;word-break: break-all;}.exception-var table td:first-child{width: 28%;font-weight: bold;white-space: nowrap;}.exception-var table td pre{margin: 0;}</style>
</head>
<body><div class="exception-var"><h2>Exception Datas</h2><table><tbody><tr><td>Code</td><td>${(exception.code)!}</td></tr><tr><td>Time</td><td>${(exception.timestamp?datetime)!}</td></tr><tr><td>Path</td><td>${(exception.path)!}</td></tr><tr><td>Exception</td><td>${(exception.error)!}</td></tr><tr><td>Message</td><td>${(exception.message)!}</td></tr></tbody></table>
</div>
</body>
</html>

编写全局异常控制类

/*** 全局异常控制类*/
@ControllerAdvice
public class GlobalExceptionHandler {/*** 404异常处理*/@ExceptionHandler(value = NoHandlerFoundException.class)@ResponseStatus(HttpStatus.NOT_FOUND)public ModelAndView errorHandler(HttpServletRequest request, NoHandlerFoundException exception, HttpServletResponse response) {return commonHandler(request, response,exception.getClass().getSimpleName(),HttpStatus.NOT_FOUND.value(),exception.getMessage());}/*** 405异常处理*/@ExceptionHandler(HttpRequestMethodNotSupportedException.class)public ModelAndView errorHandler(HttpServletRequest request, HttpRequestMethodNotSupportedException exception, HttpServletResponse response) {return commonHandler(request, response,exception.getClass().getSimpleName(),HttpStatus.METHOD_NOT_ALLOWED.value(),exception.getMessage());}/*** 415异常处理*/@ExceptionHandler(HttpMediaTypeNotSupportedException.class)public ModelAndView errorHandler(HttpServletRequest request, HttpMediaTypeNotSupportedException exception, HttpServletResponse response) {return commonHandler(request, response,exception.getClass().getSimpleName(),HttpStatus.UNSUPPORTED_MEDIA_TYPE.value(),exception.getMessage());}/*** 500异常处理*/@ExceptionHandler(value = Exception.class)public ModelAndView errorHandler (HttpServletRequest request, Exception exception, HttpServletResponse response) {return commonHandler(request, response,exception.getClass().getSimpleName(),HttpStatus.INTERNAL_SERVER_ERROR.value(),exception.getMessage());}/*** 业务异常处理*/@ExceptionHandler(value = BasicException.class)private ModelAndView errorHandler (HttpServletRequest request, BasicException exception, HttpServletResponse response) {return commonHandler(request, response,exception.getClass().getSimpleName(),exception.getCode(),exception.getMessage());}/*** 表单验证异常处理*/@ExceptionHandler(value = BindException.class)@ResponseBodypublic ExceptionEntity validExceptionHandler(BindException exception, HttpServletRequest request, HttpServletResponse response) {List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();Map<String,String> errors = new HashMap<>();for (FieldError error:fieldErrors) {errors.put(error.getField(), error.getDefaultMessage());}ExceptionEntity entity = new ExceptionEntity();entity.setMessage(JSON.toJSONString(errors));entity.setPath(request.getRequestURI());entity.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());entity.setError(exception.getClass().getSimpleName());response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());return entity;}/*** 异常处理数据处理*/private ModelAndView commonHandler (HttpServletRequest request, HttpServletResponse response,String error, int httpCode, String message) {ExceptionEntity entity = new ExceptionEntity();entity.setPath(request.getRequestURI());entity.setError(error);entity.setCode(httpCode);entity.setMessage(message);return determineOutput(request, response, entity);}/*** 异常输出处理*/private ModelAndView determineOutput(HttpServletRequest request, HttpServletResponse response, ExceptionEntity entity) {if (!(request.getHeader("accept").contains("application/json")|| (request.getHeader("X-Requested-With") != null && request.getHeader("X-Requested-With").contains("XMLHttpRequest")))) {ModelAndView modelAndView = new ModelAndView("error");modelAndView.addObject("exception", entity);return modelAndView;} else {response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());response.setCharacterEncoding("UTF8");response.setHeader("Content-Type", "application/json");try {response.getWriter().write(ResultJsonTools.build(ResponseCodeConstant.SYSTEM_ERROR,ResponseMessageConstant.APP_EXCEPTION,JSONObject.parseObject(JSON.toJSONString(entity))));} catch (IOException e) {e.printStackTrace();}return null;}}
}

@ControllerAdvice

作用于类上,用于标识该类用于处理全局异常。

@ExceptionHandler

作用于方法上,用于对拦截的异常类型进行处理。value 属性用于指定具体的拦截异常类型,如果有多个 ExceptionHandler 存在,则需要指定不同的 value 类型,由于异常类拥有继承关系,所以 ExceptionHandler 会首先执行在继承树中靠前的异常类型。

BindException

该异常来自于表单验证框架 Hibernate validation,当字段验证未通过时会抛出此异常。

编写测试 Controller

@RestController
public class TestController {@RequestMapping(value = "err")public void error(){throw new BusinessException(400, "业务异常错误信息");}@RequestMapping(value = "err2")public void error2(){throw new NullPointerException("手动抛出异常信息");}@RequestMapping(value = "err3")public int error3(){int a = 10 / 0;return a;}
}

使用 AJAX 方式请求时返回的 JSON 格式错误信息。

# /err
{"msg": "应用程序异常","code": -1,"status_code": 0,"data": {"path": "/err","code": 400,"error": "BusinessException","message": "业务异常错误信息","timestamp": "2018-12-18 11:09:00"}
}# /err2
{"msg": "应用程序异常","code": -1,"status_code": 0,"data": {"path": "/err2","code": 500,"error": "NullPointerException","message": "手动抛出异常信息","timestamp": "2018-12-18 11:15:15"}
}# /err3
{"msg": "应用程序异常","code": -1,"status_code": 0,"data": {"path": "/err3","code": 500,"error": "ArithmeticException","message": "/ by zero","timestamp": "2018-12-18 11:15:46"}
}# /err404
{"msg": "应用程序异常","code": -1,"status_code": 0,"data": {"path": "/err404","code": 404,"error": "NoHandlerFoundException","message": "No handler found for GET /err404","timestamp": "2018-12-18 11:16:11"}
}

使用浏览器请求时返回的错误信息界面。

示例代码:https://github.com/BNDong/spring-cloud-examples/tree/master/spring-cloud-zuul/cloud-zuul

参考资料

《微服务 分布式架构开发实战》 龚鹏 著

https://www.jianshu.com/p/1a49fa436623

推荐文章
  • 2021年4月程序员工资统计:平均14596元,南京程序员收入挤进一线。

  • 常见的SQL面试题:经典50例

  • 47K Star 的SpringBoot+MyBatis+docker电商项目,附带超详细的文档!

  • 写博客能月入10K?

  • 一款基于 Spring Boot 的现代化社区(论坛/问答/社交网络/博客)

更多项目源码
  • 这或许是最美的Vue+Element开源后台管理UI

  • 推荐一款高颜值的 Spring Boot 快速开发框架

  • 一款基于 Spring Boot 的现代化社区(论坛/问答/社交网络/博客)

  • 13K点赞都基于 Vue+Spring 前后端分离管理系统ELAdmin,大爱

  • 想接私活时薪再翻一倍,建议根据这几个开源的SpringBoot

​SpringCloud:统一异常处理相关推荐

  1. ssm 异常捕获 统一处理_SSM 统一异常处理

    SSM 统一异常处理 spring创建中, 处理异常可以使用try-cache处理, 也可以使用spring提供的统一异常处理 在spring中, 统一处理异常有2中方式 注解方式 @Exceptio ...

  2. ssm 异常捕获 统一处理_SpringMVC 统一异常处理介绍及实战

    背景 什么是统一异常处理 目标 统一异常处理实战 用 Assert(断言) 替换 throw exception 定义统一异常处理器类 扩展 总结 <Java 2019 超神之路> < ...

  3. Spring Boot统一异常处理的拦截指南

    通常我们在Spring Boot中设置的统一异常处理只能处理Controller抛出的异常.有些请求还没到Controller就出异常了,而这些异常不能被统一异常捕获,例如Servlet容器的某些异常 ...

  4. 使用Spring MVC统一异常处理实战

    原文:http://blog.csdn.net/ufo2910628/article/details/40399539 1 描述  在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处 ...

  5. Spring Boot中Web应用的统一异常处理

    为什么80%的码农都做不了架构师?>>>    我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供了一个默认的映射:/error,当处理中抛 ...

  6. trycatch抛出异常_Java生鲜电商平台架构中,如何统一异常处理及架构实战

    补充说明:本文讲得比较细,所以篇幅较长.请认真读完,希望读完后能对统一异常处理有一个清晰的认识. 背景 软件开发过程中,不可避免的是需要处理各种异常,就我自己来说,至少有一半以上的时间都是在处理各种异 ...

  7. 【转】Spring mvc 统一异常处理和静态文件的配置

    1.在spring mvc下实现统一异常处理很方便,只要在web.xml中配置异常时要显示的页面即可,如下: [html] view plaincopyprint? <error-page> ...

  8. springboot统一异常处理类及注解参数为数组的写法

    springboot统一异常处理类及注解参数为数组的写法 参考文章: (1)springboot统一异常处理类及注解参数为数组的写法 (2)https://www.cnblogs.com/zhucww ...

  9. C#自定义异常 统一异常处理

    C#自定义异常 统一异常处理 参考文章: (1)C#自定义异常 统一异常处理 (2)https://www.cnblogs.com/eedc/p/9266237.html (3)https://www ...

  10. 统一异常处理+错误编码设计方案

    统一异常处理+错误编码设计方案 参考文章: (1)统一异常处理+错误编码设计方案 (2)https://www.cnblogs.com/wd326150354/p/10861713.html 备忘一下 ...

最新文章

  1. springMVC3学习(二)--ModelAndView对象
  2. CF452F Permutations/Luogu2757 等差子序列 树状数组、Hash
  3. php截取字符串函数 左右,php截取中文字符串函数的技巧
  4. s7-1200跟mysql_让西门子S7-1200直接连接MySQL数据库!!!
  5. matlab 文件之间相互调用实例
  6. 数据结构与算法——图解平衡二叉树及代码实现
  7. Eclipse中错误为 Access restriction 的解决方案
  8. Tomcat服务器上Servlet连接数据库连接不上出现空指针异常的解决方案
  9. 凝结11年技术实力 弹性计算国内首著发布
  10. 梦幻西游手游海外服务器维护,梦幻西游手游维护 新神器任务轩辕丘之祸开启...
  11. Are We Evaluating Rigorously? Benchmarking Recommendation for Reproducible Evaluation and Fair Compa
  12. 视频转文字怎么操作?这些方法值得收藏
  13. 用HTML写一首绝句古诗,《绝句二首》_杜甫的诗词_诗词名句网
  14. 一个百万富翁碰到一个陌生人,陌生人找他谈了一个换钱的计划.该计划如下:我每天给你10万,而你第一天给我一分钱,第二天我仍给你十万,你给我二分钱,第三天我仍给你十万,你给我四分钱......你每天给我的
  15. 15051:小Biu的区间和
  16. Macworld2007发布iPhone!
  17. 手机安装Linus系统
  18. Django REST framework+Vue 打造生鲜超市(十三)
  19. dl380g6服务器开机没信号,DL380 G6常见问题二
  20. Excel生成条形码

热门文章

  1. PAT:1090. Highest Price in Supply Chain (25) AC
  2. CSS定位(postion)和移动(float)
  3. 配置事务springmvc3.1 mybatis 3.1 事务不起作用
  4. Google搜索引擎的十大应用
  5. Secure CRT 自动记录日志和时间戳功能配置
  6. Leetcode4-寻找两个正序数组的中位数原理及代码实现
  7. 区块链BaaS云服务(10)用友iuap区块链平台
  8. python——类和对象之__str__方法的使用
  9. [armv8-arch64]linux kernel 5.9的异常量表介绍(irq,fiq,sync,svc)
  10. optee中core_init_mmu_regs函数解读