SpringMVC统一异常处理
Posted nuist__NJUPT
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringMVC统一异常处理相关的知识,希望对你有一定的参考价值。
SpringMVC统一异常处理
在SpringMVC应用开发中,不管是对底层数据库的操作,还是对业务层或者控制层的操作,都不可避免的会遇到各种可预知的和不可预知的异常需要处理。如果每个过程都要单独处理异常,那么系统的代码耦合度高,工作量大且不好统一,以后维护的工作量也很大,如果能将所有类型的异常从各层中解耦出来,这样既能保证相关处理过程的功能单一,又实现了异常信息的统一处理和维护。
SpringMVC框架提供了3种异常处理方式:
1-简单异常处理SimpleMappingExceptionResolver;
2-实现HandlerExceptionResolver接口的自定义异常;
3-实现@ExceptionHandler注解实现异常处理
为了验证SpringMVC框架的3种异常处理的效果,需要开发一个测试应用,从Dao层,Service层,Controller层分别抛出不同的异常,然后分别集成3种方式进行异常处理,进而比较优缺点。
3种异常处理方式的相似部分有dao层,Service层,View层,MyException,TestExceptionControler以及web.xml
1-在IDEA中创建web应用ch16-1,并在WEB-INF目录下创建lib目录,在lib目录下导入SpringMVC相关jar包。
2-创建自定义异常类,在src目录下创建exception包,并在该包中创建自定义异常类MyException,具体代码如下:
public class MyException extends Exception {
private static final long serialVersionID = 1L;
public MyException(){
super() ;
}
public MyException(String message){
super(message) ;
}
}
3-创建Dao层,在src目录下创建dao包,并在该包中创建TestExceptionDao类,在该类中分别定义三个方法,分别抛出“数据库异常”,“自定义异常”,“未知异常”。
import java.sql.SQLException;
/**
* dao层中类中定义三个方法,分别抛出数据库异常,自定义异常,未知异常
*/
@Repository
public class TestExceptionDao {
public void daodb() throws Exception{
throw new SQLException("Dao中数据库异常") ;
}
public void daomy() throws Exception{
throw new MyException("Dao中自定义异常") ;
}
public void daono() throws Exception{
throw new MyException("Dao中未知的异常") ;
}
}
4-创建Service层,在src目录下创建TestExceptionService接口和TestExceptionServiceImpl实现类,该接口中定义了6个方法,其中,3个方法是Service层的方法,3个方法是调用Dao层的方法,Service层的方法是为了演示Service层的“数据库异常”,“自定义异常”,“未知异常”而定义的。
TestExceptionService接口:
/**
* 该接口中定义了6个接口方法,其中,3个方法定义了Dao层的方法,有3个方法是Service层的方法
* Service层方法是为了演示Service层的数据库异常,自定义异常和未知异常
*/
public interface TestExceptionService {
public void servicemy() throws Exception ;
public void servicedb() throws Exception ;
public void serviceno() throws Exception ;
public void daomy() throws Exception ;
public void daodb() throws Exception ;
public void daono() throws Exception ;
}
TestExceptionServiceImpl实现类:
import exception.MyException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.SQLException;
@Service
public class TestExceptionServiceImpl implements TestExceptionService {
@Autowired
private TestExceptionService testExceptionService ;
@Override
public void servicemy() throws Exception {
throw new MyException("Service中自定义的异常") ;
}
@Override
public void servicedb() throws Exception {
throw new SQLException("Service中的数据库异常") ;
}
@Override
public void serviceno() throws Exception {
throw new Exception("Service中的未知异常") ;
}
@Override
public void daomy() throws Exception {
testExceptionService.daomy();
}
@Override
public void daodb() throws Exception {
testExceptionService.daodb();
}
@Override
public void daono() throws Exception {
testExceptionService.daono();
}
}
5-创建控制器类,在src目录下创建controller包,在controller包中创建控制器类TestExceptionController,代码如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import service.TestExceptionService;
import java.sql.SQLException;
@Controller
public class TestExceptionController {
@Autowired
private TestExceptionService testExceptionService ;
@RequestMapping("/db")
public void db() throws Exception{
throw new SQLException("控制器中的数据库异常") ;
}
@RequestMapping("/my")
public void my() throws Exception{
throw new Exception("控制器中的自定义异常") ;
}
@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();
}
}
6-创建View层,View层共5个JSP页面。
分别为测试应用首页面index.jsp,还有在WEB-INF目录下创建jsp目录,并在该目录中创建404.jsp,error.jsp,my-error.jsp,sql-error.jsp.
index.jsp页面:
<%--
Created by IntelliJ IDEA.
User: nuist__NJUPT
Date: 2021/8/14
Time: 11:24
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>所有演示的例子</h1>
<h3><a href = "${pageContext.request.contextPath}/daodb">
处理dao中的数据库异常
</a></h3>
<h3><a href = "${pageContext.request.contextPath}/daomy">
处理dao中的自定义异常
</a></h3>
<h3><a href = "${pageContext.request.contextPath}/daono">
处理dao中的未知异常
</a></h3>
<hr>
<h3><a href = "${pageContext.request.contextPath}/servicedb">
处理service层的数据库异常
</a></h3>
<h3><a href = "${pageContext.request.contextPath}/servicemy">
处理service层的自定义异常
</a></h3>
<h3><a href = "${pageContext.request.contextPath}/serviceno">
处理service层的未知异常
</a></h3>
<hr>
<h3><a href = "${pageContext.request.contextPath}/db">
处理controller层的数据库异常
</a></h3>
<h3><a href = "${pageContext.request.contextPath}/my">
处理controller层的自定义异常
</a></h3>
<h3><a href = "${pageContext.request.contextPath}/no">
处理controller层的未知异常
</a></h3>
<hr>
<!--在web.xml中配置404-->
<h3><a href = "${pageContext.request.contextPath}/404">
404错误
</a></h3>
</body>
</html>
未知异常error.jsp页面:
<%--
Created by IntelliJ IDEA.
User: nuist__NJUPT
Date: 2021/8/14
Time: 12:22
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<H1>未知错误:</H1> <%=exception%>>
<H2>错误内容:</H2>
<%
exception.printStackTrace(response.getWriter());
%>
</body>
</html>
自定义异常页面my-error.jsp:
<%--
Created by IntelliJ IDEA.
User: nuist__NJUPT
Date: 2021/8/14
Time: 12:25
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<H1>自定义异常错误:</H1> <%=exception%>
<H2>错误内容:</H2>
<%
exception.printStackTrace(response.getWriter());
%>
</body>
</html>
SQL异常对应页面sql-error.jsp:
<%--
Created by IntelliJ IDEA.
User: nuist__NJUPT
Date: 2021/8/14
Time: 12:27
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<H1>数据库异常错误:</H1> <%=exception%>
<H2>错误内容:</H2>
<%
exception.printStackTrace(response.getWriter());
%>
</body>
</html>
7-在web.xml部署DispatcherServlet,配置 CharacterEncodingFilter解决中文乱码问题对于UncheckedException而言,由于代码不强制捕获,往往被忽略,如果运行时候产生UncheckedException,而代码中又没有进行相应的捕获和处理,则可能不得不面对404,500等服务器内部错误提示页面,所以还需要在web.xml文件中添加全局异常404处理。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
id = "WebApp_ID" version="4.0">
<!--部署DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/springmvc-servlet.xml</param-value>
</init-param>
<!--表示容器启动时加载的servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--任意的请求都通过DispatcherServlet-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置 CharacterEncodingFilter解决中文乱码问题-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 配置编码格式为UTF-8 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/404.jsp</location>
</error-page>
</web-app>
从上述Dao层,Service层,Controller层的代码中看出,它们只管通过thow和throws抛储异常,并不处理。
SimpleMappingExceptionResolver类:
1-使用该类处理异常时候需要在配置文件中提前配置异常类和View的关系,配置文件springmvc-servlet.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--使用扫描机制,扫描控制器类,使得注解生效-->
<context:component-scan base-package="controller"/>
<context:component-scan base-package="service"/>
<context:component-scan base-package="dao"/>
<!--配置视图解析器-->
<bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver" id = "internalResourceViewResolver">
<!--前缀-->
<property name = "prefix" value = "/WEB-INF/jsp/"/>
<!--后缀-->
<property name = "suffix" value = ".jsp"/>
</bean>
<!--配置SimpleMappingExceptionResolver,异常类与View的对应关系-->
<bean class = "org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--定义默认异常处理页面,当该异常类型注册时候使用-->
<property name = "defaultErrorView" value="error"></property>
<!--定义异常处理页面来获取异常信息的变量名,默认名为exception-->
<property name = "exceptionAttribute" value="ex"/>
<!--定义需要进行特殊处理的异常,用类名或者完全路径名作为key,异常网页作为值-->
<property name = "exceptionMappings">
<props>
<prop key = "exception.MyException">my-error</prop>
<prop key = "java.sql.SQLException"以上是关于SpringMVC统一异常处理的主要内容,如果未能解决你的问题,请参考以下文章
javaweb异常提示信息统一处理(使用springmvc,附源码)
Spring MVC学习—项目统一异常处理机制详解与使用案例