• 【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中自定义异常

  • 相关阅读:
    WebSocket
    Jedis工具类
    电脑突然没有声音了 右下角红叉叉,由于其配置信息(注册表中的)不完整或已损坏,Windows 无法启动这个硬件设备。 (代码19)
    java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.
    WCF中的数据契约(Continued)
    WCF中的服务契约
    搭建基于MOSS的团队解决方案01——Microsoft Office SharePoint 2007 Server快速入门(Continued)
    Silverlight 的发展之路
    Windows Workflow Foundation实验01——Windows Workflow Foundation快速入门(练习四)
    使用.NET平台工具操作Live Framework
  • 原文地址:https://www.cnblogs.com/HDK2016/p/7172338.html
Copyright © 2020-2023  润新知