网站的异常处理最好是解耦的,并且都放在一个地方集中管理。
比如访问权限不够,跳转到指定页面,比如访问的页面不存在,或者404 500之类的错误。
本文介绍Spring的@ControllerAdvice来对这些异常统一进行处理。
import java.io.IOException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.NoHandlerFoundException; @ControllerAdvice(annotations = {RestController.class}) public class ExceptionReaper { private static final Logger logger = LogManager.getLogger(ExceptionReaper.class); @ExceptionHandler(value = { IOException.class , RuntimeException.class }) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ModelAndView exception(Exception exception, WebRequest request) { logger.info("Catch an exception", exception); return new ModelAndView("error/errorPage"); } @ExceptionHandler(value = { NoHandlerFoundException.class }) @ResponseStatus(HttpStatus.NOT_FOUND) public ModelAndView noMapping(Exception exception, WebRequest request) { logger.info("No mapping exception", exception); return new ModelAndView("error/notFound"); } }
网上大部分的异常处理大致分为这么几种
1.web.xml配置对404和500之类的错误进行处理,比如访问不存在页面时跳转到一个静态页面,缺点是必须静态页面而且不太好用
<error-page> <error-code>404</error-code> <location>/building.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/error.jsp</location> </error-page>
2.配置exception handler,这样的话每个controller都要配置异常处理,或者在一个super controller里配置异常处理,所有controller继承他,缺点也是显而易见的。
@Controller public class MyController { @ExceptionHandler(RuntimeException.class) @ResponseBody public String runtimeExceptionHandler(RuntimeException runtimeException) { logger.error("error", runtimeException); return "error"; } }
3.在applicationContext里面配置SimpleMappingExceptionResolver
@Bean public SimpleMappingExceptionResolver exceptionResolver() { SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver(); Properties exceptionMappings = new Properties(); exceptionMappings.put("java.lang.Exception", "error/errorPage"); exceptionMappings.put("java.lang.RuntimeException", "error/errorPage"); exceptionResolver.setExceptionMappings(exceptionMappings); Properties statusCodes = new Properties(); statusCodes.put("error/404", "404"); statusCodes.put("error/error", "500"); exceptionResolver.setStatusCodes(statusCodes); return exceptionResolver; }
上面这三种处理方法比较常见,但是我觉得都不如@ControllerAdvice来的方便好用
完全可以把@ExceptionHandler放在@ControllerAdvice统一处理,不用每个controller都配置
import java.io.IOException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.NoHandlerFoundException; @ControllerAdvice(annotations = {RestController.class}) public class ExceptionReaper { private static final Logger logger = LogManager.getLogger(ExceptionReaper.class); @ExceptionHandler(value = { IOException.class , RuntimeException.class }) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ModelAndView exception(Exception exception, WebRequest request) { logger.info("Catch an exception", exception); return new ModelAndView("error/errorPage"); } @ExceptionHandler(value = { NoHandlerFoundException.class }) @ResponseStatus(HttpStatus.NOT_FOUND) public ModelAndView noMapping(Exception exception, WebRequest request) { logger.info("No mapping exception", exception); return new ModelAndView("error/notFound"); } }
@ControllerAdvice(annotations = {RestController.class}) 配置你需要拦截的类,
@ControllerAdvice(basePackages = "com.demo") 这也可以
然后下面放@ExceptionHandler作为全局的异常处理
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 告诉浏览器这是什么错误类型
最后就可以记录日志,根据需求做一些处理,返回对应的ModelAndView跳转到对应的错误页面
需要注意的是,上面这些配置,只能配置你的程序中抛出的错误
1.如果是用户请求了一个不存在的页面,没有对应的@RequestMapping,此时Spring的DispatcherServlet就会处理掉返回404,不会进入任何一个controller
2.还有比如spring security之类的权限管理模块,如果用户的密码正确,但是该账户的权限组没有权限访问当前页面,此时权限模块会有自己的AccessDeniedHandler处理,也不会进入刚才配置的@ControllerAdvice
所以对于2中的情况,一般通过权限管理模块提供的方法去处理异常
比如spring security中
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/resources/**") .permitAll() .anyRequest() .authenticated() .and() .exceptionHandling() .accessDeniedPage("/error/accessDenied.html") .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll(); }
对于1中的情况,我们可以配置Spring在没有对应的@RequestMapping时,不要自行处理,让他抛出一个NoHandlerFoundException的异常,从而让我们配置的@ControllerAdvice进行统一处理
如果是xml风格的配置,可以在DispatcherServlet对应的配置文件中配置
如果是之前介绍的class风格的配置,可以这样配置:
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);//for NoHandlerFoundException
import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.request.RequestContextListener; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; public class WebInit implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) throws ServletException { // Create the 'root' Spring application context AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.scan("com.demo"); // Manage the lifecycle of the root application context container.addListener(new ContextLoaderListener(rootContext)); // Listener that exposes the request to the current thread container.addListener(new RequestContextListener()); // Create the dispatcher servlet's Spring application context AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext(); // Register and map the dispatcher servlet DispatcherServlet dispatcherServlet = new DispatcherServlet(dispatcherContext); dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);//for NoHandlerFoundException ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", dispatcherServlet); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } }
网站的异常处理基本都能实现了
以上
相关推荐
唯一不同的加入了统一错误处理,为了方便开发人员开发,所有错误码用一张表存在数据库中,然后由应用将整表缓存,缓存采用的spring自带的cache,开发中所有错误包括系统异常在Controller直接抛出即可。之所以缓存...
在Spring MVC框架中,异常处理是一项关键任务,它确保了应用程序在遇到错误或异常时能够以优雅的方式响应,提供统一的错误信息,并保持代码的整洁和模块化。本篇文章将详细探讨Spring MVC处理异常的三种主要方法:...
通过这种方式,我们可以为整个应用程序提供统一的异常处理策略,而无需在每个控制器中重复代码。 此外,Spring MVC还支持使用`HandlerExceptionResolver`接口来自定义异常解析器。实现这个接口并将其注册到Spring的...
Spring Boot 统一异常处理最佳实践拓展篇 在 Spring Boot 中,统一异常处理是非常重要的,今天我们将介绍 Spring Boot 统一异常处理最佳实践的拓展篇。之前我们已经了解了基本的统一异常处理思路,现在我们将继续...
SpringBoot逻辑异常统一处理方法 在本文中,我们将探讨 SpringBoot 逻辑异常统一处理方法,该方法主要介绍了如何在 SpringBoot 项目中实现逻辑异常的统一处理。通过示例代码,我们将展示如何创建一个异常处理核心子...
"Spring Boot中使用AOP统一处理web层异常的方法" 本文主要介绍了在Spring Boot中使用AOP(Aspect-Oriented Programming,面向方面编程)来统一处理web层异常的方法。该方法可以使得系统在出现异常时能够正确地处理...
通过 @ExceptionHandler 或自定义 ExceptionResolver,可以统一处理 Controller 中抛出的异常。 总结: Spring MVC 中的 Controller 配置方式主要有注解式和 XML 配置两种。随着 Spring 的发展,注解式配置因其简洁...
Spring Boot作为一款流行的Java开发框架,提供了便捷的方式来实现统一异常处理。本文将深入探讨如何在Spring Boot中进行全局异常处理。 首先,Spring Boot默认提供了一个“error”映射,但其提供的错误页面并不适合...
统一异常处理就是将所有可能抛出的异常集中处理,提供一个全局的、一致的错误反馈,提高用户体验并简化代码结构。 1. **Maven配置** Maven的pom.xml文件是项目的核心,它定义了项目的依赖关系。为了使用SpringMVC...
还有`@ExceptionHandler`用于全局处理异常,提供统一的错误页面或API响应。 综上所述,Spring MVC的Controller支持在一个类中定义多个方法,每个方法对应不同的HTTP请求。这使得代码组织清晰,易于维护。通过灵活...
局部异常处理机制可以在 Controller 中使用 @ExceptionHandler 注解来处理异常。例如,我们可以定义一个 ResponseBean 对象来统一响应异常,定义一个 ExceptionEnum 枚举来表示不同的异常类型。 五、优雅地使用异常...
主要给大家介绍了关于Spring MVC Controller返回值及异常的统一处理方法,文中通过示例代码介绍的非常详细,对大家的学习或者使用Spring MVC具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
Spring Boot默认使用`BasicErrorController`来处理未被捕获的异常,产生如“Whitelabel Error Page”所示的错误页面。我们可以自定义一个`ErrorController`来覆盖默认行为: ```java @Slf4j @RestController public...
在Spring中,异常处理主要是通过AOP(面向切面编程)来实现的,它允许我们在不修改原有业务代码的情况下,对程序运行过程中的异常进行统一管理。 【描述】:“Spring异常处理共5页.pdf.zip” 描述中的“共5页”...
当Controller方法抛出异常时,标注了`@ExceptionHandler`的方法会被调用,可以统一处理错误并返回合适的响应。 10. `@InitBinder`:允许在请求处理之前对数据绑定进行自定义配置,如设置日期格式、排除某些字段等。...
在Spring MVC框架中,错误处理是一项重要的功能,它能够帮助我们统一处理应用中的异常情况,从而为用户提供更加友好的错误信息和用户体验。在Spring MVC 3.2版本中,`@ControllerAdvice`注解的引入极大地简化了全局...
创建一个全面的Spring Boot应用,涵盖了多个关键领域,包括RESTful接口、数据库交互、用户认证、分布式Token的实现(JWT)、Redis缓存操作、日志记录以及统一异常处理。下面将详细阐述这些知识点。 1. **Spring ...
在实际项目中,处理异常是必不可少的一部分,Spring Boot为此提供了强大的异常处理机制。本篇将深入探讨Spring Boot的异常处理器,帮助你更好地理解和运用。 1. **Spring Boot异常处理基础** Spring Boot默认提供...