<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ?SpringCloud:統(tǒng)一異常處理

          共 27613字,需瀏覽 56分鐘

           ·

          2021-05-17 01:26

          今日推薦

          程序猿慣用口頭禪,你被擊中了嗎?

          常見代碼重構(gòu)技巧(非常實(shí)用)

          B站,牛啊。

          程序員缺乏經(jīng)驗(yàn)的 7 種表現(xiàn)
          2021年4月程序員工資統(tǒng)計(jì):平均14596元,南京程序員收入擠進(jìn)一線。

          作者:BNDong

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

          在啟動(dòng)應(yīng)用時(shí)會(huì)發(fā)現(xiàn)在控制臺(tái)打印的日志中出現(xiàn)了兩個(gè)路徑為 {[/error]} 的訪問地址,當(dāng)系統(tǒng)中發(fā)送異常錯(cuò)誤時(shí),Spring Boot 會(huì)根據(jù)請(qǐng)求方式分別跳轉(zhuǎn)到以 JSON 格式或以界面顯示的 /error 地址中顯示錯(cuò)誤信息。

          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]}" ...

          默認(rèn)異常處理

          使用 AJAX 方式請(qǐng)求時(shí)返回的 JSON 格式錯(cuò)誤信息。

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

          使用瀏覽器請(qǐng)求時(shí)返回的錯(cuò)誤信息界面。

          自定義異常處理

          引入依賴

          <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 是一個(gè)模板引擎,用于我們?cè)O(shè)置錯(cuò)誤輸出模板。

          增加配置

          properties

          # 出現(xiàn)錯(cuò)誤時(shí), 直接拋出異常(便于異常統(tǒng)一處理,否則捕獲不到404)
          spring.mvc.throw-exception-if-no-handler-found=true
          # 不要為工程中的資源文件建立映射
          spring.resources.add-mappings=false

          yml

          spring:
            # 出現(xiàn)錯(cuò)誤時(shí), 直接拋出異常(便于異常統(tǒng)一處理,否則捕獲不到404)
            mvc:
              throw-exception-if-no-handler-found: true
            # 不要為工程中的資源文件建立映射
            resources:
              add-mappings: false

          新建錯(cuò)誤信息實(shí)體

          /**
           * 信息實(shí)體
           */
          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;
              }
          }
          /**
           * 業(yè)務(wù)異常
           */
          public class BusinessException extends BasicException {

              private static final long serialVersionUID = 1L;

              public BusinessException(int code, String message) {
                  super(code, message);
              }
          }

          BasicException 繼承了 RuntimeException ,并在原有的 Message 基礎(chǔ)上增加了錯(cuò)誤碼 code 的內(nèi)容。而 BusinessException 則是在業(yè)務(wù)中具體使用的自定義異常類,起到了對(duì)不同的異常信息進(jìn)行分類的作用。

          新建 error.ftl 模板文件

          位置:/src/main/resources/templates/ 用于顯示錯(cuò)誤信息

          <!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());
              }

              /**
               * 業(yè)務(wù)異常處理
               */
              @ExceptionHandler(value = BasicException.class)
              private ModelAndView errorHandler (HttpServletRequest request, BasicException exception, HttpServletResponse response) {
                  return commonHandler(request, response,
                          exception.getClass().getSimpleName(),
                          exception.getCode(),
                          exception.getMessage());
              }

              /**
               * 表單驗(yàn)證異常處理
               */
              @ExceptionHandler(value = BindException.class)
              @ResponseBody
              public 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;
              }

              /**
               * 異常處理數(shù)據(jù)處理
               */
              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

          作用于類上,用于標(biāo)識(shí)該類用于處理全局異常。

          @ExceptionHandler

          作用于方法上,用于對(duì)攔截的異常類型進(jìn)行處理。value 屬性用于指定具體的攔截異常類型,如果有多個(gè) ExceptionHandler 存在,則需要指定不同的 value 類型,由于異常類擁有繼承關(guān)系,所以 ExceptionHandler 會(huì)首先執(zhí)行在繼承樹中靠前的異常類型。

          BindException

          該異常來自于表單驗(yàn)證框架 Hibernate validation,當(dāng)字段驗(yàn)證未通過時(shí)會(huì)拋出此異常。

          編寫測試 Controller

          @RestController
          public class TestController {

              @RequestMapping(value = "err")
              public void error(){
                  throw new BusinessException(400, "業(yè)務(wù)異常錯(cuò)誤信息");
              }

              @RequestMapping(value = "err2")
              public void error2(){
                  throw new NullPointerException("手動(dòng)拋出異常信息");
              }

              @RequestMapping(value = "err3")
              public int error3(){
                  int a = 10 / 0;
                  return a;
              }
          }

          使用 AJAX 方式請(qǐng)求時(shí)返回的 JSON 格式錯(cuò)誤信息。

          # /err
          {
              "msg""應(yīng)用程序異常",
              "code": -1,
              "status_code": 0,
              "data": {
                  "path""/err",
                  "code": 400,
                  "error""BusinessException",
                  "message""業(yè)務(wù)異常錯(cuò)誤信息",
                  "timestamp""2018-12-18 11:09:00"
              }
          }

          # /err2
          {
              "msg""應(yīng)用程序異常",
              "code": -1,
              "status_code": 0,
              "data": {
                  "path""/err2",
                  "code": 500,
                  "error""NullPointerException",
                  "message""手動(dòng)拋出異常信息",
                  "timestamp""2018-12-18 11:15:15"
              }
          }

          # /err3
          {
              "msg""應(yīng)用程序異常",
              "code": -1,
              "status_code": 0,
              "data": {
                  "path""/err3",
                  "code": 500,
                  "error""ArithmeticException",
                  "message""/ by zero",
                  "timestamp""2018-12-18 11:15:46"
              }
          }

          # /err404
          {
              "msg""應(yīng)用程序異常",
              "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"
              }
          }

          使用瀏覽器請(qǐng)求時(shí)返回的錯(cuò)誤信息界面。

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

          參考資料

          《微服務(wù) 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)》 龔鵬 著

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


          推薦文章


          更多項(xiàng)目源碼


          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  男女操逼在线观看 | 亚天堂中文 | 久久久久久久久国产精品 | 天堂资源网 | 亚洲一二三区电影在线 |