SpringMVC 异常处理

目录

1、@ExceptionHandler-处理局部异常

2、HandlerExceptionResolver-处理全局异常

3、SimpleMappingExceptionResolver-处理全局异常

4、使用@ControllerAdvice+@ExceptionHandler


在 Spring MVC 应用的开发中,不管是操作底层数据库,还是业务层或控制层,都会不可避免地遇到各种可预知的、不可预知的异常。我们需要捕捉处理异常,才能保证程序不被终止。

Spring MVC 有以下 3 种处理异常的方式:

  1. 使用 Spring MVC 提供的简单异常处理器 SimpleMappingExceptionResolver
  2. 实现 Spring 的异常处理接口 HandlerExceptionResolver,自定义自己的异常处理器。
  3. 使用 @ExceptionHandler 注解实现异常处理

springmvc中,异常处理的思路

SpringMVC 异常处理_第1张图片

上图所示,系统的daoservicecontroller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。

springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。明白了springmvc中的异常处理机制,下面就开始分析springmvc中的异常处理。

1、@ExceptionHandler-处理局部异常

局部异常处理仅能处理指定 Controller 中的异常。

下面使用 @ExceptionHandler 注解实现。//注意:该注解不是加在产生异常的方法上,而是加在处理异常的方法上。

定义一个处理过程中可能会存在异常情况的 submit 方法,当 i=0 时会产生算术运算异常,在同一个类中定义处理异常的方法controllerExceptionHandler,捕获运算异常。

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author swadian
 * @date 2022/2/21
 * @Version 1.0
 */
@Controller
@RequestMapping
public class ExceptionController {

    @RequestMapping("/submit") // 抛错方法
    public String submit(HttpServletRequest req,
                         HttpServletResponse resp) throws Exception {
        String num = req.getParameter("num");
        System.out.println(10 / Integer.valueOf(num));
        return "success";
    }

    @ExceptionHandler({ArithmeticException.class}) //捕获运算异常
    public String controllerExceptionHandler(Exception e) {
        System.out.println("打印错误信息 ===> ArithmeticException:" + e);
        // 跳转到指定页面
        return "error";
    }
}

异常页面 error.jsp 代码如下。

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>



    
    错误页面


    发生算术运算异常,请重新输入数据!

工程中web.xml配置如下




    
    
        DispatcherServlet
        org.springframework.web.servlet.DispatcherServlet
        
        
            contextConfigLocation 
            classpath:springmvc-servlet.xml
        
        
        1
    
    
        DispatcherServlet
        / 
    

工程中springmvc-servlet.xml配置如下




    
    
    
    
    

    
    
        
        
        
        
    

整个项目的路径如下:

SpringMVC 异常处理_第2张图片

启动项目,访问submit方法,程序会进入到错误处理方法,最终跳转到错误页面

SpringMVC 异常处理_第3张图片

@ExceptionHandler 注解定义的方法优先级问题:例如发生的是 NullPointerException,但是声明的异常有 RuntimeException 和 Exception,这时候会根据异常的最近继承关系找到继承深度最浅的那个@ExceptionHandler 注解方法,即标记了 RuntimeException 的方法。

被 @ExceptionHandler 标记为异常处理方法,不能在方法中设置别的形参。但是可以使用 ModelAndView 向前台传递数据。

使用局部异常处理,仅能处理某个 Controller 中的异常,若需要对所有异常进行统一处理,可使用以下两种方法。

2、HandlerExceptionResolver-处理全局异常

Spring MVC 通过 HandlerExceptionResolver 处理程序异常,包括处理器异常、数据绑定异常以及控制器执行时发生的异常。HandlerExceptionResolver 仅有一个接口方法,源码如下。

public interface HandlerExceptionResolver {
    ModelAndView resolveException(HttpServletRequest var1, 
                                  HttpServletResponse var2, 
                                  Object var3, 
                                  Exception var4);
}

发生异常时,Spring MVC 会调用 resolveException() 方法,并转到 ModelAndView 对应的视图中,返回一个异常报告页面反馈给用户。

