亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術(shù)文章
文章詳情頁

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

瀏覽:2日期:2023-09-10 14:42:48

集中異常處理

以下代碼可在github獲取: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中拋出,拋出也沒法捕獲

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

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

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'); // 這里拋出的異常并不能被捕獲,會直接在后臺拋出,相當于回掉函數(shù),請求結(jié)果已經(jīng)返回 }}

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

方式二:ExceptionFilter

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

@Controllerpublic 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去處理,如果獲取到的異常不是我們自定義的異常或者他的子類的話,就會返回500錯誤(在這個示例前,我以為所有的filter都是這樣的,后來實踐后發(fā)現(xiàn)并不是這樣😂)。

@Componentpublic 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)常會看到:

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

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

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

@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)容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 91久久婷婷国产综合精品青草 | 国产三级日本三级在线播放 | 欧美日韩一日韩一线不卡 | 91在线视频网址 | 国产成人精品免费视频大全可播放的 | 麻豆传媒视频入口 | 亚洲精品午夜一区二区在线观看 | 久久精品国产99久久香蕉 | 日本在线不卡免费视频一区 | 欧美蜜桃臀在线观看一区 | 欧美亚洲精品在线 | 亚洲在线观看 | 久久线看观看精品香蕉国产 | 国产成人黄网址在线视频 | 97国产视频 | 亚洲黄色在线网站 | wwww亚洲| 欧美一级亚洲一级 | 国产黄色一级毛片 | 国产精品入口麻豆免费观看 | 99久久国产综合精品成人影院 | 欧美草比视频 | 国产大片中文字幕在线观看 | 久久亚洲精品视频 | 一级毛片一级毛片一级毛片一级毛片 | 色婷婷综合久久久 | 中文字幕亚洲一区二区v@在线 | 欧美高清视频www夜色资源 | 一本大道一卡2卡三卡4卡麻豆 | 国产在线一区二区杨幂 | 免费国产成高清人在线视频 | 成人在线你懂的 | 二级黄绝大片中国免费视频0 | fc2成人免费人成在线观看播放 | 黑人巨大vs北条麻妃在线播放 | 日韩亚洲欧美在线爱色 | 中文字幕在线播放第一页 | 精品一区二区三区影院在线午夜 | 中文字幕在线永久 | 日本www色视频成人免费免费 | 久久精品国产精品亚洲 |