欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring boot集中異常處理方法實例

 更新時間:2020年04月17日 08:35:12   作者:云中志  
這篇文章主要介紹了Spring boot集中異常處理方法實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

集中異常處理

以下代碼可在github獲?。?a target="_blank" rel="external nofollow" >https://github.com/Syske/learning-dome-code/tree/master/springboot-learning

方式一:ExceptionHandle

定義自己的異常類型,根據(jù)不同類型做不同處理,比如我定義的MyException:

public class MyException extends RuntimeException {
  public MyException(String msg) {
    super(msg);
  }
}

然后通過MyExceptionHandle處理該異常,需要注意的是異常不能在filter中拋出,拋出也沒法捕獲

	
@RestControllerAdvice
public class MyExceptionHandle {
 
  @ExceptionHandler(MyException.class)
  public Result exceptionHandle(MyException e) {
    return Result.getFailed( "system error:MyException" + e.getMessage());
  }
}

在controller、service以及攔截器的預(yù)處理方法中都可以完美捕獲,這里特殊說下攔截器:

	
public class MyInterceptor implements HandlerInterceptor {
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    //throw new MyException("攔截器錯誤:MyInterceptor");
    // 這里的異常會完美捕獲,并返回
    return true;
  }
 
  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    throw new MyException("攔截器錯誤:MyInterceptor");
    /** 能捕獲異常信息并返回給客戶端,但并不會覆蓋已經(jīng)請求成功的返回結(jié)果,但會包含在返回結(jié)果中,比如我的返回結(jié)果:
     {"code":1,"success":true,"msg":"請求成功","result":true}{"code":0,"success":false,"msg":"system error:MyException攔截器錯誤:MyInterceptor","result":null}
     */
  }
 
  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    throw new MyException("攔截器錯誤:MyInterceptor");
    // 這里拋出的異常并不能被捕獲,會直接在后臺拋出,相當(dāng)于回掉函數(shù),請求結(jié)果已經(jīng)返回
  }
}

上面的解釋已經(jīng)夠清楚了,就不做過多說明了。剛剛我們說了,上面的這種方式,對于filter是不起作用的,下面我們說的這種方式,主要就是針對filter來說的

方式二:ExceptionFilter

定義一個controller,請求路徑可以自己指定,比如/error/exthrow:

	
@Controller
public class ExceptionController {
 
  @RequestMapping("/error/exthrow")
  public void rethrow(HttpServletRequest request) throws Exception {
    throw ((Exception) request.getAttribute("filter.error"));
  }
}

再定義一個異常攔截器,在需要拋出異常的攔截器中直接拋出異常,然后在異常攔截器中try-catch,發(fā)生異常時直接轉(zhuǎn)發(fā)至前面定義的異常controller,這里需要注意的是,如果你的filter是實現(xiàn)Filter或者繼承OncePerRequestFilter,那你不需要任何處理,直接request.setAttribute("filter.error", e)就可以了。

由于我把自己的filter交給shiro管理,而且是繼承BasicHttpAuthenticationFilter的,不知到什么原因,直接catch到的異常類型是ServletException,為了拿到真正的異常信息,我需要通過getCause()方法獲取filter中拋出的異常。因為controller拋出的異常最后還是會交給我們定義的MyExceptionHandle去處理,如果獲取到的異常不是我們自定義的異?;蛘咚淖宇惖脑挘蜁祷?00錯誤(在這個示例前,我以為所有的filter都是這樣的,后來實踐后發(fā)現(xiàn)并不是這樣😂)。

@Component
public class ExceptionFilter implements Filter {
 
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    try {
      chain.doFilter(request, response);
    } catch (Exception e) {      
      request.setAttribute("filter.error", e);
      //將異常分發(fā)到/error/exthrow控制器
      request.getRequestDispatcher("/error/exthrow").forward(request, response);
    }
  }
 
  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
  }
 
  @Override
  public void destroy() {
 
  }
}

我的filter:

實現(xiàn)Filter接口:

	
public class MyFilter implements Filter {
  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    throw new MyException("MyFilter過濾器拋出異常");
    //filterChain.doFilter(servletRequest, servletResponse);
  }
  
}

filter2繼承OncePerRequestFilter:

	
public class MyFilter2 extends OncePerRequestFilter {
  @Override
  protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
    throw new MyException("MyFilter2異常");
  }
}

filter配置類:

	
 @Bean
  public FilterRegistrationBean myFilterRegistration() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new MyFilter());
    registration.setName("myFilter");
    registration.addUrlPatterns("/*");
    //此處盡量小,要比其他Filter靠前
    registration.setOrder(1);
    return registration;
  }
 
  @Bean
  public FilterRegistrationBean myFilter2Registration() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new MyFilter2());
    registration.setName("myFilter2");
    registration.addUrlPatterns("/*");
    //此處盡量小,要比其他Filter靠前
    registration.setOrder(2);
    return registration;
  }
 
  /**
   * 配置攔截器
   * @return
   */
  @Bean
  public FilterRegistrationBean exceptionFilterRegistration() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new ExceptionFilter());
    registration.setName("exceptionFilter");
    //此處盡量小,要比其他Filter靠前
    registration.setOrder(-1);
    return registration;
  }

方式三:BasicErrorController

其實spring boot原生提供了異常集中處理,我們經(jīng)常會看到:

