• SpringMVC 学习笔记(7)异常操作


    如何使用HandleException

    在程序中,异常是最常见的,我们需要捕捉异常并处理它,才能保证程序不被终止。

    最常见的异常处理方法就是用try catch来捕捉异常。这次我们使用springmvc给我们提供的方法来处理异常

    先模拟一个异常出现的场景。以下是一个简单的数学异常

    package com.ibigsea.springmvc.handler;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    @Controller
    public class Exception2Handler {
        
        //注意,该注解不是加在产生异常的方法上,而是另外写一个方法
        @ExceptionHandler({ArithmeticException.class})
        public ModelAndView testArithmeticException(Exception e){
            System.out.println("ArithmeticException:"+e);
            //我们要将异常在error页面中进行显示,并且将异常信息带到页面上显示出来
             //这里不能采用map的方式,@ExceptionHandler和map不能配合使用
            ModelAndView modelAndView = new ModelAndView("error");
            modelAndView.addObject("exception", e);
            return modelAndView;
        }
        
        @RequestMapping("/testException")
        public String testException(){
            int i = 10 /0;
            return "sucess";
        }
    
    }

    当i的值为0的时候,就会抛出数学异常。该如何捕捉呢,我们使用ExceptionHandler注解

    • ExceptionHandler 的value属性是一个Class 数组,因此我们可以在该注解的属性中加入多个异常类
    • 当目标方法产生异常时,将被这个方法捕捉,我们可以得到异常的实例
    • 注意,捕捉异常的方法要和目标方法在同一个controller中

    error.jsp

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
     <%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
     <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 
    <%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
      </head>
      
      <body>
       错误信息:${exception }
      
       
      </body>
    </html>

    HandleException的优先级

    当一个controller中有多个HandleException注解出现时,那么异常被哪个方法捕捉呢?这就存在一个优先级的问题

    package com.ibigsea.springmvc.handler;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    @Controller
    public class Exception2Handler {
        
        //注意,该注解不是加在产生异常的方法上,而是另外写一个方法
        @ExceptionHandler({ArithmeticException.class})
        public ModelAndView testArithmeticException(Exception e){
            System.out.println("ArithmeticException:"+e);
            //我们要将异常在error页面中进行显示,并且将异常信息带到页面上显示出来
             //这里不能采用map的方式,@ExceptionHandler和map不能配合使用
            ModelAndView modelAndView = new ModelAndView("error");
            modelAndView.addObject("exception", e);
            return modelAndView;
        }
        
        @ExceptionHandler({RuntimeException.class})
        public String testRuntimeException(Exception e){
            System.out.println("RuntimeException"+e);
            return "error";
        }
        @RequestMapping("/testException")
        public String testException(){
            int i = 10 /0;
            return "sucess";
        }
    
    }

    访问目标方法,让它抛异常,看控制台打印结果,发现它抛了ArithmeticException:java.lang.ArithmeticException: / by zero这个异常

    因此我们可以确定,ExceptionHandler的优先级是:在异常的体系结构中,哪个异常与目标方法抛出的异常血缘关系越紧密,就会被哪个捕捉到。

    捕捉全局的异常

    ExceptionHandler只能捕捉同一个controller中的异常,其实我们也有办法捕捉整个程序中所有的异常

    新建一个类,加上@ControllerAdvice注解

    package com.ibigsea.springmvc.handler;
    
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    
    //处理异常
    @ControllerAdvice
    public class HandleForException {
    
        @ExceptionHandler({ArithmeticException.class})
        public String testArithmeticException(Exception e){
            System.out.println("ArithmeticException:"+e);
            return "error";
        }
    }

    在这个类中使用ExceptionHandler,就能捕捉所有的controller中发生的异常

    结论

     52. 尚硅谷_佟刚_SpringMVC_异常处理_ResponseStatusExceptionResolver.avi

    带有@ResponseStatus注解的异常类会被ResponseStatusExceptionResolver 解析。可以实现自定义的一些异常,同时在页面上进行显示。具体的使用方法如下:

    1.首先定义一个异常类:

    @ResponseStatus(value = HttpStatus.FORBIDDEN,reason = "用户名和密码不匹配!")
    public class UserNameNotMatchPasswordException extends RuntimeException{
            
    }
    • ResponseStatus注解是修饰类的
    • 它有两个属性,value属性是http状态码,比如404,500等。reason是错误信息

    2.人为抛出一个异常:

      @RequestMapping("/testResponseStatusExceptionResolver")
        public String testResponseStatusExceptionResolver(@RequestParam("i") int i){
            if (i==13){
                throw new UserNameNotMatchPasswordException();
            }
            System.out.println("testResponseStatusExceptionResolver....");
            return "success";
        }

    3.输入如下额路径:

    http://localhost:8090/testResponseStatusExceptionResolver?i=13

    当然,也可以在方法上进行修饰:

    @ResponseStatus(reason = "测试",value = HttpStatus.NOT_FOUND)
        @RequestMapping("/testResponseStatusExceptionResolver")
        public String testResponseStatusExceptionResolver(@RequestParam("i") int i){
            if (i==13){
                throw new UserNameNotMatchPasswordException();
            }
            System.out.println("testResponseStatusExceptionResolver....");
            return "success";
        }
    这时所有的请求都会报错。

     
    • 仔细看这张结果图中的访问路径,我传入的参数是i=1,正常来说是不应该抛异常的,可是它抛了。。它真的抛了。。
    • 结论:ResponseStatus修饰目标方法,因为你修改了响应状态码为403,并加上了错误提示(reason),所有页面回显的数据按照403错误显示页面,无论它执行方法过程中有没有异常产生,用户都会得到异常的界面。而目标方法正常执行

    54. 尚硅谷_佟刚_SpringMVC_异常处理_SimpleMappingExceptionResolver.avi

    SimpleMappingException异常映射

    当异常发生时,我们可以将它映射到我们指定的界面

    如果希望对所有异常进行统一处理,可以使用SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常:

    在springmvc中配置

    <!-- 配置使用 SimpleMappingExceptionResolver 来映射异常 -->
        <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
            <!-- 
            配置异常的属性值为ex,那么在错误页面中可以通过 ${ex} 来获取异常的信息
            如果不配置这个属性,它的默认值为exception
             -->
            <property name="exceptionAttribute" value="ex"></property>
            <property name="exceptionMappings">
                <props>
                    <!-- 映射ArrayIndexOutOfBoundsException异常对应error.jsp这个页面 -->
                    <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>
                </props>
            </property>
        </bean> 

    写个目标方法测试一下

    @RequestMapping("/testExceptionMapping")
        public String testExceptionMapping(){
            int arrays[] = new int[10];
            System.out.println(arrays[11]);
            return "hello";
        }

    这里将发生数组下标越界的异常,访问目标方法,得到如下结果 
    这里写图片描述

    error.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    ${ex }
    </body>
    </html>

    这里这里的属性

    ${ex }必须和 <property name="exceptionAttribute" value="ex"></property>一一对应
  • 相关阅读:
    邮件的DNS设置
    使用GIT SUBTREE集成项目到子目录(转)
    PostGIS 快速入门(转)
    PostgreSQL数据库的安装与PostGIS的安装(转)
    python sort、sorted高级排序技巧(转)
    jQuery选择器--简洁又全面(转)
    jQuery选择器(转)
    手机/电脑的定位方式
    iOS定位原理和使用建议(转)
    【震惊】一个白帽子居然在网咖做出这种事
  • 原文地址:https://www.cnblogs.com/kebibuluan/p/8870860.html
Copyright © 2020-2023  润新知