zoukankan      html  css  js  c++  java
  • SpringMVC框架08——统一异常处理

    前言

    在Spring MVC 应用的开发中,不管是对底层数据库操作,还是业务层或控制层操作,都会不可避免地遇到各种可预知的、不可预知的异常需要处理。如果每个过程都单独处理异常,那么系统的代码耦合度高,工作量大且不好统一,以后维护的工作量也很大。
    在Spring MVC中提供了三种统一异常处理的方式,能够将所有类型的异常处理从各层中解耦出来,这样既保证了相关处理过程的功能单一,又实现了异常信息的统一处理和维护。

    1、演示案例准备

    为了验证Spring MVC 框架的3中异常处理方式,需要编写一个测试的应用,从Dao层、Service层、Controller层分别抛出不同的异常。本教程指定了3个异常,分别是:SQLException、自定义异常和未知异常,然后分别集成3种方式进行异常处理。
    分别创建相应的包和类,如下图所示:

    (1)创建自定义异常类MyException

    代码示例:

    package com.demo.exception;
    
    public class MyException extends Exception {
        public MyException() {
        }
    
        public MyException(String message) {
            super(message);
        }
    }

    (2)创建Dao层异常类

    代码示例:

    package com.demo.dao;
    
    import com.demo.exception.MyException;
    import org.springframework.stereotype.Repository;
    import java.sql.SQLException;
    
    @Repository("testExceptionDao")
    public class TestExceptionDao {
    
        public void daodb() throws SQLException {
            throw new SQLException("Dao中数据库异常");
        }
    
        public void daomy() throws MyException {
            throw new MyException("Dao中自定义异常");
        }
    
        public void daono() throws Exception {
            throw new Exception("Dao中的未知异常");
        }
    
    }

    (3)创建Service层异常类

    在service包下创建TestExceptionService接口和TestExceptionServiceImpl实现类,在该接口中定义6个方法,其中有3个是调用Dao层,有3个是Service层的方法。
    TestExceptionService接口代码示例:

    package com.demo.service;
    
    public interface TestExceptionService {
        public void servicedb() throws Exception;
        public void servicemy() throws Exception;
        public void serviceno() throws Exception;
        public void daodb() throws Exception;
        public void daomy() throws Exception;
        public void daono() throws Exception;
    }

    TestExceptionServiceImpl实现类代码示例:

    package com.demo.service;
    
    import com.demo.dao.TestExceptionDao;
    import com.demo.exception.MyException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.sql.SQLException;
    
    @Service("testExceptionService")
    public class TestExceptionServiceImpl implements TestExceptionService {
    
        @Autowired
        private TestExceptionDao testExceptionDao;
    
        @Override
        public void servicedb() throws Exception {
            throw new SQLException("Service中数据库异常");
        }
    
        @Override
        public void servicemy() throws Exception {
            throw new MyException("Service中自定义异常");
        }
    
        @Override
        public void serviceno() throws Exception {
            throw new Exception("Service中未知异常");
        }
    
        @Override
        public void daodb() throws Exception {
            testExceptionDao.daodb();
        }
    
        @Override
        public void daomy() throws Exception {
            testExceptionDao.daomy();
        }
    
        @Override
        public void daono() throws Exception {
            testExceptionDao.daono();
        }
    
    }

    (4)创建控制器层异常类

    代码示例:

    package com.demo.controller;
    
    import com.demo.exception.MyException;
    import com.demo.service.TestExceptionService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import java.sql.SQLException;
    
    @Controller
    public class TestExceptionController {
        @Autowired
        private TestExceptionService testExceptionService;
    
        @RequestMapping("/db")
        public void db() throws SQLException {
            throw new SQLException("控制器中数据库异常");
        }
    
        @RequestMapping("/my")
        public void my() throws MyException {
            throw new MyException("控制器中自定义异常");
        }
    
        @RequestMapping("no")
        public void no() throws Exception {
            throw new Exception("控制器中未知异常");
        }
    
        @RequestMapping("/servicedb")
        public void servicedb() throws Exception {
            testExceptionService.servicedb();
        }
    
        @RequestMapping("/servicemy")
        public void servicemy() throws Exception {
            testExceptionService.servicemy();
        }
    
        @RequestMapping("/serviceno")
        public void serviceno() throws Exception {
            testExceptionService.serviceno();
        }
    
        @RequestMapping("/daodb")
        public void daodb() throws Exception {
            testExceptionService.daodb();
        }
    
        @RequestMapping("/daomy")
        public void daomy() throws Exception {
            testExceptionService.daomy();
        }
    
        @RequestMapping("/daono")
        public void daono() throws Exception {
            testExceptionService.daono();
        }
    
    }

    (5)创建View视图层

    View层共有5个JSP页面,分别是:
    测试应用首页index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <html>
    <body>
    <h1>演示案例</h1>
    <p>
        <a href="${pageContext.request.contextPath}/daodb">处理dao中数据库异常</a>
    </p>
    <p>
        <a href="${pageContext.request.contextPath}/daomy">处理dao中自定义异常</a>
    </p>
    <p>
        <a href="${pageContext.request.contextPath}/daono">处理dao中未知异常</a>
    </p>
    <p>
        <a href="${pageContext.request.contextPath}/servicedb">处理service中数据库异常</a>
    </p>
    <p>
        <a href="${pageContext.request.contextPath}/servicemy">处理service中自定义异常</a>
    </p>
    <p>
        <a href="${pageContext.request.contextPath}/serviceno">处理service中未知异常</a>
    </p>
    <p>
        <a href="${pageContext.request.contextPath}/db">处理controller中数据库异常</a>
    </p>
    <p>
        <a href="${pageContext.request.contextPath}/my">处理controller中自定义异常</a>
    </p>
    <p>
        <a href="${pageContext.request.contextPath}/no">处理controller中未知异常</a>
    </p>
    </body>
    </html>

    404错误对应页面404.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>404</title>
    </head>
    <body>
        <h2>资源不存在</h2>
    </body>
    </html>

    未知异常对应页面error.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
    <html>
    <head>
        <title>未知异常</title>
    </head>
    <body>
        <h1>未知错误:</h1>
        <%=exception%>
        <h2>错误内容:</h2>
        <%
            exception.printStackTrace(response.getWriter());
        %>
    </body>
    </html>

    自定义异常对应页面my-error.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
    <html>
    <head>
        <title>自定义异常</title>
    </head>
    <body>
        <h1>自定义异常错误:</h1>
        <%=exception%>
        <h2>错误内容:</h2>
        <%
            exception.printStackTrace(response.getWriter());
        %>
    </body>
    </html>

    SQL异常对应页面sql-error.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
    <html>
    <head>
        <title>数据库异常</title>
    </head>
    <body>
        <h1>数据库异常错误:</h1>
        <%=exception%>
        <h2>错误内容:</h2>
        <%
            exception.printStackTrace(response.getWriter());
        %>
    </body>
    </html>

    (6)配置全局异常处理

    在web.xml中配置全局异常404处理

    <!--配置全局异常-->
    <error-page>
      <error-code>404</error-code>
      <location>/404.jsp</location>
    </error-page>

    2、使用配置统一处理异常

    在springmvc.xml中配置org.springframework.web.servlet.handler.SimpleMappingExceptionResolver类,并且要提前配置异常类和View的对应关系。
    springmvc.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:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
    
        <!--将AnnotationHandler自动扫描到IOC容器中-->
        <context:component-scan base-package="com"></context:component-scan>
    
        <!--配置视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--配置前缀-->
            <property name="prefix" value="/"></property>
            <!--配置后缀-->
            <property name="suffix" value=".jsp"></property>
        </bean>
    
        <!--配置异常相关-->
        <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
            <!--定义默认的异常处理页面,当该异常类型注册时使用-->
            <property name="defaultErrorView" value="error"></property>
            <!--定义异常处理页面用来获取异常信息的变量名,默认名为exception-->
            <property name="exceptionAttribute" value="ex"></property>
            <!--定义需要特殊处理的异常,用类名或完全路径名作为key,异常页名作为值-->
            <property name="exceptionMappings">
                <props>
                    <prop key="com.demo.exception.MyException">my-error</prop>
                    <prop key="java.sql.SQLException">sql-error</prop>
                    <!--在这里还可以继续扩展对不同异常类型的处理-->
                </props>
            </property>
        </bean>
    
    </beans>

    演示效果:

    404演示效果:

    3、使用接口统一处理异常

    org.springframework.web.servlet.HandlerExceptionResolver 接口用于解析请求处理过程中所产生的异常。在exception包中创建一个HandlerExceptionResolver接口的实现类MyExceptionHandler,代码如下:

    package com.demo.exception;
    
    import org.springframework.web.servlet.HandlerExceptionResolver;
    import org.springframework.web.servlet.ModelAndView;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.sql.SQLException;
    import java.util.HashMap;
    import java.util.Map;
    
    public class MyExceptionHandler implements HandlerExceptionResolver {
        @Override
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object obj, Exception e) {
            Map<String,Object> model = new HashMap<String,Object>();
            model.put("ex",e);
            //根据不同错误转向不同页面(统一处理),即异常与View的对应关系
            if (e instanceof MyException) {
                return new ModelAndView("my-error",model);
            }else if (e instanceof SQLException) {
                return new ModelAndView("sql-error",model);
            }else {
                return new ModelAndView("error",model);
            }
        }
    }

    在springmvc.xml文件中配置实现类MyExceptionHandler的托管

    <?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:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
    
        <!--将AnnotationHandler自动扫描到IOC容器中-->
        <context:component-scan base-package="com"></context:component-scan>
    
        <!--配置视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--配置前缀-->
            <property name="prefix" value="/"></property>
            <!--配置后缀-->
            <property name="suffix" value=".jsp"></property>
        </bean>
    
        <!--托管MyExceptionHandler-->
        <bean class="com.demo.exception.MyExceptionHandler"></bean>
    
    </beans>

    4、使用注解统一处理异常

    在controller包下创建BaseController类,并在该类的方法中使用@ExceptionHandler注解声明异常处理方法,代码如下:

    package com.demo.controller;
    
    import com.demo.exception.MyException;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.sql.SQLException;
    
    public abstract class BaseController {
    
        @ExceptionHandler
        public String exception(HttpServletRequest request, HttpServletResponse response,Exception e){
            request.setAttribute("ex",e);
            if (e instanceof MyException) {
                return "my-error";
            } else if (e instanceof SQLException) {
                return "sql-error";
            } else {
                return "error";
            }
        }
    }

    将所有需要异常处理的Controller都继承BaseController类,示例代码如下:

    @Controller
    public class TestExceptionController extends BaseController{
        //...
    }
  • 相关阅读:
    选择时区的命令tzselect
    Linux就这个范儿 第16章 谁都可以从头再来--从头开始编译一套Linux系统 nsswitch.conf配置文件
    centos mysql 实战 第一节课 安全加固 mysql安装
    linux mknod命令解析
    keepalived对nginx高可用演练脚本
    install 命令用法详解
    基于 HTML5 的 WebGL 自定义 3D 摄像头监控模型
    基于 HTML5 结合工业互联网的智能飞机控制
    基于HTML5 的互联网+地铁行业
    基于 HTML5 结合互联网+ 的 3D 隧道
  • 原文地址:https://www.cnblogs.com/jpwz/p/10548349.html
Copyright © 2011-2022 走看看