Spring
局部异常处理器-json
static class Controller1 {
public void foo() {
}
@ExceptionHandler
@ResponseBody
public Map<String, Object> handle1(ArithmeticException arithmeticException) {
// 局部异常处理器-json
return ImmutableMap.of("error", arithmeticException.getMessage());
}
}
@SneakyThrows
public static void test1() {
ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver();
resolver.setMessageConverters(CollUtil.newArrayList(new MappingJackson2HttpMessageConverter()));
resolver.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
HandlerMethod handlerMethod = new HandlerMethod(new Controller1(), Controller1.class.getMethod("foo"));
ArithmeticException arithmeticException = new ArithmeticException("模拟当前方法抛出一个异常");
resolver.resolveException(request, response, handlerMethod, arithmeticException);
System.out.println(new String(response.getContentAsByteArray(), StandardCharsets.UTF_8));
}
局部异常处理器-ModelAndView
@ExceptionHandler
public ModelAndView handle2(ArithmeticException arithmeticException) {
// 局部异常处理器-ModelAndView
return new ModelAndView("handle2", ImmutableMap.of("error", arithmeticException.getMessage()));
}
@SneakyThrows
public static void test2() {
ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver();
resolver.setMessageConverters(CollUtil.newArrayList(new MappingJackson2HttpMessageConverter()));
resolver.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
HandlerMethod handlerMethod = new HandlerMethod(new Controller1(), Controller1.class.getMethod("foo"));
ArithmeticException arithmeticException = new ArithmeticException("模拟当前方法抛出一个异常");
ModelAndView modelAndView = resolver.resolveException(request, response, handlerMethod, arithmeticException);
System.out.println(modelAndView.getViewName());
System.out.println(modelAndView.getModel());
}
局部异常处理器-嵌套异常
@ExceptionHandler
@ResponseBody
public Map<String, Object> handle3(IOException ioException) {
// 局部异常处理器-json
return ImmutableMap.of("error", ioException.getMessage());
}
@SneakyThrows
public static void test3() {
ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver();
resolver.setMessageConverters(CollUtil.newArrayList(new MappingJackson2HttpMessageConverter()));
resolver.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
HandlerMethod handlerMethod = new HandlerMethod(new Controller1(), Controller1.class.getMethod("foo"));
Exception exception = new Exception("e1", new RuntimeException("e2", new IOException("e3")));
resolver.resolveException(request, response, handlerMethod, exception);
System.out.println(new String(response.getContentAsByteArray(), StandardCharsets.UTF_8));
}
局部异常处理器-带参
@ExceptionHandler
@ResponseBody
public Map<String, Object> handle4(Exception e, HttpServletRequest request) {
System.out.println("=======>" + request);
// 局部异常处理器-json
return ImmutableMap.of("error", e.getMessage());
}
@SneakyThrows
public static void test4() {
ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver();
resolver.setMessageConverters(CollUtil.newArrayList(new MappingJackson2HttpMessageConverter()));
resolver.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
HandlerMethod handlerMethod = new HandlerMethod(new Controller1(), Controller1.class.getMethod("foo"));
Exception exception = new Exception("e4");
resolver.resolveException(request, response, handlerMethod, exception);
System.out.println(new String(response.getContentAsByteArray(), StandardCharsets.UTF_8));
}
全局异常处理器
@Configuration
public class WebConfig {
@ControllerAdvice
public static class MyControllerAdvice {
@ExceptionHandler
@ResponseBody
public Map<String, Object> handle(Exception e) {
System.out.println("全局异常处理...");
// 全局异常处理器-json
// 局部异常处理器优先于全局异常处理器
return ImmutableMap.of("error", e.getMessage());
}
}
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
return new MappingJackson2HttpMessageConverter();
}
@Bean
public ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver(MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter) {
ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver();
resolver.setMessageConverters(CollUtil.newArrayList(mappingJackson2HttpMessageConverter));
return resolver;
}
}
@SneakyThrows
public static void test5() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(WebConfig.class);
ExceptionHandlerExceptionResolver resolver = applicationContext.getBean(ExceptionHandlerExceptionResolver.class);
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
HandlerMethod handlerMethod = new HandlerMethod(new Controller1(), Controller1.class.getMethod("foo"));
ArithmeticException arithmeticException = new ArithmeticException("模拟当前方法抛出一个异常");
resolver.resolveException(request, response, handlerMethod, arithmeticException);
System.out.println(new String(response.getContentAsByteArray(), StandardCharsets.UTF_8));
}
Tomcat
Tomcat默认异常页面
@Configuration
public class WebConfig2 {
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
@Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
@Bean
public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet) {
return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
}
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return new RequestMappingHandlerMapping();
}
/**
* 默认的RequestMappingHandlerAdapter不带jackson转换器
*/
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
RequestMappingHandlerAdapter handlerAdapter = new RequestMappingHandlerAdapter();
handlerAdapter.setMessageConverters(CollUtil.newArrayList(new MappingJackson2HttpMessageConverter()));
return handlerAdapter;
}
@Controller
static class MyController {
@RequestMapping("test")
public ModelAndView test() {
int i = 1 / 0;
return null;
}
}
}
启动服务
public class TestTomcatExceptionHandler {
public static void main(String[] args) {
AnnotationConfigServletWebServerApplicationContext applicationContext = new AnnotationConfigServletWebServerApplicationContext(WebConfig2.class);
RequestMappingHandlerMapping requestMappingHandlerMapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
requestMappingHandlerMapping.getHandlerMethods().forEach((RequestMappingInfo k, HandlerMethod v) -> {
System.out.println("映射路径:" + k + "\t方法信息:" + v);
});
}
}
异常处理
添加异常地址
TomcatServletWebServerFactory实现了ErrorPageRegistry
// 修改Tomcat服务器默认错误地址
@Bean
public ErrorPageRegistrar errorPageRegistrar() {
return new ErrorPageRegistrar() {
@Override
public void registerErrorPages(ErrorPageRegistry webServerFactory) {
// 出现错误,会使用请求转发即forward(请求栏地址不变)跳转到此地址 如果没有此视图就会显示404
webServerFactory.addErrorPages(new ErrorPage("/error"));
}
};
}
@Bean
public ErrorPageRegistrarBeanPostProcessor errorPageRegistrarBeanPostProcessor() {
return new ErrorPageRegistrarBeanPostProcessor();
}
添加自定义视图
@ResponseBody
@RequestMapping("error")
public Map<String, Object> error(HttpServletRequest request) {
Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
return ImmutableMap.of("error", throwable.getMessage());
}
使用springmvc自带的视图
@Bean
public BasicErrorController basicErrorController() {
/**
* Spring提供的error视图 里面既有json返回,也有ModelAndView的返回
* 用rest请求会返回json
* 浏览器请求默认还是tomcat的那个错误视图(因为找不到/error对应的视图 可以自定义)
*/
ErrorProperties errorProperties = new ErrorProperties();
// 返回数据中包含错误信息
errorProperties.setIncludeException(true);
return new BasicErrorController(new DefaultErrorAttributes(), errorProperties);
}
@Bean
public View error() {
return new View() {
@Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("<h3>服务器内部错误:" + JSONObject.toJSONString(model) + "</h3>");
}
};
}
@Bean
public ViewResolver viewResolver() {
// Bean名字就是视图名
return new BeanNameViewResolver();
}