zoukankan      html  css  js  c++  java
  • 【Spring】SpringMVC之异常处理

    java中的异常分为两类,一种是运行时异常,一种是非运行时异常。在JavaSE中,运行时异常都是通过try{}catch{}捕获的,这种只能捕获显示的异常,通常项目上抛出的异常都是不可预见。那么我们能够有什么方法能够解决这种问题吗?当然有,SpringMVC中的异常处理机制就很好的做到了这一点。

    SpringMVC中的异常处理一共有3种方式

    • (1)使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver; 
    • (2)实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器;
    • (3)使用@ExceptionHandler注解实现异常处理。

    (1)使用Spring MVC提供的SimpleMappingExceptionResolver

    直接将SimpleMappingExceptionResolver类配置到SpringMVC配置文件中

            <!-- 
                只是对全局的Controller有效果
                    所有的被RequestMapping注解所添加的方法中的异常才有效果
             -->
            <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
                <property name="exceptionMappings">
                    <props>
                <!--    
                        key: 异常的类全称
                        value: ModelAndView中的viewName
                        表示当key指定的异常产生时 , 则请求转发至 value指向的视图    -->
                        <prop key="java.lang.Exception">errorPage</prop>
                    </props>
                </property>
            </bean>

    从配置文件上可以看出,如果发生了异常就跳转到名为errorPage的视图上。

    完整的applicationContext.xml文件如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context" 
        xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
        xmlns:jee="http://www.springframework.org/schema/jee" 
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:aop="http://www.springframework.org/schema/aop" 
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:util="http://www.springframework.org/schema/util"
        xmlns:jpa="http://www.springframework.org/schema/data/jpa"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
            <!-- 
                开启注解扫描
             -->
             <context:component-scan base-package="cn"></context:component-scan>
             <!-- 
                 开启mvc注解扫描
              -->
            <mvc:annotation-driven/>
            
            <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/"></property>
                <property name="suffix" value=".jsp"></property>
            </bean>
            <!-- 
                只是对全局的Controller有效果
                    所有的被RequestMapping注解所添加的方法中的异常才有效果
             -->
            <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
                <property name="exceptionMappings">
                    <props>
                <!--    
                        key: 异常的类全称
                        value: ModelAndView中的viewName
                        表示当key指定的异常产生时 , 则请求转发至 value指向的视图    -->
                        <prop key="java.lang.Exception">errorPage</prop>
                    </props>
                </property>
            </bean>
        
            
    </beans>
    applicationContext.xml

    使用这种方式的异常处理就是简单,但是问题显而易见,就是发生了异常自动就跳转到错误页面,那么这不利于后台对错误日志的收集。

    (2)实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器

    使用方式如下:

    @Component
    public class MyException implements HandlerExceptionResolver {
        @Override
        public ModelAndView resolveException(参数...) {
                     //操作...
        }
    }

    在自定义异常处理器中,我们就可以很方便对异常信息进行各种操作操作,下面是一个能收集错误信息的自定义异常处理器:

    SpringMVC的配置文件中需要负责打开扫描:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context" 
        xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
        xmlns:jee="http://www.springframework.org/schema/jee" 
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:aop="http://www.springframework.org/schema/aop" 
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:util="http://www.springframework.org/schema/util"
        xmlns:jpa="http://www.springframework.org/schema/data/jpa"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
            <!-- 
                开启注解扫描
             -->
             <context:component-scan base-package="cn"></context:component-scan>
             <!-- 
                 开启mvc注解扫描
              -->
            <mvc:annotation-driven/>
            
            <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/"></property>
                <property name="suffix" value=".jsp"></property>
            </bean>
            
    </beans>
    applicationContext.xml

    自定义的异常类:

    package cn.shop.exception;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerExceptionResolver;
    import org.springframework.web.servlet.ModelAndView;
    
    import cn.shop.util.ExceptionUtil;
    
    /**
     * 用来在全局 处理Controller异常
     */
    @Component
    public class SpringMVCException implements HandlerExceptionResolver {
        /**
         * 如果这个类的对象, 存在于容器中, 则当前的项目中, 所有的Controller 出现的异常, 都会到这个方法中
         * 
         * 参数1.      请求对象
         * 参数2. 响应对象
         * 参数3. 出现异常时的 Method对象
         * 参数4. 出现异常时的异常信息
         * 
         * 返回值, 会被ViewResolver解析
         */
        @Override
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object method,Exception e) {
            System.out.println("出现异常的方法:"+method.toString());
            //request.getQueryString():  获取get请求时的参数列表
            String paras = request.getQueryString();
            System.out.println("出现了异常, 出现异常时的请求参数:"+paras);
            System.out.println("--------------------------------------");
            System.out.println("----------      异常信息如下            ---------");
            System.out.println("--------------------------------------");
            e.printStackTrace();
            
            //存储到异常日志
            ExceptionUtil.toException(e);
            //跳转
            return new ModelAndView( "error");
        }
    
    }
    SpringMVCException.java

    存储异常的工具类:

    package cn.shop.util;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.PrintWriter;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * 用来收集异常日志
     *
     *    JavaEE  web阶段
     *
     *    当产生异常时, 应把异常收集起来 ,
     *
     *        存储到
     *            本地文件
     *            网络存储
     *            短信发送
     *            邮件
     */
    public class ExceptionUtil {
    
        /**
         * 
         * 存储: 
         *     在存储的目录下 ,按照每天的日期创建单独文件夹
         * 
         *                 每天的文件夹中, 异常日志存储的文件, 一个异常一个文件, 文件名称按照时-分-秒-毫秒的格式存储
         *         
         * 
         * @param e 要存储的异常信息
         * @param exceptionPath 要存储的位置: 是一个文件夹, 文件夹可以不存在
         * @throws Exception 
         */
        public static void toException(Exception e,File exceptionPath) throws Exception{
            if(!exceptionPath.exists()){
                //创建文件夹
                exceptionPath.mkdirs();
            }
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String day = sdf.format(date);
            //创建每天的异常文件夹
            File dayDir = new File(exceptionPath, day);
            if(!dayDir.exists())
                dayDir.mkdirs();
            //创建本次异常存储的文件
            SimpleDateFormat sdf2 = new SimpleDateFormat("HH-mm-ss-sss");
            
            String fileName = sdf2.format(date);
            File file = new File(dayDir, fileName+".txt");
            //创建一个字符打印流 , 指向创建的这个文件
            PrintWriter pw = new PrintWriter(new FileOutputStream(file));
            //将异常信息输出至这个文件
            e.printStackTrace(pw);
            pw.close();
        }
        /**
         * 
         * @param e 要存储的异常信息 , 存储的位置 ,在F://log文件夹中
         */
        public static void toException(Exception e){
            try {
                toException(e,new File("F://log"));
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }   
    }
    ExceptionUtil.java

    (3)@ExceptionHandler注解实现异常处理

    package cn.xdl.controller;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class UserController {
    
        @RequestMapping("/login.do")
        public String UserrLogin(String name,String password){
            
            //从数据库进行数据对比...
            
            //将结果值返回
            return "loginResult";
        }
        /**
         * 当前这个Controller类 ,被RequestMapping所注解的方法 如果出现了异常 ,则自动寻找当前类中是否存在被@ExceptionHandler注解的方法 , 如果存在, 则执行
         * 
         * 这个方法的写法, 与使用直接方式的Controller基本一致
         *     它的参数列表中, 可以根据需求选择如下参数: 
         *     HttpSession / HttpServletRequest /HttpServletResponse / Exception
         */
        @ExceptionHandler
        public String hahaha(Exception e,HttpServletRequest request){
            System.out.println("请求时的参数:"+request.getQueryString());
            System.out.println("---------------------------------");
            System.out.println("-----------  请看异常信息   -----------");
            System.out.println("---------------------------------");
            e.printStackTrace();
            
            return "error";
            
            
        }
    }

    上面这三种方式,各不影响,如果使用了多种方式的话,那么以离异常近的处理机制为准(就近原则)。

    参考文章:

    Java中自定义异常

  • 相关阅读:
    VS2010 自动跳过代码现象
    Reverse Linked List II 【纠结逆序!!!】
    Intersection of Two Linked Lists
    Linked List Cycle II
    Remove Nth Node From End of List 【另一个技巧,指针的指针】
    Swap Nodes in Pairs
    Merge Two Sorted Lists
    Remove Duplicates from Sorted List
    Linked List Cycle
    Dungeon Game
  • 原文地址:https://www.cnblogs.com/HDK2016/p/7172338.html
Copyright © 2011-2022 走看看