<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>

          遇到 400、500 錯誤千萬不要慌!

          共 12475字,需瀏覽 25分鐘

           ·

          2021-06-23 22:53

          點擊關(guān)注公眾號,Java干貨及時送達(dá)

          作者:fredalxin
          地址:https://fredal.xin/400-error-deal

          很多人都會在平時開發(fā)過程中遇到400或500異常,并且也沒有走到服務(wù)端controller中,就變得有些不知所措。

          我們知道SpringMVC從DispatchServlet開始接收與分發(fā)請求,從入口開始debug,還能找不到問題所在么?

          從DispatchServlet的doDispatch()方法開始處理請求:

          protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
              //刪除一些代碼
              try {
                  ModelAndView mv = null;
                  Exception dispatchException = null;

                  try {
                      // 刪除一些代碼
                      try {
                          // Actually invoke the handler.
                          mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                      }
                      finally {
                          if (asyncManager.isConcurrentHandlingStarted()) {
                              return;
                          }
                      }
                      applyDefaultViewName(request, mv);
                      mappedHandler.applyPostHandle(processedRequest, response, mv);
                  }
                  catch (Exception ex) {
                      dispatchException = ex;  // 這里捕獲了異常TypeMismatchException
                  }
                  processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
              }
              catch (Exception ex) {
              }
              finally {
                  // 刪除一些代碼
              }
          }

          其實在這兒我們就能看到exception的具體異常棧,有興趣的可以繼續(xù)看springMVC的處理方法processDispatchResult。另外,關(guān)注公眾號Java技術(shù)棧,在后臺回復(fù):面試,可以獲取我整理的 Spring 系列面試題和答案,非常齊全。

          private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
                  boolean errorView = false;
                  if (exception != null) {
                      if (exception instanceof ModelAndViewDefiningException) {
                          logger.debug("ModelAndViewDefiningException encountered", exception);
                          mv = ((ModelAndViewDefiningException) exception).getModelAndView();
                      }
                      else {
                          Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
                          mv = processHandlerException(request, response, handler, exception);// 執(zhí)行這個方法
                          errorView = (mv != null);
                      }
                  }
                  // 方便閱讀,刪除了其他代碼
            
          }

          這個方法中對異常進(jìn)行判斷,發(fā)現(xiàn)不是“ModelAndViewDefiningException”就交給processHandlerException方法繼續(xù)處理。

          protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
              // Check registered HandlerExceptionResolvers...
              ModelAndView exMv = null;
              for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
                  exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
                  if (exMv != null) {
                      break;
                  }
              }
              // 去掉了一些代碼
              throw ex;
          }

          這里看到for循環(huán)來找一個handlerExceptionResolver來處理這個異常。handler列表有spring自帶的ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver、DefaultHandlerExceptionResolver以及自定義的exceptionResolver。

          Spring Boot 系列最新教程推薦看下:https://github.com/javastacks/spring-boot-best-practice

          這些都繼承自AbstractHandlerExceptionResolver類,這個類是一個抽象類,它實現(xiàn)了HandlerExceptionResolver接口,它對HandlerExceptionResolver接口約定的方法的所實現(xiàn)代碼如下:

          public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
              if (shouldApplyTo(request, handler)) {

                  logException(ex, request);
                  prepareResponse(ex, response);
                  return doResolveException(request, response, handler, ex);
              }
              else {
                  return null;
              }
          }

          首先判斷當(dāng)前異常處理器是否可以處理當(dāng)前的目標(biāo)handler。例如通過for循環(huán)依次發(fā)現(xiàn)輪到DefaultHandlerExceptionResolver才能處理,那么最終會執(zhí)行該handlerExceptionResolver的doResolveException方法。

          protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

              try {
                  if (ex instanceof NoSuchRequestHandlingMethodException) {
                      return handleNoSuchRequestHandlingMethod(...);
                  }
                  // 刪除部分else if   instanceof 判斷
                  else if (ex instanceof TypeMismatchException) {
                      // 執(zhí)行到了這里
                      return handleTypeMismatch((TypeMismatchException) ex, request, response, handler);
                  }
                  // 刪除部分else if   instanceof 判斷
                  else if (ex instanceof BindException) {
                      return handleBindException((BindException) ex, request, response, handler);
                  }
              }
              catch (Exception handlerException) {
              }
              return null;
          }

          通過對異常類型的判斷,來執(zhí)行相應(yīng)handleXXXException方法。而handleXXXException方法中,有很多是會拋出400錯誤的!

          舉個幾個栗子:

          protected ModelAndView handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
              response.sendError(400, ex.getMessage());
              return new ModelAndView();
          }

          protected ModelAndView handleServletRequestBindingException(ServletRequestBindingException ex, HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
              response.sendError(400, ex.getMessage());
              return new ModelAndView();
          }

          protected ModelAndView handleTypeMismatch(TypeMismatchException ex, HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
              response.sendError(400);
              return new ModelAndView();
          }

          protected ModelAndView handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
              response.sendError(400);
              return new ModelAndView();
          }

          protected ModelAndView handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
              response.sendError(400);
              return new ModelAndView();
          }

          protected ModelAndView handleMissingServletRequestPartException(MissingServletRequestPartException ex, HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
              response.sendError(400, ex.getMessage());
              return new ModelAndView();
          }

          protected ModelAndView handleBindException(BindException ex, HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
              response.sendError(400);
              return new ModelAndView();
          }

          那么拋出400錯誤的時候該怎么解決呢?

          從服務(wù)端角度出發(fā),可以定義完善的全局異常處理器exceptionHandler,把易拋出400的錯誤例如TypeMismatchException、BindException都給處理掉,返回能看得懂的信息。

          從客戶端請求過程中來看,可以自定義handlerExceptionResolver,只需實現(xiàn)HandlerExceptionResolver接口即可,例如:

          public class ApiHandlerExceptionResolver implements HandlerExceptionResolver {
           @Override
              public ModelAndView resolveException(HttpServletRequest request,
                      HttpServletResponse response, Object handler, Exception exception)
           
          {
                  ModelAndView model = new ModelAndView();
                 // do something ...
                
                return model;
              } 

          所以遇到400錯誤的時候不要慌,畢竟400它是個標(biāo)準(zhǔn)的錯誤碼,好好debug或者查閱一下相關(guān)資料便能迎刃而解。

          另外,關(guān)注公眾號Java技術(shù)棧,在后臺回復(fù):面試,可以獲取我整理的 Java、Spring 系列面試題和答案,非常齊全。






          關(guān)注Java技術(shù)棧看更多干貨



          獲取 Spring Boot 實戰(zhàn)筆記!
          瀏覽 24
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  欧美成人激情在线 | 亚洲成人精品在线观看 | 亚洲精品乱码久久久久久蜜芽 | a级黄色的网站在线观看 | 免费黄色A |