上一篇:SpringMVC框架的实现文件上传
(1)pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atlantis</groupId>
<artifactId>exception</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>exception Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- 版本锁定 -->
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>exception</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
(2)web.xml
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 配置过滤器,解决中文乱码的问题 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 指定字符集 -->
<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>/*
DispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
1
DispatcherServlet
/
(3)springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置spring创建容器时要扫描的包 -->
<context:component-scan base-package="com.atlantis"/>
<!-- 配置视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 设置静态资源不被拦截 -->
<mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 -->
<mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 -->
<mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->
<!-- 配置spring开启注解mvc的支持-->
<mvc:annotation-driven />
</beans>
系统中异常包括两类:预期异常和运行时异常 RuntimeException
,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常处理,如下图:
可以发现,若不进行异常处理的话,异常信息会直接抛出到页面显示。这对用户而言是很不友好的,我们也不希望这种异常错误的页面被用户看到。因此下面我们来对异常进行处理,设置友好的页面来代替这些异常信息页面。
(1)编写自定义异常类
/**
* 自定义异常类
*/
public class SystemException extends Exception {
private String message; // 提示信息
public SystemException(String message) {
this.message = message;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
(2)修改控制器方法中异常捕获
@RequestMapping(value = "/testException")
public String testException() throws SystemException {
try {
// 模拟异常
int i = 2/0;
} catch (Exception e) {
// 控制台打印异常信息
e.printStackTrace();
// 抛出自定义异常信息
throw new SystemException("除数不能为0");
}
return "success";
}
(3)编写异常处理器,实现HandlerExceptionResolver接口
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 异常处理器
*/
public class SystemExceptionResolver implements HandlerExceptionResolver {
/**
* 处理异常的业务逻辑
*/
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
// 获取异常对象
SystemException ex = null;
if(ex instanceof SystemException) {
e = (SystemException) ex;
}else {
e = new SystemException("系统繁忙...");
}
ModelAndView mv = new ModelAndView();
// 存入错误的提示信息
mv.addObject("message", e.getMessage());
// 跳转的Jsp页面
mv.setViewName("error");
return mv;
}
}
(4)在springmvc.xml中配置异常处理器
<!-- 配置异常处理器 -->
<bean id="systemExceptionResolver" class="com.atlantis.exception.SystemExceptionResolver"/>
(5)编写error.jsp错误页面
可以自己做一个美观的错误提示页面,这里只为演示效果,所以简陋些。
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>error</title>
</head>
<body>
异常信息:${message}
</body>
</html>
SpringMVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。用户可以自己定义一些拦截器来实现特定的功能。
SpringMVC 的拦截器是 AOP 思想的具体应用,要想自定义拦截器, 要求必须实现 HandlerInterceptor 接口。
什么叫预处理和后处理?当浏览器或客户端的请求被拦截器拦截后,拦截器会先执行放行之前代码(预处理代码),然后把该请求放行给 Controller 或下一个拦截器,直到最后 Controller 响应浏览器或客户端时,又会被拦截器拦截,执行放行之后代码(后处理代码)。
谈到拦截器,还要向大家提一个词 —— 拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但是也有区别,接下来就说说它们的区别:
过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。
拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
过滤器在 url-pattern 中配置了/*
之后,可以对所有要访问的资源拦截。
拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image,js 等静态资源则不会进行拦截。
(1)编写自定义拦截器类,实现HandlerInterceptor接口
preHandle 方法是 controller 方法执行前执行:可以使用 request 或 response 跳转到指定的页面;return true
放行,执行下一个拦截器,如果没有拦截器,执行 controller 中的方法。return false
不放行,不会执行 controller 中的方法。
postHandle 方法是在 controller 方法执行后执行,在 jsp 视图执行前:可以使用 request 或者 response 跳转到指定的页面;如果指定了跳转的页面,那么 controller 方法跳转的页面将不会显示。
afterCompletion 方法是在 jsp 执行后执行:request 或 response 不能再跳转页面。
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定义拦截器类
*/
public class MyInterceptor implements HandlerInterceptor {
/**
* 预处理,Controller方法执行前执行。
* 返回值为false时不放行,不会执行后面任何代码。
* 返回值为true时放行,执行下一个拦截器,若没有则执行Controller方法。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Interceptor:preHandle()...预处理");
//request.getRequestDispatcher("WEB-INF/pages/error.jsp").forward(request,response);
return true;
}
/**
* 后处理
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Interceptor:postHandle()...后处理");
}
/**
* success.jsp页面执行后,该方法会被执行
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("Interceptor:afterCompletion()...最后处理");
}
}
(2)在springmvc.xml中配置拦截器类
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 要拦截的具体方法 -->
<mvc:mapping path="/testInterceptor"/>
<!-- 不要拦截的具体方法 -->
<!--<mvc:exclude-mapping path=""/>-->
<!-- 配置拦截器对象 -->
<bean class="com.atlantis.interceptor.MyInterceptor" />
</mvc:interceptor>
<!-- 可配置多个拦截器,按顺序执行 -->
</mvc:interceptors>