前言

在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{
//...
}

SpringMVC框架08——统一异常处理的更多相关文章

  1. 【SpringMVC学习07】SpringMVC中的统一异常处理

    我们知道,系统中异常包括:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发.测试通过手段减少运行时异常的发生.在开发中,不管是dao层 ...

  2. SpringMVC框架下的异常处理

    在eclipse的javaEE环境下:导包.... 1. 在 @ExceptionHandler 方法的入参中可以加入 Exception 类型的参数, 该参数即对应发生的异常对象 2. @Excep ...

  3. SpringMVC 控制器统一异常处理

    摘要介绍spring mvc控制器中统一处理异常的两种方式:HandlerExceptionResolver以及@ExceptionHandler:以及使用@ControllerAdvice将@Exc ...

  4. Java springmvc 统一异常处理的方案

    前言:为什么要统一异常处理?经常在项目中需要统一处理异常,将异常封装转给前端.也有时需要在项目中统一处理异常后,记录异常日志,做一下统一处理. Springmvc 异常统一处理的方式有三种. 一.使用 ...

  5. SSM框架之SpringMVC(6)异常处理及拦截器

    SpringMVC(6)异常处理及拦截器 1.异常处理 1.1.异常处理的思路 ​ 系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主 ...

  6. springMVC统一异常处理

    Spring MVC处理异常有3种方式: 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver: 实现Spring的异常处理接口HandlerExc ...

  7. 【SpringMVC】统一异常处理

    一.需求 二.统一异常处理解决方案 2.1 定义异常 2.2 异常处理 2.3 配置统一异常处理器 2.4 异常处理逻辑 一.需求 一般项目中都需要作异常处理,基于系统架构的设计考虑,使用统一的异常处 ...

  8. 在依赖的框架中已经有统一异常处理的情况下,如何定制自己的统一异常处理spring boot版本

    spring boot 环境下的统一异常处理大家已经非常熟悉了,不熟悉的化可以参考 <<Spring Boot中Web应用的统一异常处理>>.公司内部的统一异常处理如下: @E ...

  9. SpringBoot 统一异常处理

    统一异常处理: @ControllerAdvice public class GlobalExceptionHandler { private Logger logger = LoggerFactor ...

随机推荐

  1. Linux上java程序的jar包启动通用脚本(稳定用过)

    Linux上java程序的jar包启动通用脚本如下: #! /bin/sh export LANG="zh_CN.GBK" SERVICE_NAME=` .sh` SCRIPT_N ...

  2. indeed招聘

    https://cn.indeed.com/%E5%B7%A5%E4%BD%9C-%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E5%85%AC%E5%8F%B8-%E5% ...

  3. AngularJs -- ngMessages(1.3+)

    ngMessages(1.3+) 表单和验证是AngularJS中复杂的组件之一.用AngularJS默认的方式来写,不是特别好,不简洁. 在AngualrJS1.3发布前,表单验证必须以这种方式编写 ...

  4. 20155202 2016-2017-2 《Java程序设计》第5周学习总结

    20155202 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 第八章:异常处理 java中所有错误会包装成对象,可以尝试(try)执行程序并捕捉(catc ...

  5. python中的__getattr__、__getattribute__、__setattr__、__delattr__、__dir__

    __getattr__:     属性查找失败后,解释器会调用 __getattr__ 方法. class TmpTest: def __init__(self): self.tmp = 'tmp12 ...

  6. Jquery常用方法合集,超实用

    转自:十分钟玩转 jQuery.实例大全 一.简介 定义 jQuery创始人是美国John Resig,是优秀的Javascript框架: jQuery是一个轻量级.快速简洁的javaScript库. ...

  7. SQL Server 索引(一)数据结构和存储结构

    本文关注以下方面(本文所有的讨论基于SQL Server数据库): 索引的分类: 索引的结构: 索引的存储 一.索引定义分类 让我们先来回答几个问题: 什么是索引? 索引是对数据库表中一列或多列的值进 ...

  8. 用python socket模块实现简单的文件下载

    server端: # ftp server端 import socket, os, time server = socket.socket() server.bind(("localhost ...

  9. 谁在call我-backtrace的实现原理【转】

    转自:http://www.xuebuyuan.com/1504689.html 显示函数调用关系(backtrace/callstack)是调试器必备的功能之一,比如在gdb里,用bt命令就可以查看 ...

  10. 利用backtrace和ucontex定位segment错误【转】

    转自:https://blog.csdn.net/gqtcgq/article/details/53883546 C程序运行时,经常会碰到”segmentfault”错误.这是由于程序中非法访问内存导 ...