SSM————SpringMVC
一、基本概念
三层架构和MVC

SpringMVC和Struts的异同:
共同点:
它们都是表现层框架,都是基于 MVC 模型编写的。
它们的底层都离不开原始 ServletAPI。
它们处理请求的机制都是一个核心控制器。
区别:
Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter 。
Spring MVC 是基于方法设计的,而 Struts2 是基于类,Struts2 每次执行都会创建一个动作类。所
以 Spring MVC 会稍微比 Struts2 快些。
Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便。
(JSR303 是一套 JavaBean 参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注
解加在我们 JavaBean 的属性上面,就可以在需要校验的时候进行校验了。)
Struts2 的 OGNL 表达式使页面的开发效率相比 Spring MVC 更高些,但执行效率并没有比 JSTL 提
升,尤其是 struts2 的表单标签,远没有 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>
<!--控制器jar包-->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--配置控制器需要的参数-->
<init-param>
<!--给springmvc一个别名-->
<param-name>contextConfigLocation</param-name>
<!--spring的路径-->
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--配置控制器的启动时间(默认为请求一次启动一次控制器,这里配置成服务器加载就一直启动)-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--配置控制器映射也就是控制器作用的地方-->
<servlet-mapping>
<!--因为是'/'所以基本上所有的请求都交由DispatcherServlet处理.-->
<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>
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="cn.itcast"/> <!-- 配置视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!--配置解析器读取的视图的路径和名称--> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean> <!-- 配置spring开启注解mvc的支持--> <mvc:annotation-driven/> </beans>
在 SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。
使 用 <mvc:annotation-driven> 自动加载 RequestMappingHandlerMapping (处理映射器) 和
RequestMappingHandlerAdapter ( 处 理 适 配 器 ) , 可 用 在 SpringMVC.xml 配 置 文 件 中 使 用
<mvc:annotation-driven>替代注解处理器和适配器的配置。
controller.java
package cn.itcast.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; //控制器,当页面就在的时候控制器已经把这个HelloController加载成实例,去等待请求使用 @Controller public class HelloController { //前端控制器会处理请求来这里 @RequestMapping(path="/hello") public String sayHello(){ System.out.println("hello springmvc"); return "success";//解析器会把返回值当成是页面名 } }
三、springmvc工作的详细流程:
springmvc框架基于组件方式执行流程:
package cn.itcast.controller; import cn.itcast.domain.Account; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/param") public class ParamController { @RequestMapping("/saveAccount") public String saveAccount(Account account){ System.out.println("执行了..,,"); System.out.println(account); return "success"; } }

