springmvc、 springboot 项目全局异常处理
异常在项目中那是不可避免的,通常情况下,我们需要对全局异常进行处理,下面介绍两种比较常用的情况。
准备工作:
在捕获到异常的时候,我们通常需要返回给前端错误码,错误信息等,所以我们需要手动封装一个jsonData对象,这里为了方便,我直接通过返回布尔类型来进行判断成功或失败,在实际的项目中更多是返回状态码 比如 0、1 、404 、500 等,在这里不影响我们演示。
jsondata对象
自定义一个异常 (注意需要继承RuntimeException,因为在spring中仅有RuntimeException支持事务)
情况一、对全局进行捕获,并统一返回json数据
我们通过@ControllerAdvice的方式来捕获全局异常
主要代码如下:
import com.me.exception.RbacException; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @ControllerAdvice @Slf4j public class ExceptionHandReturnJson { private final String UNKNOW_EX_MSG = "未知错误"; @ExceptionHandler(Exception.class) @ResponseBody public JsonData handle(Exception e){ JsonData result = new JsonData(); /*判断异常的类型*/ // 如果是自定义异常 if(e instanceof RbacException){ log.error("【自定义异常】:{}"+e.getMessage()); result = JsonData.fail(e.getMessage()); }else{ log.error("【系统异常】:{}"+e.getMessage()); result = JsonData.fail(UNKNOW_EX_MSG); } return result; } }
然后确保我们这个类所在的包被扫描到即可。
下面我们自定义一个类,并手动产生一个异常:
运行结果:
情况二、对全局异常进行捕获,返回modelandview类型
我们通过实现HandlerExceptionResolver 的方式来捕获全局异常
主要代码如下:
package com.me.common; import com.me.exception.RbacException; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ResponseBody; 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; /** * 全局异常处理 */ @Slf4j public class ExceptionHand implements HandlerExceptionResolver { private final String UNKNOW_EX_MSG = "未知错误"; /** * 通过实现HandlerExceptionResolver 接口,对捕获到的异常进行处理 * 当然,我们需要在spring容器中创建这个bean * @param request * @param response * @param o * @param e * @return */ @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) { // 请求地址 // String url = request.getRequestURL().toString(); ModelAndView mav = new ModelAndView(); // 如果是自定义异常 if(e instanceof RbacException){ log.error("【自定义异常】:{}"+e.getMessage()); JsonData result = JsonData.fail(e.getMessage()); mav.addObject("result",result); }else{ log.error("【系统异常】:{}"+e.getMessage()); JsonData result = JsonData.fail(UNKNOW_EX_MSG); mav.addObject("result",result); } // 设置异常处理返回的页面,在/views/exception.jsp mav.setViewName("exception"); return mav; } }
然后我们需要在spring容器中创建这个类的bean , 按照springmvc和springboot不同的做法都可以。
同样,我们还是用刚才的方法进行测试
因为返回的是modelAndView类型的对象,所以我们需要创建一个view
运行结果:
===========================================================================================
总结:
上面就是两种种捕获全局异常进行处理的不同方式,
1.实现HandlerExceptionResolver接口,返回modelAndView类型
2.通过@ControllerAdvice注解捕获,并通过@ResponseBody返回json类型
具体使用哪种看实际的项目,个人更喜欢第一种,统一返回json类型。
其他:
更规范的json返回对象是code码而不是boolean类型的,这里只为了做演示。那么在我们使用code码的时候,我们抛异常的时候可以自定义传入code以及msg ,这时建议用枚举来管理二者关系,抛异常的时候传入枚举类型,捕获的时候再从枚举中取值。
更详细的课程教学,请看廖师兄的课程 https://www.imooc.com/learn/810