SpringBoot处理异常的两种方式

本文记录我在学习过程中对于SpringBoot处理异常的两种方式的理解

1. 实现HandlerExceptionResolver接⼝,定义全局异常处理器。

package com.lxs.demo.demos.exception;

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;

@Component
public class CustomHandlerExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
        e.printStackTrace();
        CustomException ce = null;
        if (e instanceof CustomException) {
            ce = (CustomException) e; //自定义异常
        } else if (e instanceof NullPointerException) {
            ce =  new CustomException("空指针异常,请联系管理员处理...");
        } else {
            ce = new CustomException("其他系统异常,请联系管理员处理...");
        }
        ModelAndView mv = new ModelAndView();
        e.getMessage(); //${e.message}
        mv.addObject("e", ce);
        mv.setViewName("error");
        return mv;
    }
}
继承了 HandlerExceptionResolver,,捕获这个异常,

然后判断这个异常的类型,

第一个是自定义异常,第二个是空指针异常,剩下的就是其他的异常

在判断完这个异常后,我这里把它存到了model里面

然后我做了一个转发,跳转到了error.jsp这个页面,这是error.jsp的页面内容,来显示e.message

下面就来进行一下测试

我写了个index.html页面      和TestController,这是代码

package com.lxs.demo.demos.web;

import com.lxs.demo.demos.exception.CustomException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;

@Controller
@RequestMapping("/test")
public class TestController {

    @RequestMapping("/one")
    public String one() {
        String s = null;
        s.trim(); //空指针异常
        return "success";
    }

    @RequestMapping("/two")
    @ResponseStatus(code = HttpStatus.BAD_REQUEST)
    public String two(String name) throws Exception {
        if ("tom".equals(name)) {
            throw new CustomException("用户名重复的自定义异常");
        }
        return "success";
    }

    @RequestMapping("/three")
    public String three() throws Exception {
        String[] s = {"a", "b", "c"};
        s[4] = "123";
        return "success";
    }

/one   /two  /three分别代表空指针,用户名重复,数组越界异常

接下来启动项目访问index.html

分别访问one,two,three出现如下页面

2.@ControllerAdvice + @ExceptionHandler,ControllerAdvice对于Controller增强

ExceptionHandler这个注解跟ModelAttribute很像,

@ModelAttribute这个注解是在所有的方法执行之前执行
@ExceptionHandler是在所有方法发生异常时执行

下面测试一下,这是我的TestController代码

package com.lxs.demo.demos.web;

import com.lxs.demo.demos.exception.CustomException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/test")
public class TestController {

    @RequestMapping("/one")
    public String one() {
        String s = null;
        s.trim(); //空指针异常
        return "success";
    }

    @RequestMapping("/two")
    @ResponseStatus(code = HttpStatus.BAD_REQUEST)
    public String two(String name) throws Exception {
        if ("tom".equals(name)) {
            throw new CustomException("用户名重复的自定义异常");
        }
        return "success";
    }

    @RequestMapping("/three")
    public String three() throws Exception {
        String[] s = {"a", "b", "c"};
        s[4] = "123";
        return "success";
    }

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

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

    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Map errorHandler(Exception ex) {
        Map map = new HashMap();
        map.put("code", 400);
        map.put("msg", ex.getMessage());
        return map;
    }


}

@ExceptionHanlder对于不同的异常做了不同的处理

下面来测试一下

上文的index.html页面不变,继续访问

访问one

此时控制台打印空指针异常

访问其他的同理,就不一一展示了

此时会发现一个问题,

@ExceptionHandler只会对当前的处理器进行处理,那么应该怎么做到全局呢

所以此时需要配合@ControllerAdvice使用

ControllerAdvice对于Controller增强,对所有的Controller都适用

这时写了一个类,这是代码

package com.lxs.demo.demos.exception;

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;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class MyControllerAdvice {

    /**
     * 全局异常捕捉处理
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Map errorHandler(Exception ex) {
        Map map = new HashMap();
        map.put("code", 400);
        map.put("msg", ex.getMessage());
        return map;
    }

    /**
     * 空指针异常
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = NullPointerException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Map errorNullHandler(NullPointerException ex) {
        Map map = new HashMap();
        map.put("code", 300);
        map.put("msg", "空指针异常");
        return map;
    }


    /**
     * 全局捕捉自定义异常(凡是抛出CustomException的异常都会走这里)
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = CustomException.class)
    public Map myErrExceptionHandler(CustomException ex) {
        Map map = new HashMap();
        map.put("code", 500);
        map.put("msg", ex.getMessage());
        return map;
    }

}

这就是一个全局异常处理器

 

下面来测试一下,我把TestController中的ExceptionHandler全部注释掉

再打开网页测试一下,在访问如图所示

好了,说到这里差不多就结束,只要把这两种方式弄清楚就行

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值