Spring MVC完整总结
- 1.SpringMVC的基本概念
- 2.SpringMVC的入门
- 3.请求参数的绑定
- 4.常用注解
- 5 响应数据和结果视图
- 6 SpringMVC实现文件上传
- 7 SpringMVC中的异常处理
- 8 SpringMVC中的拦截器
1.SpringMVC的基本概念
1.1 关于三层架构和MVC
1.1.1 三层架构
1.1.2 MVC模型
1.2 SpringMVC概述
1.2.1 SpringMVC是什么
1.2.2 SpringMVC在三层架构的位置
1.2.3 SpringMVC的优势
1.2.4 SpringMVC和Struts2的优略分析
2.SpringMVC的入门
2.1 SpringMVC的入门案例
2.1.1 前期准备
2.1.2 拷贝jar包
2.1.3 配置核心控制器-一个Servlet
2.1.4 创建spring mvc的配置文件
2.1.5 编写控制器并使用注解配置
2.1.6 测试
2.2 入门案例的执行过程及原理分析
2.2.1 案例的执行过程
1、服务器启动,应用被加载。读取到web.xml中的配置创建spring容器并且初始化容器中的对象。
从入门案例中可以看到的是:HelloController和InternalResourceViewResolver,但是远不止这些。
2、浏览器发送请求,被DispatherServlet捕获,该Servlet并不处理请求,而是把请求转发出去。转发的路径是根据请求URL,匹配@RequestMapping中的内容。
3、匹配到了后,执行对应方法。该方法有一个返回值。
4、根据方法的返回值,借助InternalResourceViewResolver找到对应的结果视图。
5、渲染结果视图,响应浏览器。
2.2.2 SpringMVC的请求响应流程
2.3 入门案例中涉及的组件
2.3.1 DispatcherServlet:前端控制器
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
2.3.2 HandlerMapping:处理器映射器
HandlerMapping负责根据用户请求找到Handler即处理器,SpringMVC提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
2.3.3 Handler:处理器
它就是我们开发中要编写的具体业务控制器。由DispatcherServlet把用户请求转发到Handler。由Handler对具体的用户请求进行处理。
2.3.4 HandlAdapter:处理器适配器
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
2.3.5 View Resolver:视图解析器
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
2.3.6 View:视图
SpringMVC框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。 一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
2.3.7 <.mvc:annotation-driven>说明
在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器称为SpringMVC的三大组件。
使用<.mvc:annotation-driven>自动加载RequestMappingHandlerMapping(处理映射器)和RequestMappingHandlerAdapter(处理适配器),可用在SpringMVC.xml配置文件中使用mvc:annotation-driven替代注解处理器和适配器的配置。
它就相当于在xml中配置了:
<!-- 上面的标签相当于 如下配置--> <!-- Begin --> <!-- HandlerMapping -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- HandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- HadnlerExceptionResolvers -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver"></bean>
<bean class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver"></bean>
2.4 RequestMapping注解
2.4.1 使用说明
2.4.2 使用示例
2.4.2.1 出现位置的示例:
2.4.2.2 method属性的示例:
2.4.2.3 params属性的示例:
3.请求参数的绑定
3.1 绑定说明
3.1.1 绑定的机制
3.1.2 支持的数据类型:
3.1.3 使用要求:
3.1.4 使用示例
3.1.4.1 基本类型和String类型作为参数
3.1.4.2 POJO类型作为参数
运行结果:
3.1.4.3 POJO类中包含集合类型参数
运行结果:
3.1.4.4 请求参数乱码问题
post请求方式:
web.xml
<!-- 配置springMVC编码过滤器 -->
<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>
<!-- 启动过滤器 -->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- 过滤所有请求 -->
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在springmvc的配置文件中可以配置,静态资源不过滤:
<!-- location表示路径,mapping表示文件,**表示该目录下的文件以及子目录的文件 -->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/scripts/" mapping="/javascript/**"/>
3.2 特殊情况
3.2.1 自定义类型转换器
3.2.1.1 使用场景:
运行结果:
3.2.1.2 使用步骤
/**
* 把字符串转换日期
*/
public class StringToDateConverter implements Converter<String,Date>{
/**
* String source 传入进来字符串
* @param source
* @return
*/
public Date convert(String source) {
// 判断
if(source == null){
throw new RuntimeException("请您传入数据");
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
// 把字符串转换日期
return df.parse(source);
} catch (Exception e) {
throw new RuntimeException("数据类型转换出现错误");
}
}
}
/**
* 自定义类型转换器
* @param user
* @return
*/
@RequestMapping("/saveUser")
public String saveUser(User user){
System.out.println("执行了...");
System.out.println(user);
return "success";
}
User
public class User implements Serializable{
private String uname;
private Integer age;
private Date date;
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "User{" +
"uname='" + uname + '\'' +
", age=" + age +
", date=" + date +
'}';
}
}
springmvc.xml
<!--配置自定义类型转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="cn.itcast.utils.StringToDateConverter"/>
</set>
</property>
</bean>
<!-- 开启SpringMVC框架注解的支持 -->
<mvc:annotation-driven conversion-service="conversionService"/>
3.2.2 使用ServletAPI对象作为方法参数
4.常用注解
4.1 RequestParam
4.1.1 使用说明
4.1.2 使用示例
4.2 RequestBody
4.2.1 使用说明
4.2.2 使用示例
post请求运行结果:
get请求运行结果:
4.3 PathVaribale
4.3.1 使用说明
4.3.2 使用示例
4.3.3 REST风格URL
4.3.4 基于HiddentHttpMethodFilter的示例
4.4 RequestHeader
4.4.1 使用说明
4.4.2 使用示例
4.5 CookieValue
4.5.1 使用说明
4.5.2 使用示例
4.6 ModelAttribute
4.6.1 使用说明
4.6.2 使用示例
4.6.2.1 基于POJO属性的基本使用:
4.6.2.2 基于Map的应用场景示例1:ModelAttribute修饰方法带返回值
4.6.2.3 基于Map的应用场景示例1:ModelAttribute修饰方法不带返回值
4.7 SessionAttribute
4.7.1 使用说明
4.7.2 使用示例
5 响应数据和结果视图
UserController
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 返回String
* @param model
* @return
*/
@RequestMapping("/testString")
public String testString(Model model){
System.out.println("testString方法执行了...");
// 模拟从数据库中查询出User对象
User user = new User();
user.setUsername("美美");
user.setPassword("123");
user.setAge(30);
// model对象
model.addAttribute("user",user);
return "success";
}
/**
* 是void
* 请求转发一次请求,不用编写项目的名称
*/
@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;
}
/**
* 返回ModelAndView
* @return
*/
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
// 创建ModelAndView对象
ModelAndView mv = new ModelAndView();
System.out.println("testModelAndView方法执行了...");
// 模拟从数据库中查询出User对象
User user = new User();
user.setUsername("小凤");
user.setPassword("456");
user.setAge(30);
// 把user对象存储到mv对象中,也会把user对象存入到request对象
mv.addObject("user",user);
// 跳转到哪个页面
mv.setViewName("success");
return mv;
}
/**
* 使用关键字的方式进行转发或者重定向
* @return
*/
@RequestMapping("/testForwardOrRedirect")
public String testForwardOrRedirect(){
System.out.println("testForwardOrRedirect方法执行了...");
// 请求的转发
// return "forward:/WEB-INF/pages/success.jsp";
// 重定向
return "redirect:/index.jsp";
}
/**
* 模拟异步请求响应
*/
@RequestMapping("/testAjax")
public @ResponseBody User testAjax(@RequestBody User user){
System.out.println("testAjax方法执行了...");
// 客户端发送ajax的请求,传的是json字符串,后端把json字符串封装到user对象中
System.out.println(user);
// 做响应,模拟查询数据库
user.setUsername("haha");
user.setAge(40);
// 做响应
return user;
}
}
User
public class User implements Serializable{
private String username;
private String password;
private Integer age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
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">
<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.itcast"/>
<!-- 视图解析器对象 -->
<bean id="internalResourceViewResolver" 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/**"/>
<!-- 开启SpringMVC框架注解的支持 -->
<mvc:annotation-driven />
</beans>
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>
<!--配置前端控制器-->
<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>
<!--配置解决中文乱码的过滤器-->
<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>
</web-app>
success.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/1
Time: 1:18
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>执行成功</h3>
${user.username}
${user.password}
</body>
</html>
index.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/1
Time: 1:06
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>
<h3>重定向</h3>
</body>
</html>
response.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/1
Time: 1:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="js/jquery.min.js"></script>
<script>
// 页面加载,绑定单击事件
$(function(){
$("#btn").click(function(){
// alert("hello btn");
// 发送ajax请求
$.ajax({
// 编写json格式,设置属性和值
url:"user/testAjax",
contentType:"application/json;charset=UTF-8",
data:'{"username":"hehe","password":"123","age":30}',
dataType:"json",
type:"post",
success:function(data){
// data服务器端响应的json的数据,进行解析
alert(data);
alert(data.username);
alert(data.password);
alert(data.age);
}
});
});
});
</script>
</head>
<body>
<a href="user/testString" >testString</a>
<br/>
<a href="user/testVoid" >testVoid</a>
<br/>
<a href="user/testModelAndView" >testModelAndView</a>
<br/>
<a href="user/testForwardOrRedirect" >testForwardOrRedirect</a>
<br/>
<button id="btn">发送ajax的请求</button>
</body>
</html>
5.1 返回值分类
5.1.1字符串
controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
//指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/pages/success.jsp
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 返回String
* @param model
* @return
*/
@RequestMapping("/testString")
public String testString(Model model){
System.out.println("testString方法执行了...");
// 模拟从数据库中查询出User对象
User user = new User();
user.setUsername("美美");
user.setPassword("123");
user.setAge(30);
// model对象
model.addAttribute("user",user);
return "success";
}
5.1.2void
/**
* 是void
* 请求转发一次请求,不用编写项目的名称
*/
@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;
}
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/1
Time: 1:16
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>
<a href="user/testString" >testString</a>
<br/>
<a href="user/testVoid" >testVoid</a>
<br/>
</body>
</html>
5.1.3 ModelAndView
ModelAndView是SpringMVC为我们提供的一个对象,该对象也可以用作控制器方法的返回值。
该对象中有两个方法:
/**
* 返回ModelAndView
* @return
*/
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
// 创建ModelAndView对象
ModelAndView mv = new ModelAndView();
System.out.println("testModelAndView方法执行了...");
// 模拟从数据库中查询出User对象
User user = new User();
user.setUsername("小凤");
user.setPassword("456");
user.setAge(30);
// 把user对象存储到mv对象中,也会把user对象存入到request对象
mv.addObject("user",user);
// 跳转到哪个页面
mv.setViewName("success");
return mv;
}
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/1
Time: 1:16
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>
<a href="user/testString" >testString</a>
<br/>
<a href="user/testVoid" >testVoid</a>
<br/>
<a href="user/testModelAndView" >testModelAndView</a>
<br/>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/1
Time: 1:18
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>执行成功</h3>
${user.username}
${user.password}
</body>
</html>
5.2 转发(forward)和重定向(Redirect)
return “forward:/WEB-INF/pages/success.jsp”
return “redirect:/index.jsp”
/**
* 使用关键字的方式进行转发或者重定向
* @return
*/
@RequestMapping("/testForwardOrRedirect")
public String testForwardOrRedirect(){
System.out.println("testForwardOrRedirect方法执行了...");
// 请求的转发
// return "forward:/WEB-INF/pages/success.jsp";
// 重定向
return "redirect:/index.jsp";
}
5.3 ResponseBody响应json数据
/**
* 模拟异步请求响应
*/
@RequestMapping("/testAjax")
public @ResponseBody User testAjax(@RequestBody User user){
System.out.println("testAjax方法执行了...");
// 客户端发送ajax的请求,传的是json字符串,后端把json字符串封装到user对象中
System.out.println(user);
// 做响应,模拟查询数据库
user.setUsername("haha");
user.setAge(40);
// 做响应
return user;
}
response.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/1
Time: 1:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="js/jquery.min.js"></script>
<script>
// 页面加载,绑定单击事件
$(function(){
$("#btn").click(function(){
// alert("hello btn");
// 发送ajax请求
$.ajax({
// 编写json格式,设置属性和值
url:"user/testAjax",
contentType:"application/json;charset=UTF-8",
data:'{"username":"hehe","password":"123","age":30}',
dataType:"json",
type:"post",
success:function(data){
// data服务器端响应的json的数据,进行解析
alert(data);
alert(data.username);
alert(data.password);
alert(data.age);
}
});
});
});
</script>
</head>
<body>
<a href="user/testString" >testString</a>
<br/>
<a href="user/testVoid" >testVoid</a>
<br/>
<a href="user/testModelAndView" >testModelAndView</a>
<br/>
<a href="user/testForwardOrRedirect" >testForwardOrRedirect</a>
<br/>
<button id="btn">发送ajax的请求</button>
</body>
</html>
6 SpringMVC实现文件上传
UserController
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 跨服务器文件上传
* @return
*/
@RequestMapping("/fileupload3")
public String fileuoload3(MultipartFile upload) throws Exception {
System.out.println("跨服务器文件上传...");
// 定义上传文件服务器路径
String path = "http://localhost:9090/uploads/";
// 说明上传文件项
// 获取上传文件的名称
String filename = upload.getOriginalFilename();
// 把文件的名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid+"_"+filename;
// 创建客户端的对象
Client client = Client.create();
// 和图片服务器进行连接
WebResource webResource = client.resource(path + filename);
// 上传文件
webResource.put(upload.getBytes());
return "success";
}
/**
* SpringMVC文件上传
* @return
*/
@RequestMapping("/fileupload2")
public String fileuoload2(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";
}
/**
* 文件上传
* @return
*/
@RequestMapping("/fileupload1")
public String fileuoload1(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";
}
}
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">
<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.itcast"/>
<!-- 视图解析器对象 -->
<bean id="internalResourceViewResolver" 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/**"/>
<!--配置文件解析器对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760" />
</bean>
<!-- 开启SpringMVC框架注解的支持 -->
<mvc:annotation-driven />
</beans>
success.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/4
Time: 21:58
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>
<h3>上传文件成功</h3>
</body>
</html>
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>
<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>
<!--配置解决中文乱码的过滤器-->
<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>
</web-app>
index.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/4
Time: 21:56
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>
<h3>传统文件上传</h3>
<form action="/user/fileupload1" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload" /><br/>
<input type="submit" value="上传" />
</form>
<h3>Springmvc文件上传</h3>
<form action="/user/fileupload2" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload" /><br/>
<input type="submit" value="上传" />
</form>
<h3>跨服务器文件上传</h3>
<form action="/user/fileupload3" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload" /><br/>
<input type="submit" value="上传" />
</form>
</body>
</html>
6.1 文件上传的回顾
6.1.1 文件上传的必要前提
6.1.2 文件上传的原理分析
6.1.3 借助第三方组件实现文件上传
/**
* 文件上传
* @return
*/
@RequestMapping("/fileupload1")
public String fileuoload1(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";
}
6.2 springmvc传统方式的文件上传
6.2.1说明
传统方式的文件上传,指的是我们上传的文件和访问的应用存在于同一台服务器上。 并且上传完成之后,浏览器可能跳转。
6.2.2 实现步骤
/**
* SpringMVC文件上传
* @return
*/
@RequestMapping("/fileupload2")
public String fileuoload2(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";
}
配置文件解析器
6.3 springmvc跨服务器方式的文件上传
6.3.1 分服务器的目的
6.3.2 准备两个tomcat服务器,并创建一个用于存放图片的web工程
/**
* 跨服务器文件上传
* @return
*/
@RequestMapping("/fileupload3")
public String fileuoload3(MultipartFile upload) throws Exception {
System.out.println("跨服务器文件上传...");
// 定义上传文件服务器路径
String path = "http://localhost:9090/uploads/";
// 说明上传文件项
// 获取上传文件的名称
String filename = upload.getOriginalFilename();
// 把文件的名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid+"_"+filename;
// 创建客户端的对象
Client client = Client.create();
// 和图片服务器进行连接
WebResource webResource = client.resource(path + filename);
// 上传文件
webResource.put(upload.getBytes());
return "success";
}
7 SpringMVC中的异常处理
7.1 异常处理的思路
7.2 实现步骤
7.2.1 编写异常类和错误页面
SysException
/**
* 自定义异常类
*/
public class SysException extends Exception{
// 存储提示信息的
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SysException(String message) {
this.message = message;
}
}
index.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/5
Time: 22:08
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>
<h3>异常处理</h3>
<a href="user/testException" >异常处理</a>
</body>
</html>
error.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/5
Time: 22:28
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${errorMsg}
</body>
</html>
success.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/5
Time: 22:11
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>
<h3>执行成功</h3>
</body>
</html>
7.2.2 自定义异常处理器
SysExceptionResolver
/**
* 异常处理器
*/
public class SysExceptionResolver implements HandlerExceptionResolver{
/**
* 处理异常业务逻辑
* @param request
* @param response
* @param handler
* @param ex
* @return
*/
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// 获取到异常对象
SysException e = null;
if(ex instanceof SysException){
e = (SysException)ex;
}else{
e = new SysException("系统正在维护....");
}
// 创建ModelAndView对象
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",e.getMessage());
mv.setViewName("error");
return mv;
}
}
7.2.3 配置异常处理器
springmvc.xml
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>
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">
<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.itcast"/>
<!-- 视图解析器对象 -->
<bean id="internalResourceViewResolver" 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/**"/>
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>
<!-- 开启SpringMVC框架注解的支持 -->
<mvc:annotation-driven />
</beans>
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>
<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>
<!--配置解决中文乱码的过滤器-->
<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>
</web-app>
7.2.4 运行结果:
8 SpringMVC中的拦截器
8.1 拦截器的作用
8.2 自定义拦截器的步骤及代码
MyInterceptor1
/**
* 自定义拦截器
*/
public class MyInterceptor1 implements HandlerInterceptor{
/**
* 预处理,controller方法执行前
* return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
* return false不放行
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1执行了...前1111");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
}
/**
* 后处理方法,controller方法执行后,success.jsp执行之前
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor1执行了...后1111");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
}
/**
* success.jsp页面执行后,该方法会执行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor1执行了...最后1111");
}
}
MyInterceptor2
/**
* 自定义拦截器
*/
public class MyInterceptor2 implements HandlerInterceptor{
/**
* 预处理,controller方法执行前
* return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
* return false不放行
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor2执行了...前2222");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
}
/**
* 后处理方法,controller方法执行后,success.jsp执行之前
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor2执行了...后2222");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
}
/**
* success.jsp页面执行后,该方法会执行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor2执行了...最后2222");
}
}
UserController
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testInterceptor")
public String testInterceptor(){
System.out.println("testInterceptor执行了...");
return "success";
}
}
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">
<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.itcast"/>
<!-- 视图解析器对象 -->
<bean id="internalResourceViewResolver" 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/**"/>
<!--配置拦截器-->
<mvc:interceptors>
<!--配置拦截器-->
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="/user/*"/>
<!--不要拦截的方法
<mvc:exclude-mapping path=""/>
-->
<!--配置拦截器对象-->
<bean class="cn.itcast.controller.cn.itcast.interceptor.MyInterceptor1" />
</mvc:interceptor>
<!--配置第二个拦截器-->
<mvc:interceptor>
<!--要拦截的具体的方法-->
<mvc:mapping path="/**"/>
<!--不要拦截的方法
<mvc:exclude-mapping path=""/>
-->
<!--配置拦截器对象-->
<bean class="cn.itcast.controller.cn.itcast.interceptor.MyInterceptor2" />
</mvc:interceptor>
</mvc:interceptors>
<!-- 开启SpringMVC框架注解的支持 -->
<mvc:annotation-driven />
</beans>
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>
<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>
<!--配置解决中文乱码的过滤器-->
<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>
</web-app>
index.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/5
Time: 22:08
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>
<h3>拦截器</h3>
<a href="user/testInterceptor" >拦截器</a>
</body>
</html>
success.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/5
Time: 22:11
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>
<h3>执行成功</h3>
<% System.out.println("success.jsp执行了..."); %>
</body>
</html>
error.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/5/5
Time: 23:06
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>
<h3>错误页面</h3>
</body>
</html>
8.3 拦截器的细节
8.3.1 拦截器的放行
preHandle预处理,controller方法执行前
* return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
* return false不放行
8.3.2 拦截器中方法的说明
8.3.3 拦截器的作用路径
8.3.4 多个拦截器的执行顺序
多个拦截器是按照配置的顺序决定的。