但是這種方式不夠友好,而且大部分情況不滿足我們的需求,我們可以通過繼承這個controller,然后重寫error方法或者errorHtml方法,或者兩個都重寫,區(qū)別是errorHtml是處理請求頭為text/html的請求發(fā)生的異常,而error是除了這個之外的其他異常。

下面是我定義的baseController,error部分返回的結(jié)果是空,還需要進(jìn)一步的研究:

	
@RestController
@RequestMapping(value = "error")
public class MyBaseErrorController extends BasicErrorController {
 
  public MyBaseErrorController(ErrorAttributes errorAttributes) {
    super(errorAttributes, new ErrorProperties());
  }
 
  @Override
  @RequestMapping(produces = {MediaType.ALL_VALUE})
  public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
 
    return new ResponseEntity<Map<String, Object>>(Result.failedResultMap(000, "未知錯誤"), HttpStatus.OK);
  }
 
  @RequestMapping(
      produces = {"text/html"}
  )
  public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
    HttpStatus status = this.getStatus(request);
    response.setStatus(status.value());
    return null;
  }
 
}

最后,對于以上問題我最后的解決方法是繼承ErrorController,然后定義errorHtml和error,更重要的是@RequestMapping注解,然后在方法中response寫入返回值,這種方式不夠優(yōu)雅:

@RestController
@RequestMapping(value = "error")
public class MyBaseErrorController implements ErrorController {
  private static final String path_default = "/error";
  @Autowired
  private ErrorAttributes errorAttributes;
  @RequestMapping(produces = {MediaType.ALL_VALUE})
  public void error(HttpServletRequest request, HttpServletResponse response) {
    setJsonError(response);
  }
  @RequestMapping(
      produces = {"text/html"}
  )
  public void errorHtml(HttpServletRequest request, HttpServletResponse response) {
    setJsonError(response);
  }
 
  @Override
  public String getErrorPath() {
    return path_default;
  }
 
  private void setJsonError(HttpServletResponse response) {
    PrintWriter writer = null;
    try {
      response.setStatus(200);
      response.setHeader("Content-type", "text/html;charset=UTF-8");
      response.setCharacterEncoding("UTF-8");
      writer = response.getWriter();
      writer.write(JSON.toJSONString(Result.getFailed("未知錯誤", null)));
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (writer != null) {
        writer.close();
      }
    }
  }
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Mybatis?Lombok使用方法與復(fù)雜查詢介紹

    Mybatis?Lombok使用方法與復(fù)雜查詢介紹

    Lombok是一種Java實用工具,可用來幫助開發(fā)人員消除Java的冗長,尤其是對于簡單的Java對象(POJO),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-10-10
  • 關(guān)于IO密集型服務(wù)提升性能的三種方式

    關(guān)于IO密集型服務(wù)提升性能的三種方式

    這篇文章主要介紹了關(guān)于IO密集型服務(wù)提升性能的三種方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Spring單數(shù)據(jù)源的配置詳解

    Spring單數(shù)據(jù)源的配置詳解

    spring數(shù)據(jù)源的配置網(wǎng)絡(luò)上有很多例子,這里我也來介紹一下單數(shù)據(jù)源配置的例子,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • JPA延遲加載no Session報錯解決分析

    JPA延遲加載no Session報錯解決分析

    這篇文章主要為大家介紹了JPA延遲加載no Session報錯解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • SpringMVC用XML方式實現(xiàn)AOP的方法示例

    SpringMVC用XML方式實現(xiàn)AOP的方法示例

    這篇文章主要介紹了SpringMVC用XML方式實現(xiàn)AOP的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • 使用synchronized關(guān)鍵字實現(xiàn)信號量的方法

    使用synchronized關(guān)鍵字實現(xiàn)信號量的方法

    在Java中,信號量(Semaphore)是一種常用的同步工具,它可以用來控制對共享資源的訪問數(shù)量,下面,我們將使用Synchronized關(guān)鍵字來實現(xiàn)一個簡單的信號量,我們的目標(biāo)是實現(xiàn)一個計數(shù)信號量,其中信號量的計數(shù)指示可以同時訪問某一資源的線程數(shù),需要的朋友可以參考下
    2024-04-04
  • Java獲取登錄用戶的IP地址示例代碼

    Java獲取登錄用戶的IP地址示例代碼

    在開發(fā)中我們經(jīng)常需要獲取用戶IP地址,通過地址來實現(xiàn)一些功能,下面這篇文章主要給大家介紹了關(guān)于Java獲取登錄用戶的IP地址的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • SpringMVC+ZTree實現(xiàn)樹形菜單權(quán)限配置的方法

    SpringMVC+ZTree實現(xiàn)樹形菜單權(quán)限配置的方法

    本篇文章主要介紹了SpringMVC+ZTree實現(xiàn)樹形菜單權(quán)限配置的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • Java實現(xiàn)二維碼QRCode的編碼和解碼與示例解析

    Java實現(xiàn)二維碼QRCode的編碼和解碼與示例解析

    本文主要介紹Java實現(xiàn)二維碼QRCode的編碼和解碼,這里給大家一個小示例以便理解,有需要的小伙伴可以參考下
    2016-08-08
  • EJB基礎(chǔ)知識(入門必看)

    EJB基礎(chǔ)知識(入門必看)

    下面小編就為大家?guī)硪黄狤JB基礎(chǔ)知識(入門必看)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06

最新評論