SpringMVC基于注解使用:异常处理

314 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情

一、springmvc内置异常处理解析器

在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异常需要处理。每个过程都单独处理异常,系统的代码耦合度高,工作量大且不好统一,维护的工作量也很大。

那么,能不能将所有类型的异常处理从各处理过程解耦出来,这样既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护?答案是肯定的。下面将介绍使用Spring MVC统一处理异常的解决和实现过程。

在SpringMVC中拥有一套非常强大的异常处理机制,SpringMVC通过HandlerExceptionResolver处理程序的异常,包括请求映射,数据绑定以及目标方法的执行时发生的异常。

image.png 在容器启动好,进入DispatcherServlet之后,会对HandlerExceptionResolver进

行初始化操作:

image.png 会默认的从DispatcherServlet.properties中找到对应的异常处理类:

#默认的处理类
org.springframework.web.servlet.HandlerExceptionResolver=
#处理@ExceptionHandler
org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
#解析@ResponseStatus注释类型的异常
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
#按照不同类型分别对异常进行解析
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
        
        
        

AbstractHandlerMethodExceptionResolver是ExceptionHandlerExcpetionResolver父类

SimpleMappingExceptionResolver:通过配置的异常类和view的对应关系解析异常

1-1、使用@ExceptionHandler操作Exception

为了给用户一个好的体验,因此我们在写写代码的时候不能将错误信息直接给用户显示出来,需要进行一下处理,比如下面这样:

控制器方法需要必传一个参数:

image.png

直接浏览器不传name参数如下:

image.png

1-1-1、使用@ExceptionHandler处理

image.png

浏览器访问可以看到如下页面

image.png 这样我们就可以对这个error.jsp进行一些处理,比如404 500 等一些错误的页面UI处理。

小结

我们在当前控制器中添加了@ExceptionHandler,也只能处理当前控制器的错误信息,如果需要处理所有控制器的错误信息,我们还需要进行统一错误信息。

二、统一异常处理

@ControllerAdvice 是Spring3.2提供的新注解,它是对Controller的增强,可对controller中被 @RequestMapping注解的方法加一些逻辑处理:

  1. 全局异常处理

  2. 全局数据绑定

  3. 全局数据预处理

@ExceptionHandler

加在Controller中 :只处理当前控制器的异常,优先级比全局高

加在ControllerAdvice中 :处理全局异常

2-1、使用@ControllerAdvice创建全局异常处理类

image.png 通过上图可以看到,目前有两个异常处理类,分别是控制器内部的还有使用@ControllerAdvice创建的全局异常处理类,那么如果这个时候发生异常是哪个异常来处理呢?下面来测试一下

image.png

特别说明一下,如果控制器内没有使用@ExceptionHandler注解的方法,会自动使用全局的错误异常方法

2-1-1、异常会被更精准的异常类处理

如果控制器内,没有定义异常处理方法,这个时候如果在全局异常处理类内定义了更加精准的异常处理方法,则会由更精准的异常处理方法处理。

image.png

2-1-2、异常处理优先级别

1、控制器异常 优先级最高 就近原则
2、全局异常中具体异常 如果控制器中没有定义异常 精准原则
3、全局异常 当异常没有满足以上两种情况,会交给全局异常处理

就近精准异常>就近异常>全局精准异常>全局异常

在实际项目中,一般只需要定义全局异常即可。

三、根据请求端请求方式自动返回异常处理信息

上面叙述的是返回视图层的方式来返回异常信息,但是现在项目有很多使用了Json的返回格式,因此我们的异常处理就需要自动判断应该返回哪种格式的数据。

3-1、如何判断请求类型

3-1-1、可以通过请求头来判断

如果Content-Type="application/json" 则为json请求

//-------------通过请求头判断是否包含application/json判断是否是json----------------begin
//如果不等于-1则代表为json请求
int accept = request.getHeader("Accept").indexOf("application/json");
//-------------通过请求头判断是否包含application/json判断是否是json----------------end

3-1-2、通过类和方法上的注解判断

如果类上的注解是@RestController或者方法上的注解是@ResponseBody,则为json请求

//---------通过注解判断是否是json-----------begin
//获取类上面的注解
RestController restControllerestController = handle.getClass().getAnnotation(RestController.class);
//获取方法上的注解
ResponseBody responseBody = handle.getMethod().getAnnotation(ResponseBody.class);
//---------通过注解判断是否是json-----------end

image.png 上图即为处理代码。

测试

1、使用页面的请求方式

image.png

2、使用Json请求

image.png

四、404异常处理

4-1、首先在web.xml配置error-page

<error-page>
    <error-code>404</error-code>
    <location>/errpage/404.html</location>
</error-page>

4-2、创建404错误页面

image.png

4-3、创建spring-mvc静态资源映射

image.png

4-4、测试

image.png