创建一个 HandlerExceptionResolver 接口的实现类 MyExceptionHandler,代码如下。

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * @author swadian
 * @date 2022/2/21
 * @Version 1.0
 */
@Component
public class MyExceptionHandler implements HandlerExceptionResolver {
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse,
                                         Object o,
                                         Exception e) {
        Map model = new HashMap();
        model.put("errorMessage", "程序运行出错");
        //根据不同错误转向不同页面(统一处理),即异常与View的对应关系
        if (e instanceof ArithmeticException) {
            return new ModelAndView("error", model);
        }
        return new ModelAndView("other_error", model);
    }
}

添加新的错误页面other_error.jsp如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>



    
    系统正忙页面


    errorMessage:${errorMessage} 
系统正忙,请稍后再试!

更改ExceptionController类,新增空指针异常

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author swadian
 * @date 2022/2/21
 * @Version 1.0
 */
@Controller
@RequestMapping
public class ExceptionController {
    @RequestMapping("/submit") // 抛错方法
    public String submit(HttpServletRequest req,
                         HttpServletResponse resp) throws Exception {
        String num = req.getParameter("num");
        System.out.println("输入的参数长度为:" + num.length());//空指针异常
        System.out.println(10 / Integer.valueOf(num));
        return "success";
    }
}

启动项目,访问submit方法,不输入参数,程序会进入到错误处理方法,最终跳转到其他错误页面

SpringMVC 异常处理_第4张图片

3、SimpleMappingExceptionResolver-处理全局异常

全局异常处理可使用 SimpleMappingExceptionResolver 来实现。它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常。

在 springmvc-servlet.xml 中配置全局异常,代码如下。

    
        
        
        
        
        
        
            
                error
                
            
        
    

启动项目,访问submit方法,不输入参数,程序会进入到错误处理方法,最终跳转到其他错误页面

SpringMVC 异常处理_第5张图片

4、使用@ControllerAdvice+@ExceptionHandler

注意该方式需要开启注解支持

    
    
    
    
    

全局异常处理类:MyExceptionHandler.java

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.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

/**
 * @author swadian
 * @date 2022/2/21
 * @Version 1.0
 */
@ControllerAdvice
public class MyExceptionHandler {

    /**
     * 处理异常:捕获数据运算异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler({ArithmeticException.class}) //捕获所有异常 Exception.class
    @ResponseBody //返回字符串而非视图
    @ResponseStatus(HttpStatus.OK)
    public String arithmeticExceptionHandler(Exception e) {
        System.out.println("打印错误信息 ===> ArithmeticException:" + e);
        //返回错误信息
        return "错误信息:" + e.getMessage();
    }
}

测试类

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author swadian
 * @date 2022/2/21
 * @Version 1.0
 */
@RestController
@RequestMapping
public class SubmitController {
    //计算
    @RequestMapping("/submit")
    public String submit(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String num = request.getParameter("num");
        Integer i = 10 / Integer.valueOf(num);
        return "计算成功,结果为:" + i;
    }
}

启动程序,参数输入为0,得到如下处理结果:

SpringMVC 异常处理_第6张图片

上文说到 @ ExceptionHandler 需要进行异常处理的方法必须与出错的方法在同一个 Controller里面。那么当代码加入了 @ControllerAdvice,则不需要必须在同一个controller 中了。

这也是 Spring 3.2 带来的新特性。从名字上可以看出大体意思是控制器增强。

也就是说,@controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。 请确保此WebExceptionHandle 类能被扫描到并装载进 Spring 容器中。

若在其他的由@Controller标记的Handler类中的Handle方法抛出异常,且没有在Handler类中定义@ExceptionHandler方法,则会去由@ControllerAdvice标记的类中去找,若也找不到,则在页面抛出异常。

问题:Tomcat方式启动和Application方式启动有什么区别呢?

https://www.jb51.net/article/211409.htm

你可能感兴趣的:(springmvc,springmcv,异常处理)