SpringMVC框架
1. SpringMVC 入门案例
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种用于设计创建 Web 应用程序表现层的模式。
三层架构:
①SpringMVC的概述
1. 是一种基于Java实现的MVC设计模型的请求驱动类型的轻量级WEB框架。
2. Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供
了构建 Web 应用程序的全功能 MVC 模块。
3. 使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的
SpringMVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts2等。
② SpringMVC在三层架构中的位置
1. 表现层框架
③ SpringMVC和Struts2框架的对比
共同点:
它们都是表现层框架,都是基于MVC模型编写的。
它们的底层都离不开原始ServletAPI。
它们处理请求的机制都是一个核心控制器。
区别:
Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
Spring MVC 是基于方法设计的,而Struts2是基于类,Struts2每次执行都会创建一个动作类。所以Spring MVC 会稍微比 Struts2 快些。
Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便
Struts2 的OGNL 表达式使页面的开发效率相比Spring MVC 更高些,但执行效率并没有比JSTL提升,尤其是struts2的表单标签,远没有html执行效率高。
1.1 入门案例
①创建maven工程,webapp项目。导包。
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>springmvc_day01_01_start</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>springmvc_day01_01_start Maven Webapp</name>
<url>http://maven.apache.org</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>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>springmvc_day01_01_start</finalName>
</build>
</project>
②在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>/*</url-pattern>
</filter-mapping>
<!-- 前端控制器配置-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
③resources目录下创springmvc.xml配置springmvc
<?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">
<!--开启注解的扫描-->
<context:component-scan base-package="org.example"></context:component-scan>
<!--配置视图解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--配置自定义类型转换器-->
<bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="org.example.utils.StringToDateConverter"></bean>
</set>
</property>
</bean>
<!--开启springmvc注解的支持,并配置类型转换器使其生效,即conversion-service-->
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"></mvc:annotation-driven>
</beans>
④编写控制器并使用注解配置
@Controller
public class HelloController {
/**
* RequestMapping : 用于建立请求URL和处理请求方法之间的对应关系。
* @return
*/
@RequestMapping(path="/hello")
public String sayHello(){
System.out.println("Hello StringMVC");
return "success";
}
⑤创建success.jsp用于界面的跳转,当点击超链接时跳转。index.xml文件,指定url请求
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入门程序</h3>
<a href="hello">入门程序</a>
</body>
</html>
⑥部署到Tomcat,启动运行。
1.2 案例执行过程分析
①springmvc的请求响应流程
②整体流程
1.3 springMVC中的组件
①DispatcherServlet:前端控制器
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
②HandlerMapping:处理器映射器
HandlerMapping负责根据用户请求找到Handler即处理器,SpringMVC提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
③Handler:处理器
它就是我们开发中要编写的具体业务控制器。由DispatcherServlet把用户请求转发到Handler。由Handler对具体的用户请求进行处理。
④HandlerAdapter:处理器适配器
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
⑤View Resolver:视图解析器
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
⑥View:视图
SpringMVC框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。
1.4 mvc:annotation-driven
用mvc:annotation-driven自动加载RequestMappingHandlerMapping(处理映射器)和RequestMappingHandlerAdapter(处理适配器),可用在SpringMVC.xml配置文件中使用mvc:annotation-driven替代注解处理器和适配器的配置。
1.5 RequestMapping注解
作用: 用于建立请求URL和处理请求方法之间的对应关系。
属性:
value:用于指定请求的URL。它和path属性的作用是一样的。
method:用于指定请求的方式。
params:用于指定限制请求参数的条件。它支持简单的表达式。
要求请求参数的key和value必须和配置的一模一样。
1.5.1 params属性
/** 删除账户
* @return
*/
@RequestMapping(value="/removeAccount",params= {"accountName","money>100"})
public String removeAccount() {
System.out.println("删除了账户");
return "success";
}
jsp中的代码:
<!-- 请求参数的示例 -->
<a href="account/removeAccount?accountName=aaa&money>100">删除账户,金额100</a> <br/>
<a href="account/removeAccount?accountName=aaa&money>150">删除账户,金额150</a>
注意:
当我们点击第一个超链接时,可以访问成功。
当我们点击第二个超链接时,无法访问。
1.6 请求参数绑定
1.绑定机制
- 表单提交的数据都是k=v格式,username=haha&password=123
- SpingMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的。
- 要求:提交表单的name和参数的名称是相同的。
① 一般情况:
<a href="account/findAccount?accountId=10">查询账户</a>
中请求参数是: accountId=10
/**
*查询账户
* @return
* */
@RequestMapping("/findAccount")
public String findAccount(Integer accountId) {
System.out.println("查询了账户。。。。"+accountId);
}
②POJO类型作为参数
jsp:
<%-- 把数据封装到Account类中--%>
<form action="param/saveAccount" method="post">
姓名:<input type="text" name="username"><br/>
密码:<input type="text" name="password"><br/>
金额:<input type="text" name="money"><br/>
用户姓名:<input type="text" name="user.uname"><br/>
用户年龄:<input type="text" name="user.age"><br/>
<input type="submit" value="提交"><br/>
</form>
其中User作为Account类中的一个属性,如果要将数据封装到User类里的属性uname和age,需要通过user.uname实现。
③ POJO类包含集合类型
用户姓名:<input type="text" name="list[0].uname"><br/>
<%--把文本框的输入封装到user的uname中,在添加到list的0位置上
用户年龄:<input type="text" name="list[0].age"><br/>
<%--把文本框的输入封装到user的uname中,在添加到map中,map的key为字符串‘one’
用户姓名:<input type="text" name="map['one'].uname"><br/>
用户年龄:<input type="text" name="map['one'].age"><br/>
public class Account implements Serializable {
private String username;
private String password;
private Double money;
private List<User> list;
private Map<String,User> map;
1.7 过滤器
在springmvc的配置web.xml文件进行配置时,dispatcherServlet对象会处理对应的URL,一般我们使用/,其表示对所有的url进行拦截,但是我们一般不会对静态资源进行拦截,因此需要在springmvc.xml中配置不需要拦截的数据。
<!-- location表示路径,mapping表示文件,**表示该目录下的文件以及子目录的文件 -->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/scripts/" mapping="/javascript/**"/>
说明:
location元素表示webapp目录下的static包下的所有文件;
mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b;
该配置的作用是:DispatcherServlet不会拦截以/static开头的所有请求路径,并当作静态资源
交由Servlet处理。
1.8 自定义类型转换器
对于有时输入的日期类型与库内的类型不匹配时,需要自定义类型转换器。
①创建对应的转换类,其需要实现Converter接口。
public class StringToDateConverter implements Converter<String,Date>{
@Override
public Date convert(String s) {
//1.判断
if(s == null){
throw new RuntimeException("输入数据为空...");
}
DateFormat df = new SimpleDateFormat("yyyy-mm-dd");
//2.把字符串转换为日期
try {
return df.parse(s);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
②在spring配置文件中配置类型转换器
<!--配置自定义类型转换器-->
<bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="org.example.utils.StringToDateConverter"></bean>
</set>
</property>
</bean>
③在annotation-driven标签中引用配置的类型转换
<!--开启springmvc注解的支持,并配置类型转换器使其生效,即conversion-service-->
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"></mvc:annotation-driven>
1.9 常用注解
①RequestParam:
作用:
把请求中指定名称的参数给控制器中的形参赋值。
value:请求参数中的名称
required:请求参数中是否必须提供此参数。默认值:true。表示必须提供,如果不提供,报错。
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam(name = "name") String username){
System.out.println("well done");
System.out.println(username);
return "success";
}
<a href="anno/testRequestParam?name=哈哈">RequestParam</a>
②RequestBody:
作用:
用于获取请求体内容。直接使用得到是key=value&key=value...结构的数据。
required:是否必须有请求体。默认为true。当取值为true时,get请求方式会报错。如果为false,get请求得到的是null。
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String body){
System.out.println("well done");
System.out.println(body);
return "success";
}
<form action="anno/testRequestBody" method="post">
用户姓名:<input type="text" name="username"><br/>
用户年龄:<input type="text" name="age"><br/>
<input type="submit" value="提交"><br/>
</form>
③RequestVariable:
作用:
用于绑定url中的占位符。例如:请求url中/delete/{id},这个{id}就是url占位符。
@RequestMapping(value = "/testPathVariable/{uid}")
public String testPathVariable(@PathVariable(name = "uid") String id){
System.out.println("well done");
System.out.println(id);
return "success";
}
<a href="anno/testPathVariable/10">PathVariable</a>
④RequestHeader:
作用:
用于获取请求消息头。
@RequestMapping(value = "/testRequestHeader")
public String testRequestHeader(@RequestHeader(value = "Accept") String header){
System.out.println("well done");
System.out.println(header);
return "success";
<a href="anno/testRequestHeader">RequestHeader</a>
⑤CookieValue
作用:
用于把指定cookie名称的值传入控制器方法参数。
@RequestMapping(value = "/testCookieValue")
public String testCookieValue(@CookieValue(value = "JSESSIONID") String cookieValue){
System.out.println("well done");
System.out.println(cookieValue);
return "success";
}
<a href="anno/testCookieValue">CookieValue</a>
⑥ModelAttribute:
作用:
出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。
它可以修饰没有返回值的方法,也可以修饰有返回值的方法。
出现在参数上,获取指定的数据给参数赋值。
@RequestMapping(value = "/testModelAttribute")
public String testModelAttribute(@ModelAttribute(value = "abc") User user){
System.out.println("testModelAttribute执行完成了....");
System.out.println(user);
return "success";
}
@ModelAttribute
public void showUser(String uname, Map<String,User> map){
System.out.println("showUser...........");
//通过用户名查询数据库(模拟)
User user = new User();
user.setUname(uname);
user.setAge(20);
user.setDate(new Date());
map.put("abc",user);
}
⑦SessionAttributes:
作用:
用于多次执行控制器方法间的参数共享。
value:用于指定存入的属性名称。
type:用于指定存入的数据类型。
@SessionAttributes(value = {"msg"}) //把msg=布布存放到session域对象中
public class AnnoController {
@RequestMapping(value = "/testSessionAttributes")
public String testSessionAttributes(Model model){
System.out.println("testSessionAttribute执行完成了....");
//底层会存储到request域对象中
model.addAttribute("msg","布布");
return "success";
}
/**
* 从Session域中获取值
* @param modelMap
* @return
*/
@RequestMapping(value = "/getSessionAttributes")
public String getSessionAttributes(ModelMap modelMap){
System.out.println("getSessionAttribute执行完成了....");
//底层会存储到request域对象中
String msg = (String)modelMap.get("msg");
System.out.println(msg);
return "success";
}
/**
* 清楚session
* @param status
* @return
*/
@RequestMapping(value = "/deleteSessionAttributes")
public String deleteSessionAttributes(SessionStatus status){
System.out.println("deleteSessionAttribute执行完成了....");
status.setComplete();
return "success";
}
}
<a href="anno/testSessionAttributes">TestSessionAttributes</a>
<a href="anno/getSessionAttributes">GetSessionAttributes</a>
<a href="anno/deleteSessionAttributes">DeleteSessionAttributes</a>
2. 响应数据和结果视图
2.1 ModelAndView
ModelAndView是springmvc提供的一个对象,该对象可以用作控制器方法的返回值。
①之前我们可以通过Model获取返回值。
@RequestMapping("/testString")
public String testString(Model model){
System.out.println("testString方法执行了.....");
//模拟从数据库中查询出user对象
User user = new User();
user.setUsername("妹妹");
user.setPassword("13224");
user.setAge(45);
//model对象
model.addAttribute("user",user);
return "success";
}
<a href="user/testString">TestString</a>
②也可以通过servlet的API获取
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception{
System.out.println("testVoid方法执行了.....");
//编写请求转发的程序
//request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
//重定向
//response.sendRedirect(request.getContextPath() + "/index.jsp");
//设置中文乱码
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//直接进行相应
response.getWriter().print("你好");
return;
}
<a href="user/testVoid">TestVoid</a>
③现在通过ModelAndView实现。
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
//创建ModelAndView
ModelAndView mv = new ModelAndView();
System.out.println("testModelAndView方法执行了.....");
//模拟从数据库中查询出user对象
User user = new User();
user.setUsername("龙龙");
user.setPassword("1232");
user.setAge(45);
//把user对象存储到mv对象中,也会把user对象存入到request对象
mv.addObject("user",user);
//跳转到哪个页面
mv.setViewName("success");
return mv;
}
<a href="user/testModelAndView">TestModelAndView</a>
2.2 转发和重定向
①forward转发和redirect重定向
/**
* 关键字的方式进行转发或者重定向
* 此方法不能使用视图解析器,必须手动指定跳转的页面
* @param
* @return
*/
@RequestMapping("/testForwardOrRedirect")
public String testForwardOrRedirect(){
System.out.println("testForwardOrRedirect方法执行了.....");
//请求的转发
//return "forward:/WEB-INF/pages/success.jsp";
//重定向:不能直接访问到pages下面的jsp
return "redirect:/index.jsp";
}
<a href="user/testForwardOrRedirect">TestForwardOrRedirect</a>
2.3 ResponseBody响应json数据
作用:
该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端.
需要导入以下jar包:
/**
* 模拟异步请求响应
*/
@RequestMapping("/testAjax")
@ResponseBody
public User testAjax(@RequestBody User user){
System.out.println("testAjax方法执行了.....");
//客户端发送ajax的请求,传的是json字符串,后端把json字符串封装到user对象中
System.out.println(user);
//做响应,模拟查询数据库
user.setUsername("haha");
user.setAge(98);
//做响应
return user;
}
<head>
<title>Title</title>
<script src="js/jquery.min.js"></script>
<script>
//页面加载,绑定单击事件
$(function () {
$("#btn").click(function () {
//alert("hello everyone");
//发送ajax请求
$.ajax({
//编写json格式,设置属性和值
url:"user/testAjax",
contentType:"application/json;charset=UTF-8",
data:'{"username":"hehe","password":"123","age":36}',
dataType:"json",
type:"post",
success:function (data) {
//data服务器端响应的json的数据,进行解析
alert(data);
alert(data.username);
alert(data.password);
alert(data.age);
}
});
});
});
</script>
</head>
<button id="btn">发送ajax请求</button>
3.springmvc实现文件上传
①文件上传的必要前提
1. form表单的enctype取值必须是:
multipart/form-data(默认值是:application/x-www-form-urlencoded)
enctype:表单请求正文的类型。
2. method属性取值必须是post。
3. 提供一个文件选择域<input type="file" />
②导包 commons-fileupload和commons-io
3.1 传统方式上传
@RequestMapping("/fileUpload1")
public String fileUpload1(HttpServletRequest request) throws Exception {
System.out.println("文件上传...");
//使用fileupload组件实现文件上传
//上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
//判断,该路径是否存在
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
//解析request对象,获取上传文件项
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
//解析request
List<FileItem> items = upload.parseRequest(request);
//遍历
for(FileItem item : items){
//判断,当前item对象是否是上传文件项
if(item.isFormField()){
//说明普通表单项
}else{
//说明上传文件项
//获取上传文件的名称
String filename = item.getName();
//把文件的名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + "_" + filename;
//完成文件上传
item.write(new File(path,filename));
//删除临时文件
item.delete();
}
}
return "success";
}
<h3>文件上传</h3>
<form action="user/fileUpload1" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"><br>
<input type="submit" value="上传">
</form>
配置文件解析器:
<bean id="multipartResolver" <!--id的值是固定的-->
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置上传文件的最大尺寸为10MB-->
<property name="maxUploadSize" value="10485760"></property>
</bean>
注意:
文件上传解析器id是固定的,不能起别名,否则无法实现请求参数的绑定。
3.2 springmvc方式的文件上传
@RequestMapping("/fileUpload2")
public String fileUpload2(HttpServletRequest request, MultipartFile upload) throws Exception {
System.out.println("springmvc文件上传...");
//使用fileupload组件实现文件上传
//上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
//判断,该路径是否存在
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
//说明上传文件项
//获取上传文件的名称
String filename = upload.getOriginalFilename();
//把文件的名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + "_" + filename;
//完成文件上传
upload.transferTo(new File(path,filename));
return "success";
}
<form action="user/fileUpload2" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"><br>
<input type="submit" value="上传">
</form>
4. springmvc的异常处理
系统的dao,service,controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行处理。
①编写异常类
public class SysException extends Exception {
//存储提示信息的
private String message;
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SysException(String message) {
this.message = message;
}
}
②编写jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${errorMsg}
</body>
</html>
③自定义异常处理器(需要实现HandlerExceptionResolver接口)
public class SysExceptionResolver implements HandlerExceptionResolver {
/**
* 处理异常业务逻辑
* @param request
* @param response
* @param o
* @param e
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
//获取到异常对象
SysException exception = null;
if(e instanceof SysException){
exception = (SysException) e;
}else{
e = new SysException("系统正在维护....");
}
//创建ModelAndView对象
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",exception.getMessage());
mv.setViewName("error");
return mv;
}
}
④配置异常处理器
<!--配置异常处理器对象-->
<bean id="sysExceptionResolver" class="org.example.exception.SysExceptionResolver"></bean>
⑤运行
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testException")
public String testException() throws SysException{
System.out.println("testException方法执行了.....");
try {
//模拟异常
int a = 1 / 0;
} catch (Exception e) {
//打印异常信息
e.printStackTrace();
//抛出自定义异常信息
throw new SysException("查询所有用户出现错误了.....");
}
return "success";
}
}
⑥分析:
当运行服务器时,点击页面的超链接会执行testException方法,但是其存在异常,异常处理器获取到异常,执行对应的自定义异常处理器,根据异常的类型,跳转页面。
5.springmvc框架中的拦截器
Spring MVC 的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
过滤器和拦截器的区别:
过滤器是servlet规范中的一部分,任何java web工程都可以使用。
拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用。
过滤器在url-pattern中配置了/*之后,可以对所有要访问的资源拦截。
拦截器它是只会拦截访问的控制器方法,如果访问的是jsp,html,css,image或者js是不会进行拦截的。
自定义拦截器,必须实现HandlerInterceptor接口。
①自定义拦截器实现HandlerInterceptor接口
public class MyInterceptor1 implements HandlerInterceptor {
/**
* 预处理,controller方法执行前执行的
* return true表示放行。执行下一个拦截器,如果没有,执行controller中的方法
* return false表示不放行。
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("MyInterceptor1执行了....前111111111111");
//httpServletRequest.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(httpServletRequest,httpServletResponse);
return true;
}
/**
* 后处理的方法,controller方法执行后,success.jsp执行之前
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor1执行了....后1111111111111");
//httpServletRequest.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(httpServletRequest,httpServletResponse);
}
/**
* success.jsp页面执行后,该方法会执行
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("MyInterceptor1执行了....吼吼吼吼后111111111");
}
}
②配置拦截器:此处配置了两个拦截器,根据配置的顺序不同,其执行的顺序也不同。
<!--配置拦截器-->
<mvc:interceptors>
<!--配置拦截器1-->
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="/user/**"/>
<!--不要拦截的方法
<mvc:exclude-mapping path=""/>
-->
<!--配置拦截器对象-->
<bean class="org.example.interceptor.MyInterceptor1"></bean>
</mvc:interceptor>
<!--配置拦截器2 :配置的拦截器顺序决定拦截的顺序-->
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="/**"/>
<!--不要拦截的方法
<mvc:exclude-mapping path=""/>
-->
<!--配置拦截器对象-->
<bean class="org.example.interceptor.MyInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
③编写jsp文件
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>拦截器</h3>
<a href="user/testInterceptor">拦截器</a>
</body>
</html>
error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>错误页面</h3>
</body>
</html>
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>执行成功</h3>
<% System.out.println("success.jsp执行了...."); %>
</body>
</html>
④结果
分析:多个拦截器的执行过程