异常处理
异常处理器
异常分类管理
代码:
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 ExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
System.out.println("my exception is running ...."+ex);
ModelAndView modelAndView = new ModelAndView();
if( ex instanceof NullPointerException){
modelAndView.addObject("msg","空指针异常");
}else if ( ex instanceof ArithmeticException){
modelAndView.addObject("msg","算数运算异常");
}else{
modelAndView.addObject("msg","未知的异常");
}
modelAndView.setViewName("error.jsp");
return modelAndView;
}
}
注解实现异常处理
-
代码:
import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @Component //使用注解开发异常处理器 //声明该类是一个Controller的通知类,声明后该类就会被加载成异常处理器 @ControllerAdvice//如果将这句话注释掉,这个异常处理器就不能使用了 public class ExceptionAdvice { //类中定义的方法携带@ExceptionHandler注解的会被作为异常处理器,后面添加实际处理的异常类型 @ExceptionHandler(NullPointerException.class)//处理空指针异常 @ResponseBody//如果不写ResponseBody,它就会去找return的页面,添加过后便不会解析成页面 public String doNullException(Exception ex){ return "空指针异常"; } @ExceptionHandler(ArithmeticException.class)//处理算术异常 @ResponseBody public String doArithmeticException(Exception ex){ return "ArithmeticException"; } @ExceptionHandler(Exception.class)//处理全部的异常 @ResponseBody public String doException(Exception ex){ return "all"; } }
两种异常处理方式对比
注解处理器可以拦截到入参类型转换异常
:简单来说就是处理的时间比较早,是在参数转换到controller里面之前加载
非注解处理器无法拦截到入参类型转换异常
:这个是在后面加载,二者工作时机不同,这个比较晚
项目异常处理方案(理解
)
异常分类
-
业务异常:用户这么做的
- 规范的用户行为产生的异常:比如输入年龄,用户输入-1
- 不规范的用户行为操作产生的异常:比如用户通过某种偶然的方式知道了公司里面财务审批的url地址,直接在地址栏输入敲回车过去了,然后把钱给批了钱领了
-
系统异常:
- 项目运行过程中可预计且无法避免的异常:比如连接超时,网络特别慢,特别卡
-
其他异常:
- 编程人员未预期到的异常:程序员写的代码有误,不可预料
异常处理方案
-
业务异常:
- 发送对应消息传递给用户,提醒规范操作
-
系统异常:
- 发送固定消息传递给用户,安抚用户
- 发送特定消息给运维人员,提醒维护
- 记录日志
-
其他异常:
- 发送固定消息传递给用户,安抚用户
- 发送特定消息给编程人员,提醒维护
- 纳入预期范围内
- 记录日志
自定义异常
-
测试代码
-
自定义异常类
-
BusinessException.java
//自定义异常继承RuntimeException,覆盖父类所有的构造方法 public class BusinessException extends RuntimeException { public BusinessException() { } public BusinessException(String message) { super(message); } public BusinessException(String message, Throwable cause) { super(message, cause); } public BusinessException(Throwable cause) { super(cause); } public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } }
-
SystemException.java系统异常
//自定义异常继承RuntimeException,覆盖父类所有的构造方法 public class SystemException extends RuntimeException { public SystemException() { } public SystemException(String message) { super(message); } public SystemException(String message, Throwable cause) { super(message, cause); } public SystemException(Throwable cause) { super(cause); } public SystemException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } }
-
-
ajax异步请求
<%@page pageEncoding="UTF-8" language="java" contentType="text/html;UTF-8" %> <a href="javascript:void(0);" id="testException">访问springmvc后台controller,传递Json格式POJO</a><br/> <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script> <script type="text/javascript"> $(function () { $("#testException").click(function(){ $.ajax({ contentType:"application/json", type:"POST", url:"save", /*通过修改参数,激活自定义异常的出现*/ // name长度低于8位出现业务异常 // age小于0出现业务异常 // age大于100出现系统异常 // age类型如果无法匹配将转入其他类别异常 data:'{"name":"Jock","age":"111"}', dataType:"text", //回调函数 success:function(data){ alert(data); } }); }); }); </script>
-
error.jsp出错跳转的页面
<%--异常消息展示页面--%> <%@page pageEncoding="UTF-8" language="java" contentType="text/html;UTF-8" %> ${msg}
-
UserController.java
import com.itheima.domain.User; import com.itheima.exception.BusinessException; import com.itheima.exception.SystemException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.ArrayList; import java.util.List; @Controller public class UserController { @RequestMapping("/save") @ResponseBody public List<User> save(@RequestBody User user) { System.out.println("user controller save is running ..."); //模拟业务层发起调用产生了异常 // int i = 1/0; // String str = null; // str.length(); //对用户的非法操作进行判定,并包装成异常对象进行处理,便于统一管理 if(user.getName().trim().length() < 8){ throw new BusinessException("对不起,用户名长度不满足要求,请重新输入!"); } if(user.getAge() < 0){ throw new BusinessException("对不起,年龄必须是0到100之间的数字!"); } if(user.getAge() > 100){ throw new SystemException("服务器连接失败,请尽快检查处理!"); } User u1 = new User(); u1.setName("Tom"); u1.setAge(3); User u2 = new User(); u2.setName("Jerry"); u2.setAge(5); ArrayList<User> al = new ArrayList<User>(); al.add(u1); al.add(u2); return al; } }
-
异常处理器ProjectExceptionAdvice.java
import org.springframework.stereotype.Component; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @Component @ControllerAdvice public class ProjectExceptionAdvice { @ExceptionHandler(BusinessException.class) public String doBusinessException(Exception ex, Model m){ //使用参数Model将要保存的数据传递到页面上,功能等同于ModelAndView //业务异常出现的消息要发送给用户查看 m.addAttribute("msg",ex.getMessage()); return "error.jsp"; } @ExceptionHandler(SystemException.class) public String doSystemException(Exception ex, Model m){ //系统异常出现的消息不要发送给用户查看,发送统一的信息给用户看 m.addAttribute("msg","服务器出现问题,请联系管理员!"); //实际的问题现象应该传递给redis服务器,运维人员通过后台系统查看 //实际的问题显现更应该传递给redis服务器,运维人员通过后台系统查看 return "error.jsp"; } @ExceptionHandler(Exception.class) public String doException(Exception ex, Model m){ m.addAttribute("msg",ex.getMessage()); //将ex对象保存起来 return "error.jsp"; } }
-