【Java从零到架构师第③季】【33】SpringMVC-异常处理


持续学习&持续更新中…

守破离


以前是如何处理异常的?

在这里插入图片描述

使用try-catch

弊端:每个Controller下的每个方法(@RequestMapping)都需要写try-catch语句。

	@RequestMapping("/demo1")
	@ResponseBody
	public String demo1(String birthday) {
	    try {
	        System.out.println("demo1");
	        Date birth = new SimpleDateFormat("yyyy年MM月dd日").parse(birthday);
	        System.out.println(birth);
	    } catch (Exception e) {
	        e.printStackTrace();
	        // 处理异常!
	    }
	    return "success!";
	}
使用throws+配置500页面

用途:这种方法,适合那些服务器内部出现严重的错误,用于警告用户他的行为不当。

handle_500.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<div>出异常啦!</div>
<div>
    <%
        StringBuilder sb = new StringBuilder();
        Throwable throwable = exception;
        do {
            sb.append(throwable.getClass())
                    .append("——")
                    .append(throwable.getMessage())
                    .append("<br>");
            throwable = throwable.getCause();
        } while (throwable != null);
    %>
    <text><%=sb.toString()%></text>
</div>
<div>
    <%--  根据异常做出相应的处理  --%>
    <p><%=exception%></p>
</div>
</body>
</html>

web.xml:

	<error-page>
	    <error-code>500</error-code>
	    <location>/WEB-INF/handle_500.jsp</location>
	</error-page>

编写代码时不用管异常:

	@RequestMapping("/demo2")
	@ResponseBody                            // 检查型异常
	    public String demo2(String birthday) throws Exception {
	    System.out.println("demo2");
	    Date birth = new SimpleDateFormat("yyyy/MM/dd").parse(birthday);
	    System.out.println(birth);
	    
	    // 运行时异常:
	    // System.out.println(1 / 0);
	    // throw new RuntimeException("demo1");
	    return "success!";
	}

异常处理

在这里插入图片描述

异常处理—SimpleMappingExceptionResolver

缺点:为异常处理页面能够传递的东西(信息)有限(<property name="exceptionAttribute" value="ex"/>

在这里插入图片描述

统一设置异常处理页面

applicationContext.xml:

    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionAttribute" value="ex"/>
        <property name="defaultErrorView" value="/WEB-INF/error/default.jsp"/>
    </bean>

ExceptionController1:

@Controller
@RequestMapping("/exception1")
public class ExceptionController1 {

    @RequestMapping("/demo1")
    @ResponseBody
    public String demo1() {
        throw new DateTimeException("demo1");
    }

    @RequestMapping("/demo2")
    @ResponseBody
    public String demo2() throws Exception {
        throw new IOException("demo2");
    }

	// ...

}

JSP页面使用异常:

<!-- 不用在page指令中加上 isErrorPage="true" -->
<body>
<p>异常:${ex}</p>
<p>异常信息:${ex.message}</p>
</body>

当想要特殊处理某个异常时

applicationContext.xml:

 <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
     <property name="exceptionMappings">
         <props>
             <prop key="java.lang.ArrayIndexOutOfBoundsException">/WEB-INF/error/runtime.jsp</prop>
             <prop key="java.io.IOException">/WEB-INF/error/io.jsp</prop>
         </props>
     </property>
     <property name="exceptionAttribute" value="ex"/>
     <property name="defaultErrorView" value="/WEB-INF/error/default.jsp"/>
 </bean>

异常处理—自定义异常解析器

在这里插入图片描述

@Component
public class MyExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
                                         HttpServletResponse response,
                                         Object handler,
                                         Exception ex) {
//      可以使用request、response对象

//      可以通过handler知道是哪个Controller的哪个方法出现了异常
//      拿到具体的Controller和具体的方法后,就可以做出相应的处理
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        System.out.println(handlerMethod.getBean());
        System.out.println(handlerMethod.getMethod());

        ModelAndView mv = new ModelAndView();
//      自己可以根据异常的类型决定去哪个异常处理页面
//      对某种类型的异常做特殊处理
//      if (ex instanceof ArrayIndexOutOfBoundsException) {
//          mv.setViewName("xxx");
//      } else if (ex instanceof IOException) {
//          mv.setViewName("xxx");
//      }else if(ex instanceof xxx) {
//          // ...
//      }else {
//          mv.setViewName("default.jsp");
//      }
        mv.setViewName("/WEB-INF/error/default.jsp");

//      可以给异常处理页面传递任何信息
//      mv.addObject(attributeName,attributeValue);
        mv.addObject("ex", ex);
        mv.addObject("userinfo", "name:lp, age:10,...");
        return mv;
    }
}

异常处理—@ExceptionHandler

缺点:需要为每一个Controller都写带有@ExceptionHandler的异常处理方法

在这里插入图片描述

@Controller
@RequestMapping("/ex2")
public class ExceptionController2 {

    @RequestMapping("/demo1")
    @ResponseBody
    public String demo1() {
        throw new DateTimeException("demo1");
    }

    @RequestMapping("/demo2")
    @ResponseBody
    public String demo2() throws Exception {
        throw new IOException("demo2");
    }

    @RequestMapping("/demo3")
    @ResponseBody
    public String demo3() {
        throw new ArithmeticException("demo3");
    }

    //    需要特殊处理的异常
//    @ExceptionHandler(DateTimeException.class)
//    public void exceptionHandlerSpecial1(Exception ex) {
//        System.out.println(ex);
//    }
//
//    @ExceptionHandler(ArithmeticException.class)
//    public ModelAndView exceptionHandlerSpecial2(Exception ex) {
//        ModelAndView mv = new ModelAndView();
//        mv.addObject("ex", ex);
//        mv.setViewName("/WEB-INF/error/runtime.jsp");
//        System.out.println(ex);
//        return mv;
//    }
    
    // 需要特殊处理的异常
    @ExceptionHandler({DateTimeException.class, ArithmeticException.class})
    public void exceptionHandlerSpecial(Exception ex) {
        System.out.println(ex);
    }

    // 其余所有的异常
    @ExceptionHandler
    public ModelAndView exceptionHandlerOther(Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("ex", ex);
        mv.setViewName("/WEB-INF/error/default.jsp");
        return mv;
    }

}

异常处理—@ExceptionHandler+@ControllerAdvice

在这里插入图片描述

@ControllerAdvice
public class MyExceptionHandler {

    // 默认处理所有的异常
    @ExceptionHandler
    public ModelAndView exceptionHandlerOther(Exception ex) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("ex", ex);
        mv.setViewName("/WEB-INF/error/default.jsp");
        return mv;
    }

    // 需要特殊处理的异常
    @ExceptionHandler({DateTimeException.class, ArithmeticException.class})
    @ResponseBody
    public String exceptionHandlerSpecial(Exception ex) {
        System.out.println(ex);
        return "出现了异常:" + ex;
    }

}

参考

小码哥-李明杰: Java从0到架构师③进阶互联网架构师.


本文完,感谢您的关注支持!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值