博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

springmvc 全局异常处理实践

Posted on 2021-03-17 23:29  海绵谷  阅读(127)  评论(0编辑  收藏  举报

引申

1.首先异常类Throwable 分为两种(两个子类),分别是用来标识系统错误或资源耗尽的异常类Error,与表示应用程序中错误的异常类Exception.
2.经常看到的空指针异常、数组下标越界异常、数字类型格式化异常,有共同父类(Exception)。
3.经常看到的OutOfMemoryError、StackOverflowError,有共同的父类(Error)
4.我们也可以自定义异常,通常是继承RuntimeException(运行时异常的未受检异常unchecked exception),相对而言,Exception的其他子类和Exception自身则是受检异常(checked exception),Error及其子类也是未受检异常。
5.通常我们用try...catch 来捕获异常,然后用throw 来抛出原异常或者是新异常。
6.finally 语句跟在catch后面,形如 try{ ... }catch(Exception e ){...}finally{..},finally内的代码不管有无异常发生,都会执行,具体来说:

  • 如果没有异常发生,在try内的代码执行结束后执行
  • 如果有异常发生且被catch捕获,在catch内的代码执行结束后执行。
  • 如果有异常发生但没被捕获,则在异常被抛给上层之前执行。由于finally的这个特点,它一般用于释放资源,如数据库连接、文件流等。
  • try/catch/finally语法中,catch不是必需的,也就是可以只有try/finally,表示不捕获异常,异常自动向上传递,但finally中的代码在异常发生后也执行。
  • finally语句有一个执行细节,如果在try或者catch语句内有return语句,则return语句在finally语句执行结束后才执行,但finally并不能改变返回值
  • 如果在finally中也有return语句呢?try和catch内的return会丢失,实际会返回finally中的返回值。finally中有return不仅会覆盖try和catch内的返回值,还会掩盖try和catch内的异常,就像异常没有发生一样。

javaweb 全局异常处理流程

全局异常处理实现方式

  • 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;
  • 实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器;
  • 使用@ExceptionHandler注解实现异常处理;

springmvc 全局异常处理实践一、实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器

  1. 对于异常,我们通常会处理系统级异常、业务逻辑异常、或者数据校验异常,所以对应的对于异常的处理方式,我们亦可以直接定向到错误页面或者弹出提示框。代码如下
package com.example.springmvcexception.myexception;

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.io.IOException;
import java.io.OutputStream;

/**
 * @author ngLee
 * @version 1.0
 * @Desc
 * @date 2021/3/16 21:40
 */
@Component
public class ExceptionResolve implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse response, Object o, Exception e) {
        System.out.println(httpServletRequest.getRequestURI());
        System.out.println(httpServletRequest.getRequestURL().toString());
        try {
            if(e instanceof YwException){
                String al = "<script language=JavaScript>alert('"+e.getMessage()+"')</script>";
                response.setHeader("Content-type", "text/html,charset=GBK");
                OutputStream os = response.getOutputStream();
                os.write(al.getBytes("GBK"));
                os.flush();
                os.close();
            }else if(e instanceof SystemException){
                ModelAndView mv = new ModelAndView();
                mv.addObject("status","505");
                mv.addObject("msg",e.getMessage());
                mv.addObject("data","请联系运维人员,解决问题!");
                mv.setViewName("error.html");
                return mv;
            }
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return null;
    }
}

自定义两种等级的异常类分别继承RuntimeException,使用的时候通常在代码里直接抛出,例如这样throw new SystemException("缺少网管配置");
自定义的系统级异常VO

package com.example.springmvcexception.myexception;

/**
 * @author ngLee
 * @version 1.0
 * @Desc 系统级异常
 * @date 2021/3/16 22:17
 */
public class SystemException extends RuntimeException {
    private String code;
    private String msg;
    
    public String getCode() {
        return code;
    }
    
    public void setCode(String code) {
        this.code = code;
    }
    
    public String getMsg() {
        return msg;
    }
    
    public void setMsg(String msg) {
        this.msg = msg;
    }
    
    public SystemException() {
    }
    
    public SystemException(String message) {
        this.msg = message;
    }
    
    @Override
    public String getMessage() {
        return "系统级异常:"+this.getMsg();
    }
}

自定义的业务逻辑异常VO

package com.example.springmvcexception.myexception;

/**
 * @author ngLee
 * @version 1.0
 * @Desc 业务逻辑异常,弹出提示
 * @date 2021/3/16 22:15
 */
public class YwException extends RuntimeException{
    private String code;
    private String msg;
    public YwException() {
    }
    public YwException(String message) {
        this.msg = message;
    }
    
    @Override
    public String getMessage() {
        return "业务逻辑异常:"+this.getMsg();
    }
    
    public String getCode() {
        return code;
    }
    
    public void setCode(String code) {
        this.code = code;
    }
    
    public String getMsg() {
        return msg;
    }
    
    public void setMsg(String msg) {
        this.msg = msg;
    }
}

controller层出现异常代码

package com.example.springmvcexception.controller;

import com.example.springmvcexception.myexception.SystemException;
import com.example.springmvcexception.myexception.YwException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author ngLee
 * @version 1.0
 * @Desc
 * @date 2021/3/16 21:35
 */
@Controller
public class SpringExceptionController {
    @GetMapping("/t1")
    public String test1(){
        try {
            int a = 7/0;
        }catch (Exception e){
            throw new YwException("不能为0");
        }
        
        return "test1";
    }
    @GetMapping("/t2")
    public String test2(){
        try {
            String[]  arr = {"1","2"};
            String a =  arr[2];
        }catch (Exception e){
            throw new SystemException("数组越界");
        }
        return "test1";
    }
}

实现效果

分别访问http://localhost:8085/springmvc/t2 以及 http://localhost:8085/springmvc/t1,异常处理效果如下


----**********************************-------