Spring Boot : 全局异常捕捉(三)
来源:互联网 发布:华为手机应用数据清理 编辑:程序博客网 时间:2024/06/08 13:46
前言
在写 Spring Boot : 自动JSON转换和热部署(二) 时本来想把全局异常捕捉加上的,但是不知道为什么测试一直没成功.今天又看了下全局异常捕捉@ControllerAdvice 和 @ExceptionHandler 两个标签. 参考 : Spring3.2新注解@ControllerAdvice , 在spring加载bean的时候一定要把全局异常捕捉类加载进来,否则是不成功的.
目录
- 前言
- 目录
- 下面是反面教程
- 修复方案
下面是反面教程 :
基于之前的写法创建MyDefaultExceptionHandler类:
package cn.milo.controllor;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;/** * Created by admin on 2017/6/25. */@ControllerAdvicepublic class MyDefaultExceptionHandler { @ExceptionHandler(value = Exception.class) // @ExceptionHandler(value={RuntimeException.class,MyRuntimeException.class}) 指定具体要处理的异常 // @ExceptionHandler//处理所有异常 @ResponseBody //在返回自定义相应类的情况下必须有,这是@ControllerAdvice注解的规定 public String exceptionHandler() { System.out.println("DefaultExceptionHandler.exceptionHandler()"); return "DefaultExceptionHandler Running"; }}
在SampleController中添加 :
package cn.milo.controllor;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;/** * Created by admin on 2017/6/25. */@Controller/*@RestController is a stereotype annotation that combines @ResponseBody and @Controller.意思是:@RestController注解相当于@ResponseBody + @Controller合在一起的作用。 */@EnableAutoConfigurationpublic class SampleController { @RequestMapping("/demo10") public String demo104Exception() { int k = 1/0; return "1"; }/*ExceptionHandler 不是一定在@ControllerAdvice 标注的类中才生效.如将注释放开,异常可以被捕捉.且捕捉顺序如下:同一个异常被局部范围异常处理器和全局范围异常处理器同时覆盖,会选择小范围的局部范围处理器同一个异常被小范围的异常类和大范围的异常处理器同时覆盖,会选择小范围的异常处理器*/// @ExceptionHandler(Exception.class)// public void ExceptionHandler(){// System.out.println("捕捉到异常了.....");// }}
请求 : http://localhost:8080/demo10 控制台信息如下 :
2017-06-28 18:27:18.207 ERROR 12536 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ArithmeticException: / by zero] with root causejava.lang.ArithmeticException: / by zero at cn.milo.controllor.SampleController.demo104Exception(SampleController.java:83) ~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_17] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_17] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_17] at java.lang.reflect.Method.invoke(Method.java:601) ~[na:1.7.0_17] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.0.28.jar:8.0.28] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217) ~[tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) [tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) [tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) [tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) [tomcat-embed-core-8.0.28.jar:8.0.28] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) [tomcat-embed-core-8.0.28.jar:8.0.28] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_17] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_17] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.28.jar:8.0.28] at java.lang.Thread.run(Thread.java:722) [na:1.7.0_17]
说明异常根本没有被捕捉啊.分析原因是下边这段代码,如果在SampleController.java中添加了如下main方法,那么无论是执行main启动springboot还是通过mvn spring-boot:run方式启动springboot最终Spring只会加载SampleController.java这个类,我们写的MyDefaultExceptionHandler.java完全不会被加载.但是这种情况下如果把SampleController.java最下放的ExceptionHandler那段代码放开却可以捕捉到异常.
public static void main(String[] args) throws Exception { SpringApplication.run(SampleController.class, args);}
修复方案 :
创建一个Application.java,并去掉SampleController中的main方法.
package cn.milo.controllor;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * Created by admin on 2017/6/28. */@SpringBootApplicationpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
注意:SpringApplication.run(Application.class, args); 红色部分.这样写spring才会加载MyDefaultExceptionHandler.java, 原理后续我搞清楚Spring Boot再介绍吧,哈哈
正确的测试结果:
补充 : 如果MyDefaultExceptionHandler.java和SampleController.java在同一包下,则Application上方注解写为@SpringBootApplication就可以了.如果不同包的话要写成@SpringBootApplication(scanBasePackages = {“cn.milo.controllor”,”cn.milo.exception”}),因为Application.java如果注解为@SpringBootApplication,main方法默认只加载本包内的controller到spring.
- Spring Boot : 全局异常捕捉(三)
- spring boot全局异常捕捉
- spring boot 全局异常捕捉
- 5. 全局异常捕捉【从零开始学Spring Boot】
- (5)全局异常捕捉【从零开始学Spring Boot】
- 5. 全局异常捕捉【从零开始学Spring Boot】
- (5)全局异常捕捉【从零开始学Spring Boot】
- spring boot 全局异常
- Spring Boot05 之全局异常捕捉
- spring mvc 的全局异常捕捉
- spring boot 全局异常捕获
- Spring boot 全局异常处理
- spring boot全局异常处理
- 关于捕捉全局异常
- springboot全局异常捕捉
- Android全局异常捕捉
- 捕捉全局异常
- SpringBoot全局异常捕捉
- crond和crontab调研
- vue v-if v-else v-else-if
- 【批量生成10万条sql数据库数据+IO流的使用】生成简单sql插入语句大量数据,以及输出流生成文件2017年
- 5.1 常用工具之ADB介绍与快速入门
- 优秀的开源项目
- Spring Boot : 全局异常捕捉(三)
- 关于常用编译预处理指令的问题
- 操作系统的运行机制
- PHP sprintf()函数详解
- LeetCode:8. String to Integer (atoi)
- MySQL 存储过程和函数以及数据恢复和备份
- 接口和抽象类
- React Native原生模块向JS模块传递数据的几种方式(Android)
- Android页面最简单的跳转出现的问题