前言

再项目中,我们新建项目的时候,都会对接口进行异常全局捕获管理,然后返回给前端!所以,如何快速的实现异常全局捕获就尤其重要!

基于springBoot实现全局异常捕获功能

  1. package com.haoker.servicebase.handler;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.haoker.result.R;
  5. import org.springframework.amqp.rabbit.connection.CorrelationData;
  6. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.beans.factory.annotation.Value;
  9. import org.springframework.web.bind.annotation.ControllerAdvice;
  10. import org.springframework.web.bind.annotation.ExceptionHandler;
  11. import org.springframework.web.bind.annotation.ResponseBody;
  12. import javax.servlet.http.HttpServletRequest;
  13. import java.net.Inet4Address;
  14. import java.net.InetAddress;
  15. import java.net.UnknownHostException;
  16. import java.util.Date;
  17. import java.util.Map;
  18. import java.util.UUID;
  19. /**
  20. * 统一异常处理类,采用ControllerAdvice注解,注意拦截的内容默认包要处于扫描中才能生效。
  21. *
  22. */
  23. @ControllerAdvice
  24. public class GlobalExceptionHandler implements RabbitTemplate.ConfirmCallback {
  25. @Value("${spring.application.name}")
  26. private String serverIdName;
  27. @Value("${server.port}")
  28. private String serverPort;
  29. @Autowired
  30. private RabbitTemplate rabbitTemplate;
  31. @ExceptionHandler(RuntimeException.class)
  32. @ResponseBody
  33. public R errorResult(HttpServletRequest request, Exception ex) throws UnknownHostException {
  34. // 采用全局捕获异常 拦截系统中的错误,返回友好的提示给客户端
  35. Map<String, String[]> parameterMap = request.getParameterMap();
  36. StackTraceElement[] stackTrace = ex.getStackTrace();
  37. StackTraceElement stackTraceElement = stackTrace[0];
  38. // 转换成json
  39. JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(stackTraceElement));
  40. // 新增参数内容
  41. jsonObject.put("parameterContent", parameterMap);
  42. // 新增错误日志
  43. jsonObject.put("errorContent", ex.getMessage());
  44. jsonObject.put("serviceId", serverIdName);
  45. jsonObject.put("createTime", new Date());
  46. jsonObject.put("messageId", UUID.randomUUID().toString().replace("-", ""));
  47. // 获取我们的ip
  48. jsonObject.put("serverIp", getServerAddres());
  49. // 投递到MQ中
  50. // try{
  51. // sendMsg(jsonObject.toJSONString());
  52. // }catch (Exception e){
  53. // return R.error().message(ex.getMessage());
  54. // }
  55. return R.error().message(ex.getMessage());
  56. }
  57. /**
  58. * 发送消息的方法
  59. */
  60. public void sendMsg(String msgJson) {
  61. // 设置生产者消息确认机制
  62. this.rabbitTemplate.setMandatory(true);
  63. this.rabbitTemplate.setConfirmCallback(this);
  64. CorrelationData correlationData = new CorrelationData();
  65. correlationData.setId(msgJson);
  66. String orderExchange = "fanoutExceptionLogExchange";
  67. rabbitTemplate.convertAndSend(orderExchange, null, msgJson, correlationData);
  68. }
  69. /**
  70. * correlationData 投递失败回调的消息
  71. *
  72. * @param correlationData
  73. * @param ack true 投递到MQ成功 如果是为false情况下 消息投递失败
  74. * @param s
  75. */
  76. @Override
  77. public void confirm(CorrelationData correlationData, boolean ack, String s) {
  78. String msg = correlationData.getId();
  79. if (!ack) {
  80. System.out.println();
  81. /*log.info("<<<往MQ投递消息失败>>>>:" + msg);*/
  82. // 采用递归算法重试
  83. sendMsg(msg);
  84. return;
  85. }
  86. /*log.info("<<<往MQ投递消息成功>>>>:" + msg);*/
  87. // 生产者投递多次还是is的情况下应该 人工记录
  88. }
  89. private String getServerAddres() throws UnknownHostException {
  90. InetAddress ip4 = Inet4Address.getLocalHost();
  91. return ip4.getHostAddress() + ":" + serverPort;
  92. }
  93. }

自定义异常捕获

1、添加自定义异常类

  1. public class MyException extends RuntimeException {
  2. private static final long serialVersionUID = 1L;
  3. public MyException(String code, String msg) {
  4. this.code = code;
  5. this.msg = msg;
  6. }
  7. private String code;
  8. private String msg;
  9. public String getCode() {
  10. return code;
  11. }
  12. public void setCode(String code) {
  13. this.code = code;
  14. }
  15. public String getMsg() {
  16. return msg;
  17. }
  18. public void setMsg(String msg) {
  19. this.msg = msg;
  20. }
  21. }

2、添加异常捕获处理

  1. @ExceptionHandler(MyException.class)
  2. @ResponseBody
  3. public R errorResult(HttpServletRequest request, Exception ex) throws UnknownHostException {
  4. // 采用全局捕获异常 拦截系统中的错误,返回友好的提示给客户端
  5. Map<String, String[]> parameterMap = request.getParameterMap();
  6. StackTraceElement[] stackTrace = ex.getStackTrace();
  7. StackTraceElement stackTraceElement = stackTrace[0];
  8. // 转换成json
  9. JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(stackTraceElement));
  10. // 新增参数内容
  11. jsonObject.put("parameterContent", parameterMap);
  12. // 新增错误日志
  13. jsonObject.put("errorContent", ex.getMessage());
  14. jsonObject.put("serviceId", serverIdName);
  15. jsonObject.put("createTime", new Date());
  16. jsonObject.put("messageId", UUID.randomUUID().toString().replace("-", ""));
  17. // 获取我们的ip
  18. jsonObject.put("serverIp", getServerAddres());
  19. // 投递到MQ中
  20. // try{
  21. // sendMsg(jsonObject.toJSONString());
  22. // }catch (Exception e){
  23. // return R.error().message(ex.getMessage());
  24. // }
  25. return R.error().message(ex.getMessage());
  26. }

3、再controller中抛出异常

  1. @RestController
  2. @RequestMapping("/exce")
  3. public class ExceptionController {
  4. @RequestMapping("/api/v1/myexce")
  5. public Object testMyException() {
  6. throw new MyException("500", "my ext异常");
  7. }
  8. }