四、springmvc的注解
@RequestMapping(" ")用于建立请求URL和处理方法之间的对应关系
出现位置:
类上:
请求 URL 的第一级访问目录。此处不写的话,就相当于应用的根目录。写的话需要以/开头
方法上:
请求 URL 的第二级访问目录。
属性:
value:用于指定请求的 URL。它和 path 属性的作用是一样的。当只有一个属性的时候可以不写默认为value和path。
method:用于指定请求的方式。
params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和
配置的一模一样。
例如:
params = {"accountName"},表示请求参数必须有 accountName
params = {"moeny!100"},表示请求参数中 money 不能是 100。
headers:用于指定限制请求消息头的条件。
注意:
以上四个属性只要出现 2 个或以上时,他们的关系是与的关系。
四、请求参数的绑定
我们都知道,表单中请求参数都是基于 key=value 的。 SpringMVC 绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的。 例如: <a href="account/findAccount?accountId=10">查询账户</a> 中请求参数是: accountId=10 /** * 查询账户 * @return */ @RequestMapping("/findAccount") public String findAccount(Integer accountId) { System.out.println("查询了账户。。。。"+accountId); return "success"; }
1、支持的数据类型:
(1)基本类型参数:
包括基本类型和 String 类型。
(2)POJO 类型参数:
包括实体类,以及关联的实体类。
请求参数绑定实体类型(实体类中嵌套另一个实体类):
例子:
User.java
1 package cn.itcast.domain;
2
3 import java.io.Serializable;
4
5 public class User implements Serializable{
6 private String uname;
7 private Integer age;
8
9 public String getUname() {
10 return uname;
11 }
12
13 public void setUname(String uname) {
14 this.uname = uname;
15 }
16
17 public Integer getAge() {
18 return age;
19 }
20
21 public void setAge(Integer age) {
22 this.age = age;
23 }
24
25 @Override
26 public String toString() {
27 return "User{" +
28 "uname='" + uname + '\'' +
29 ", age=" + age +
30 '}';
31 }
32 }
Account.java
1 package cn.itcast.domain;
2
3 import java.io.Serializable;
4
5 public class Account implements Serializable{
6 private String username;
7 private String password;
8 private double money;
9 private User user;
10 public String getUsername() {
11 return username;
12 }
13
14 public void setUsername(String username) {
15 this.username = username;
16 }
17
18 public String getPassword() {
19 return password;
20 }
21
22 public void setPassword(String password) {
23 this.password = password;
24 }
25
26 public double getMoney() {
27 return money;
28 }
29
30 public void setMoney(double money) {
31 this.money = money;
32 }
33
34 public User getUser() {
35 return user;
36 }
37
38 public void setUser(User user) {
39 this.user = user;
40 }
41
42 @Override
43 public String toString() {
44 return "Account{" +
45 "username='" + username + '\'' +
46 ", password='" + password + '\'' +
47 ", money=" + money +
48 ", user=" + user +
49 '}';
50 }
51 }
param.jsp
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
2 <html>
3 <head>
4 <title>Title</title>
5 </head>
6 <body>
7 <%--请求参数的绑定--%>
8 <%-- <a href="param/testParam?username=hehe">请求参数的绑定</a>--%>
9
10 <form action="param/saveAccount" method="post">
11 姓名:<input type="text" name="username"/><br/>
12 密码:<input type="text" name="password"/><br/>
13 金额:<input type="text" name="money"><br/>
14 用户姓名:<input type="text" name="user.uname"><br/>
15 用户年龄:<input type="text" name="user.age"><br/>
16 <input type="submit" value="提交"/>
17 </form>
18 </body>
19 </html>
ParamController.java
1 package cn.itcast.controller; 2 3 import cn.itcast.domain.Account; 4 import org.springframework.stereotype.Controller; 5 import org.springframework.web.bind.annotation.RequestMapping; 6 7 @Controller 8 @RequestMapping("/param") 9 public class ParamController { 10 @RequestMapping("/saveAccount") 11 public String saveAccount(Account account){ 12 System.out.println("执行了..,,"); 13 System.out.println(account); 14 return "success"; 15 16 } 17
请求参数绑定集合类型(实体类中嵌套集合):
User.java
1 package cn.itcast.domain; 2 3 import java.io.Serializable; 4 5 public class User implements Serializable{ 6 private String uname; 7 private Integer age; 8 9 public String getUname() { 10 return uname; 11 } 12 13 public void setUname(String uname) { 14 this.uname = uname; 15 } 16 17 public Integer getAge() { 18 return age; 19 } 20 21 public void setAge(Integer age) { 22 this.age = age; 23 } 24 25 @Override 26 public String toString() { 27 return "User{" + 28 "uname='" + uname + '\'' + 29 ", age=" + age + 30 '}'; 31 } 32 }
Account.java
1 package cn.itcast.domain; 2 3 import java.io.Serializable; 4 import java.util.List; 5 import java.util.Map; 6 7 public class Account implements Serializable{ 8 private String username; 9 private String password; 10 private double money; 11 private List<User> list; //list集合中装入User类型的数据 12 private Map<String,User> map; //map键值对中可以装入User类型的数据 13 14 public String getUsername() { 15 return username; 16 } 17 18 public void setUsername(String username) { 19 this.username = username; 20 } 21 22 public String getPassword() { 23 return password; 24 } 25 26 public void setPassword(String password) { 27 this.password = password; 28 } 29 30 public double getMoney() { 31 return money; 32 } 33 34 public void setMoney(double money) { 35 this.money = money; 36 } 37 38 public List<User> getList() { 39 return list; 40 } 41 42 public void setList(List<User> list) { 43 this.list = list; 44 } 45 46 public Map<String, User> getMap() { 47 return map; 48 } 49 50 public void setMap(Map<String, User> map) { 51 this.map = map; 52 } 53 54 @Override 55 public String toString() { 56 return "Account{" + 57 "username='" + username + '\'' + 58 ", password='" + password + '\'' + 59 ", money=" + money + 60 ", list=" + list + 61 ", map=" + map + 62 '}'; 63 } 64 }
param.xml
1 <%-- 2 Created by IntelliJ IDEA. 3 User: Administrator 4 Date: 2019/3/26 0026 5 Time: 下午 8:56 6 To change this template use File | Settings | File Templates. 7 --%> 8 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 9 <html> 10 <head> 11 <title>Title</title> 12 </head> 13 <body> 14 <%--请求参数的绑定--%> 15 <%--把数据封装Account类中,类中存在list和map的集合--%> 16 17 <form action="param/saveAccount" method="post"> 18 姓名:<input type="text" name="username"/><br/> 19 密码:<input type="text" name="password"/><br/> 20 金额:<input type="text" name="money"><br/> 21
//给列表中的 22 用户姓名:<input type="text" name="list[0].uname"><br/> 23 用户年龄:<input type="text" name="list[0].age"><br/> 24 25 用户姓名:<input type="text" name="map['one'].uname"><br/> 26 用户年龄:<input type="text" name="map['one'].age"><br/> 27 <input type="submit" value="提交"/> 28 </form> 29 </body> 30 </html>
ParamController.java
1 package cn.itcast.controller; 2 3 import cn.itcast.domain.Account; 4 import org.springframework.stereotype.Controller; 5 import org.springframework.web.bind.annotation.RequestMapping; 6 7 @Controller 8 @RequestMapping("/param") 9 public class ParamController { 10 @RequestMapping("/saveAccount") 11 public String saveAccount(Account account){ 12 System.out.println("执行了..,,"); 13 System.out.println(account); 14 return "success"; 15 16 } 17
SpringMVC 绑定请求参数是自动实现的,但是要想使用,必须遵循使用要求。
2、使用要求:
如果是基本类型或者 String 类型:
要求我们的参数名称必须和控制器中方法的形参名称保持一致。(严格区分大小写)
如果是 POJO 类型,或者它的关联对象:
要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型。
如果是集合类型,有两种方式:
第一种:
要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。
给 List 集合中的元素赋值,使用下标。
给 Map 集合中的元素赋值,使用键值对。
第二种:
接收的请求参数是 json 格式数据。需要借助一个注解实现。
五、解决中文乱码问题(看上面的web.xml文件)
六、自定义类型转换器
解决代码格式封装错误问题
使用步骤(web.xml和上面一样不用配):
1、定义一个类,实现Converter接口,该接口有两个泛型
2、配置springmvc
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:mvc="http://www.springframework.org/schema/mvc" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 6 xsi:schemaLocation=" 7 http://www.springframework.org/schema/beans 8 http://www.springframework.org/schema/beans/spring-beans.xsd 9 http://www.springframework.org/schema/mvc 10 http://www.springframework.org/schema/mvc/spring-mvc.xsd 11 http://www.springframework.org/schema/context 12 http://www.springframework.org/schema/context/spring-context.xsd"> 13 <!-- 配置spring创建容器时要扫描的包 --> 14 <context:component-scan base-package="cn.itcast"/> 15 <!-- 配置视图解析器 --> 16 <bean id="viewResolver" 17 class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 18 <!--配置解析器读取的视图的路径和名称--> 19 <property name="prefix" value="/WEB-INF/pages/"></property> 20 <property name="suffix" value=".jsp"></property> 21 </bean> 22 <!--配置自定义类型转换器--> 23 <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> 24 <!--把自己写的接口实现类配置到converters下-->
<property name="converters"> 25 <set> 26 <bean class="cn.itcast.utils.StringToDateConverter"></bean> 27 </set> 28 </property> 29 </bean> 30 31 <!-- 配置spring开启注解mvc的支持--> 32 <!--把上面的配置进行启动才能用,所以这里是配启动的--> 33 <mvc:annotation-driven conversion-service="conversionService"/> 34 35 </beans>
其他代码:
user.java
1 package cn.itcast.domain; 2 3 import java.io.Serializable; 4 import java.util.Date; 5 6 public class User implements Serializable{ 7 private String uname; 8 private Integer age; 9 private Date date; 10 public String getUname() { 11 return uname; 12 } 13 14 public void setUname(String uname) { 15 this.uname = uname; 16 } 17 18 public Integer getAge() { 19 return age; 20 } 21 22 public void setAge(Integer age) { 23 this.age = age; 24 } 25 26 public Date getDate() { 27 return date; 28 } 29 30 public void setDate(Date date) { 31 this.date = date; 32 } 33 34 @Override 35 public String toString() { 36 return "User{" + 37 "uname='" + uname + '\'' + 38 ", age=" + age + 39 ", date=" + date + 40 '}'; 41 } 42 }
web.xml
1 <!DOCTYPE web-app PUBLIC 2 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 3 "http://java.sun.com/dtd/web-app_2_3.dtd" > 4 5 <web-app> 6 <display-name>Archetype Created Web Application</display-name> 7 <!--配置控制器--> 8 <servlet> 9 <!--控制器名称--> 10 <servlet-name>dispatcherServlet</servlet-name> 11 <!--控制器jar包--> 12 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 13 <!--配置控制器需要的参数--> 14 <init-param> 15 <!--给springmvc一个别名--> 16 <param-name>contextConfigLocation</param-name> 17 <!--spring的路径--> 18 <param-value>classpath:springmvc.xml</param-value> 19 </init-param> 20 <!--配置控制器的启动时间(默认为请求一次启动一次控制器,这里配置成服务器加载就一直启动)--> 21 <load-on-startup>1</load-on-startup> 22 </servlet> 23 24 <!--配置控制器映射也就是控制器作用的地方--> 25 <servlet-mapping> 26 <!--因为是'/'所以基本上所有的请求都交由DispatcherServlet处理.--> 27 <servlet-name>dispatcherServlet</servlet-name> 28 <url-pattern>/</url-pattern> 29 </servlet-mapping> 30 31 <!--配置解决中文乱码问题的过滤器--> 32 <filter> 33 <!--起个过滤器的名字--> 34 <filter-name>characterEncodingFilter</filter-name> 35 <!--过滤器的路径--> 36 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 37 <!--过滤器的初始化参数--> 38 <init-param> 39 <param-name>encoding</param-name> 40 <param-value>UTF-8</param-value> 41 </init-param> 42 </filter> 43 <!--配置过滤映射,也就是过滤器作用的地方--> 44 <filter-mapping> 45 <!--用到的过滤器--> 46 <filter-name>characterEncodingFilter</filter-name> 47 <!--需要过滤的资源--> 48 <url-pattern>/*</url-pattern> 49 </filter-mapping> 50 </web-app>
param.jsp
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2019/3/26 0026 Time: 下午 8: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> <%--请求参数的绑定--%> <%--自定义类型转换--%> <form action="param/saveUser" method="post"> 用户姓名:<input type="text" name="uname"><br/> 用户年龄:<input type="text" name="age"><br/> 用户生日:<input type="text" name="date"> <input type="submit" value="提交"/> </form> </body> </html>
StringToDateConverter.java
1 package cn.itcast.utils; 2 import org.springframework.core.convert.converter.Converter; 3 import org.springframework.lang.Nullable; 4 5 import java.text.DateFormat; 6 import java.text.ParseException; 7 import java.text.SimpleDateFormat; 8 import java.util.Date; 9 10 public class StringToDateConverter implements Converter<String,Date> { 11 12 @Nullable 13 @Override 14 public Date convert(String source) { 15 if (source == null) { 16 throw new RuntimeException("请您传入数据"); 17 18 } 19 DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); 20 try { 21 return df.parse(source); //将字符串类型转换为date类型 22 } catch (ParseException e) { 23 throw new RuntimeException("数据类型转换出现错误"); 24 } 25 26 } 27 28 }
ParamController.java
1 package cn.itcast.controller; 2 3 import cn.itcast.domain.Account; 4 import cn.itcast.domain.User; 5 import org.springframework.stereotype.Controller; 6 import org.springframework.web.bind.annotation.RequestMapping; 7 8 @Controller 9 @RequestMapping("/param") 10 public class ParamController { 11 @RequestMapping("/saveUser") 12 public String saveUser(User user){ 13 System.out.println("执行了..,,"); 14 System.out.println(user); 15 return "success"; 16 17 } 18 }
七、获取Servlet原生的API
需要获取哪个API在方法参数中加入即可。
ParamController.java
1 package cn.itcast.controller; 2 3 import cn.itcast.domain.Account; 4 import cn.itcast.domain.User; 5 import org.springframework.stereotype.Controller; 6 import org.springframework.web.bind.annotation.RequestMapping; 7 8 import javax.servlet.ServletContext; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 import javax.servlet.http.HttpSession; 12 13 @Controller 14 @RequestMapping("/param") 15 public class ParamController { 16 /*原生的servlet*/ 17 @RequestMapping("/testServlet") 18 public String testServlet(HttpServletRequest request, HttpServletResponse response){ 19 System.out.println("执行了..,,"); 20 System.out.println(request); 21 HttpSession session = request.getSession(); 22 System.out.println(session); 23 ServletContext servletContext = session.getServletContext(); 24 System.out.println(servletContext); 25 System.out.println(response); 26 return "success"; 27 28 } 29 30 }
八、常用注解
1、RequestParam
作用:
把请求中指定名称的参数给控制中的形参赋值。
属性:
value:请求参数中的名称
required:请求参数中是否必须提供此参数,默认值:true,表示必须提供,如果不提供将报错。
例子:
anno.jsp
1 <%-- 2 Created by IntelliJ IDEA. 3 User: Administrator 4 Date: 2019/3/27 0027 5 Time: 下午 2:11 6 To change this template use File | Settings | File Templates. 7 --%> 8 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 9 <html> 10 <head> 11 <title>Title</title> 12 </head> 13 <body> 14 <%--常用的注解--%> 16 <a href="anno/testRequestParam?name=haha">RequestParam</a> 17 </body> 18 </html>
AnnoController.java
1 package cn.itcast.controller; 2 3 import org.springframework.stereotype.Controller; 4 import org.springframework.web.bind.annotation.RequestMapping; 5 import org.springframework.web.bind.annotation.RequestParam; 6 7 /* 8 *常用的注解 9 */ 10 @Controller 11 @RequestMapping("/anno") 12 public class AnnoController { 13 @RequestMapping("/testRequestParam")
//默认required为true必须传入name属性才能执行(传username都不行),否则报错 14 public String testRequestParam(@RequestParam(name="name") String username){ 15 System.out.println(username); 16 System.out.println("执行了..."); 17 return "success"; 19 } 21 }
2、RequestBody(后面json异步用到)
作用:
用于获取请求体内容,直接使用得到是key=value&key=value...结构的数据
get请求方式不适用
属性:
required:是否必须有请求体,默认值是:true,当取值为true时,get请求方式报错,如果取值为false,get请求得到是null。
例子:
anno.jsp
1 <%-- 2 Created by IntelliJ IDEA. 3 User: Administrator 4 Date: 2019/3/27 0027 5 Time: 下午 2:11 6 To change this template use File | Settings | File Templates. 7 --%> 8 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 9 <html> 10 <head> 11 <title>Title</title> 12 </head>
14 <%--常用的注解--%> 17 <form action="anno/testRequestBody" method="post"> 18 用户姓名:<input type="text" name="uname"><br/> 19 用户年龄:<input type="text" name="age"><br/> 20 <input type="submit" value="提交"/> 21 </form> 22 </body> 23 </html>
AnnoController.java
1 package cn.itcast.controller; 2 3 import org.springframework.stereotype.Controller; 4 import org.springframework.web.bind.annotation.RequestBody; 5 import org.springframework.web.bind.annotation.RequestMapping; 6 import org.springframework.web.bind.annotation.RequestParam; 7 8 /* 9 *常用的注解 10 */ 11 @Controller 12 @RequestMapping("/anno") 13 public class AnnoController { 14 15 /*获取到请求体的内容*/ 16 @RequestMapping("/testRequestBody") 17 public String testRequestBody(@RequestBody String body){ 18 System.out.println(body); 19 System.out.println("执行了..."); 20 return "success"; 21 } 23 }
3、PathVariable
作用:
用于绑定 url 中的占位符。例如:请求 url 中 /delete/{id},这个{id}就是 url 占位符。
url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志。
属性:
value:用于指定 url 中占位符名称。
required:是否必须提供占位符
*知识补充:REST风格URL
什么是rest:
REST(英文:Representational State Transfer,简称 REST)描述了一个架构样式的网络系统,
比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。在目前主流的三种 Web 服务交互方案中,REST 相比于 SOAP(Simple Object Access protocol,简单对象访问协议)以及 XML-RPC 更加简单明了,无论是对 URL 的处理还是对 Payload 的编码,REST 都倾向于用更加简单轻量的方法设计和实现。值得注意的是 REST 并没有一个明确的标准,而更像是一种设计的风格。
restful 的优点:
它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用

anno.jsp
1 <%-- 2 Created by IntelliJ IDEA. 3 User: Administrator 4 Date: 2019/3/27 0027 5 Time: 下午 2:11 6 To change this template use File | Settings | File Templates. 7 --%> 8 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 9 <html> 10 <head> 11 <title>Title</title> 12 </head> 13 <> 14 <%--常用的注解--%> 15 <a href="anno/testPathVariable/10">testPathVariable</a> 16 17 </body> 18 </html>
AnnoController.jav
1 package cn.itcast.controller; 2 3 import org.springframework.stereotype.Controller; 4 import org.springframework.web.bind.annotation.PathVariable; 5 import org.springframework.web.bind.annotation.RequestBody; 6 import org.springframework.web.bind.annotation.RequestMapping; 7 import org.springframework.web.bind.annotation.RequestParam; 8 9 /* 10 *常用的注解 11 */ 12 @Controller 13 @RequestMapping("/anno") 14 public class AnnoController { 15 @RequestMapping("/testPathVariable/{id}") 16 public String testPathVariable(@PathVariable(name = "id") String id){ 17 System.out.println(id); 18 System.out.println("执行了..."); 19 return "success"; 20 } 21 22 }
*4、HiddentHttpMethodFilter(了解,一般不用)
作用:
由于浏览器 form 表单只支持 GET 与 POST 请求,而 DELETE、PUT 等 method 并不支持,Spring3.0 添加了一个过滤器,可以将浏览器请求改为指定的请求方式,发送给我们的控制器方法,使得支持 GET、POST、PUT 与 DELETE 请求。
使用方法:
第一步:在 web.xml 中配置该过滤器。
第二步:请求方式必须使用 post 请求。
第三步:按照要求提供_method 请求参数,该参数的取值就是我们需要的请求方式
*5、RequestHeader
作用:
用于获取请求消息头。
属性:
value:提供消息头名称
required:是否必须有此消息头
注:在实际开发中一般不怎么用
![]()

*6、CookieValue
作用:
用于把指定 cookie 名称的值传入控制器方法参数。
属性:
value:指定 cookie 的名称。
required:是否必须有此 cookie。
![]()

7、ModelAttribute
作用:
该注解是 SpringMVC4.3 版本以后新加入的。它可以用于修饰方法和参数。出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。出现在参数上,获取指定的数据给参数赋值。
属性:
value:用于获取数据的 key。key 可以是 POJO 的属性名称,也可以是 map 结构的 key。
应用场景:当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。
例如:
我们在编辑一个用户时,用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数据是肯定没有此字段的内容,一旦更新会把该字段内容置为 null,此时就可以使用此注解解决问题。
anno.jsp
1 <%-- 2 Created by IntelliJ IDEA. 3 User: Administrator 4 Date: 2019/3/27 0027 5 Time: 下午 2:11 6 To change this template use File | Settings | File Templates. 7 --%> 8 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 9 <html> 10 <head> 11 <title>Title</title> 12 </head> 13 <> 14 <%--常用的注解--%> 15 16 <form action="anno/testModelAttribute" method="post"> 17 用户姓名:<input type="text" name="uname"><br/> 18 用户年龄:<input type="text" name="age"><br/> 19 <input type="submit" value="提交"/> 20 </form> 21 </body> 22 </html>
AnnoController.java
1 package cn.itcast.controller; 2 3 import cn.itcast.domain.User; 4 import org.springframework.stereotype.Controller; 5 import org.springframework.web.bind.annotation.*; 6 7 import java.util.Date; 8 import java.util.Map; 9 10 /* 11 *常用的注解 12 */ 13 @Controller 14 @RequestMapping("/anno") 15 public class AnnoController { 16 /*testModelAttribute注解*/ 17 @RequestMapping("/testModelAttribute") 18 public String testModelAttribute(@ModelAttribute("abc") User user){ 19 System.out.println("testModelAttribute执行了..."); 20 System.out.println(user); 21 return "success"; 22 } 23 24 //当传输的是不完整表单的时候不完整的数据可以去数据取出来封装好再用 25 @ModelAttribute 26 public Map showUser(String uname, Map<String,User> map){ 27 System.out.println("showUser执行了"); 28 User user = new User(); 29 user.setUname(uname); 30 user.setAge(10); 31 user.setDate(new Date()); 32 map.put("abc",user); 33 return map; 34 } 36 }
8、SessionAttribute
作用:
用于多次执行控制器方法间的参数共享。(只能用在类上)
属性:
value:用于指定存入的属性名称
type:用于指定存入的数据类型。
annol.jsp
1 <%-- 2 Created by IntelliJ IDEA. 3 User: Administrator 4 Date: 2019/3/27 0027 5 Time: 下午 2:11 6 To change this template use File | Settings | File Templates. 7 --%> 8 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 9 <html> 10 <head> 11 <title>Title</title> 12 </head> 13 <> 14 <%--常用的注解--%> 15 <a href="anno/testSessionAttributes">SessionAttributes</a> 16 <a href="anno/getSessionAttributes">getSessionAttributes</a> 17 <a href="anno/delSessionAttributes">delSessionAttributes</a> 18 </body> 19 </html>
AnnoController.java
package cn.itcast.controller; import cn.itcast.domain.User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.support.SessionStatus; import java.util.Date; import java.util.Map; /* *常用的注解 */ @Controller @RequestMapping("/anno") @SessionAttributes(value = {"msg"}) //把msg=美美存入到session域对象中 public class AnnoController { //这个方法是向域对象中存值 @RequestMapping("/testSessionAttributes") public String testSessionAttributes(Model model){ System.out.println("testSessionAttribute..."); model.addAttribute("msg","美美"); return "success"; } //这个方法是向域对象中取值 @RequestMapping("/getSessionAttributes") public String getSessionAttributes(ModelMap modelMap){ System.out.println("testSessionAttribute..."); String msg = (String) modelMap.get("msg"); System.out.println(msg); return "success"; } //这个方法是向域对象中删除值 @RequestMapping("/delSessionAttributes") public String delSessionAttributes(SessionStatus status) { System.out.println("delSessionAttribute..."); status.setComplete(); return "success"; } }
响应(response)
一、返回值分类
1、入门程序(返回一个字符串)【配置文件和封装与上面基本一样所以不重写了】
response.jsp
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2019/3/27 0027 Time: 下午 8:04 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> </body> </html>
UserController.java
package cn.itcast.controller; import cn.itcast.domain.User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/user") public class UserController { @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.addAttribute("user",user); return "success"; } }
success.jsp
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2019/3/27 0027 Time: 下午 8:00 To change this template use File | Settings | File Templates. --%>
// 在page directive中的isELIgnored属性用来指定是否忽略。格式为: <%@ page isELIgnored="true|false"%>
// 如果设定为真,那么JSP中的表达式被当成字符串处理。比如下面这个表达式${2000 % 20}, 在isELIgnored="true"时输出为${2000 % 20},
//而isELIgnored="false"时输出为100。Web容器默认isELIgnored="false"。 <%@ 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>
2、返回void
response.xml
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2019/3/27 0027 Time: 下午 8:04 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>
UserController.java
package cn.itcast.controller; import cn.itcast.domain.User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; @Controller @RequestMapping("/user") public class UserController { //返回值是void @RequestMapping("/testVoid") public void testVoid(HttpServletRequest request){ System.out.println("testVoid方法执行了"); //模拟从数据库中查询出User对象 } }
报404

返回值为空,会默认去查找与请求路径同名的jsp文件。(这是个不好的现象)
用以下方式去处理:
(1)使用request请求转发
package cn.itcast.controller; @Controller @RequestMapping("/user") public class UserController { /* 返回值是void 请求转发一次请求,不用编写项目的名称*/ @RequestMapping("/testVoid") public void testVoid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("testVoid方法执行了"); //因为是手动执行的servlet没有解析器对路径进行解析,所以不能只写jsp的名字如"success",必须写全相对路径 request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response); return;//加return是为了不让后面的代码继续执行,因为已经转发了,后面有些代码没必要执行 } }
(2)通过response重定向
package cn.itcast.controller; import cn.itcast.domain.User; @Controller @RequestMapping("/user") public class UserController { @RequestMapping("/testVoid") public void testVoid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("testVoid方法执行了"); //重定向 response.sendRedirect(request.getContextPath()+"/index.jsp"); return;//加return是为了不让后面的代码继续执行,因为已经转发了,后面有些代码没必要执行 } }
(3)通过response指定响应结果
package cn.itcast.controller; import cn.itcast.domain.User; @Controller @RequestMapping("/user") public class UserController { //通过输出流直接输出响应内容 //设置中文乱码 response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); response.getWriter().print("你好"); return;//加return是为了不让后面的代码继续执行,因为已经转发了,后面有些代码没必要执行 } }
3、返回ModelAndView对象(和上面的返回String类似)
ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值。
model方法。链接:https://blog.csdn.net/itbiggod/article/details/79685610
response.xml
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="user/testModelAndView">testModerAndView</a></br>
</body>
</html>
UserController.java
package cn.itcast.controller; import cn.itcast.domain.User; @Controller @RequestMapping("/user") public class UserController { /** * 返回ModelAndView对象 * @return */ @RequestMapping("/testModelAndView") public ModelAndView testModelAndView(){ //创建ModelAndView对象,Spring已经提供new就可以用了,相当于一个封装 ModelAndView mv = new ModelAndView(); System.out.println("testString方法执行了"); //模拟从数据库中查询出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; } }
二、转发和重定向
1、用关键字进行请求转发
(1)forward转发(controller 方法在提供了 String 类型的返回值之后,默认就是请求转发。我们也可以写成:)
response.java
package cn.itcast.controller;
import cn.itcast.domain.User;
@Controller
@RequestMapping("/user")
public class UserController {
/*
* 使用关键字的方式转发或者重定向
*
* */
@RequestMapping("/testForwardOrRedirect")
public String testForwardOrRedirect(){
System.out.println("testString方法执行了");
//请求转发,关键字forward
return "forward:/WEB-INF/pages/success.jsp";
}
}
需要注意的是,如果用了 formward:则路径必须写成实际视图 url,不能写逻辑视图。
它相当于“request.getRequestDispatcher("url").forward(request,response)”。使用请求
转发,既可以转发到 jsp,也可以转发到其他的控制器方法。
(2)redirect重定向(contrller 方法提供了一个 String 类型返回值之后,它需要在返回值里使用:redirect:)
package cn.itcast.controller;
import cn.itcast.domain.User;
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testForwardOrRedirect")
public String testForwardOrRedirect(){
System.out.println("testString方法执行了");
//请求转发,关键字redirect
//return "forward:/WEB-INF/pages/success.jsp";
//重定向
return "redirect:index.jsp";
}
}
它相当于“response.sendRedirect(url)”。需要注意的是,如果是重定向到 jsp 页面,则 jsp 页面不
能写在 WEB-INF 目录中,否则无法找到
三、ResponseBoy响应json数据
配置控制器对静态资源不拦截(否则执行不了jqery代码)。
(未封装)
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="cn.itcast"/> <!-- 配置视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!--配置解析器读取的视图的路径和名称--> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </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>
response.jsp
<%@ 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 () {
//ajax发请求
$.ajax({
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的数据,进行解析
}
});
});
});
</script>
</head>
<body>
<button id="btn">发送ajax请求</button>
</body>
</html>
UserController.java
package cn.itcast.controller; import cn.itcast.domain.User; @Controller @RequestMapping("/user") public class UserController { /* * 模拟异步请求和响应 * */ @RequestMapping("/testAjax") //@RequestBody 获取异步请求中请求体的内容 public void testAjax(@RequestBody String body){ System.out.println("testAjax方法执行了"); System.out.println(body); } }
(封装)
请求体中传输的属性和javabean中的属性相同,则spring会自动把传输的数据封装到javabean中
json字符串和javaBean对象相互转换的过程中,需要使用jackson的jar包。
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.0</version> </dependency>
response.jsp
<%@ 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 () {
//ajax发请求
$.ajax({
url:"user/testAjax",
contentType:"application/json;charset=UTF-8",
//通过@RequestBody后,data-->user
data:'{"username":"hehe","password":"123","age":"30"}',
dataType:"json",
type:"post",
success:function (data) {
//对服务器端响应的user的json数据,进行解析通过@ResponseBody后data-->user
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">testModerAndView</a></br>
<a href="user/testForwardOrRedirect">testModerAndView</a></br>
<button id="btn">发送ajax请求</button>
</body>
</html>
UserController.java
package cn.itcast.controller; import cn.itcast.domain.User; @Controller @RequestMapping("/user") public class UserController { @RequestMapping("/testAjax") //@RequestBody 获取异步请求中请求体的内容 //@ResponseBody 把返回值转成json的串 public @ResponseBody User testAjax(@RequestBody User user){ System.out.println("testAjax方法执行了"); //客户端发送ajax的请求,传的是json字符串,后台把json字符串封装到User对象中 System.out.println(user); //做响应,模拟查询数据库set user.setUsername("haha"); user.setAge(40); //做响应 return user; } }
SpringMVC实现文件上传
一、实现文件上传的一些条件
1、文件上传的必要前提:
(1)form 表单的 enctype 取值必须是:multipart/form-data(默认值是:application/x-www-form-urlencoded)
enctype:是表单请求正文的类型
(2)method 属性取值必须是 Post
(3)提供一个文件选择域<input type=”file” />
2、借助第三方组件实现文件上传
使用 Commons-fileupload 组件实现文件上传,需要导入该组件相应的支撑 jar 包:Commons-fileupload 和commons-io。commons-io 不属于文件上传组件的开发 jar 文件,但Commons-fileupload 组件从 1.1 版本开始,它工作时需要 commons-io 包的支持。
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency>
二、传统的方式上传代码
index.xml
<%@ 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>
</body>
</html>
UserController.java
package cn.itcast.controller; import org.apache.commons.fileupload.FileItem; @Controller @RequestMapping("/user") public class UserController { /** * 文件上传 * @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传统方式文件上传

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="cn.itcast"/> <!-- 配置视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!--配置解析器读取的视图的路径和名称--> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean> <!--配置文件解析器--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="10485760"/> </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>
package cn.itcast.controller; import org.apache.commons.fileupload.FileItem; @Controller @RequestMapping("/user") public class UserController { //SpringMVC文件上传 @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.getName(); // 把文件的名称设置唯一值,uuid String uuid = UUID.randomUUID().toString().replace("-", ""); filename = uuid+"_"+filename; // 完成文件上传 upload.transferTo(new File(path,filename)); return "success"; }
四、跨服器文件上传
package cn.itcast.controller; import com.sun.jersey.api.client.Client; @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异常处理
如果没有异常处理器那么异常的抛出和我们平时写代码一样很不美观,springmvc的异常处理是为了更加美观和人性地给用户抛出异常
一、概念:
系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端
控制器交由异常处理器进行异常处理,如下图:

二、入门程序
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="user/testException">异常处理</a>
</body>
</html>
编写自定义异常类
SysException.java
package cn.itcast.exception; 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; } }
编写异常处理器
SysExceptionResolver.java
package cn.itcast.exception; import org.springframework.lang.Nullable; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class SysExceptionResolver implements HandlerExceptionResolver{ /* 处理异常业务逻辑 */ public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, @Nullable Object o, 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; } }
配置异常处理器
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"></context:component-scan> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean> <!--前端控制器,哪些静态资源不拦截--> <mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 --> <mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 --> <mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript --> <!--配置异常处理器(只要程序中发生异常就往这个处理器中跳)--> <bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>
<mvc:annotation-driven ></mvc:annotation-driven> </beans>
异常显示界面
error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>-
<html>
<head>
<title>Title</title>
</head>
<body>
${errorMsg}
</body>
</html>
拦截器
一、概念
Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
过滤器和拦截器的区别:
过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。
拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的。
它也是 AOP 思想的具体应用。
我们要想自定义拦截器, 要求必须实现:HandlerInterceptor 接口。

二、入门程序
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h6>拦截器</h6>
<a href="user/testInterceptor">拦截器</a>
</body>
</html>
controller.java
package cn.itcast.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/user") public class UserController { @RequestMapping("/testInterceptor") public String testInterceptor() { System.out.println("testInterceptor执行了..."); return "success"; } }
编写拦截器类,实现HandlerInterceptor接口
MyInterceptor1.java
package cn.itcast.interceptor; import org.springframework.lang.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /* 自定义拦截器 */ public class MyInterceptor1 implements HandlerInterceptor{ @Override /** * 预处理 controller方法执行前 * return true 放行,执行下一个拦截器,如果没有执行controller中的方法 * return false 不放行, */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor执行了...前111"); //request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); return true; } /* 后处理方法,controller方法执行后,success.jsp执行之前 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor执行了..后111");
//request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); } /* success.jsp执行后,该方法会执行,最后执行的方法 这个不能再用请求转发 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("MyInterceptor执行了...最后111"); } }
MyInterceptor2.java
package cn.itcast.interceptor; import org.springframework.lang.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /* 自定义拦截器 */ public class MyInterceptor2 implements HandlerInterceptor{ @Override /** * 预处理 controller方法执行前 * return true 放行,执行下一个拦截器,如果没有执行controller中的方法 * return false 不放行, * */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor执行了...前222"); //request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); return true; } /* 后处理方法,controller方法执行后,success.jsp执行之前 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor执行了..后222"); request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); } /* success.jsp执行后,该方法会执行,最后执行的方法 这个不能再用请求转发 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("MyInterceptor执行了...最后222"); } }
配置拦截器
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"></context:component-scan> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean> <!--前端控制器,哪些静态资源不拦截--> <mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 --> <mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 --> <mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->
<!--配置拦截器--> <mvc:interceptors> <!--配置多个拦截器--> <mvc:interceptor> <!--要拦截的具体的方法--> <mvc:mapping path="/user/*"/> <!--不要拦截的方法--> <!-- <mvc:exclude-mapping path=""/>--> <!--配置拦截器对象--> <bean class="cn.itcast.interceptor.MyInterceptor1"/> </mvc:interceptor> <!--配置第二个拦截器--> <mvc:interceptor> <!--要拦截的具体的方法--> <mvc:mapping path="/**"/> <!--不要拦截的方法--> <!-- <mvc:exclude-mapping path=""/>--> <!--配置拦截器对象--> <bean class="cn.itcast.interceptor.MyInterceptor2"/> </mvc:interceptor> </mvc:interceptors> <mvc:annotation-driven ></mvc:annotation-driven> </beans>

浙公网安备 33010602011771号