springmvc执行流程:
SpringMVC框架也是一个基干请求驱动的Web框架,并且使用了前端控制器模式(是用来提供一个集中的请
求处理机制,所有的请求都将由一个单一的处理程序处理来进行设计,再根据请求映射规则分发给相应的页面控制器(动作/处理器)进行处理。首先让我们整体看一下SpringMVC处理请求的流程:
1.首先用户发送请求请求被SpringMvc前端控制器(DispatherServlet)捕获;
2.前端控制器(DispatherServlet)对请求URL解析获取请求URI根据URI,调用HandlerMapping)
3.前端控制器(DispatherServlet)获得返回的HandlerExecutionChain(包括Handler对象以及Handler对象对应的拦截器);
4.DispatcherServlet根据获得的HandlerExecutionChain,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHander(…)方法);
5.HandlerAdapter根据请求的Handler适配并执行对应的Handler;HandlerAdapter(提取Reauest中的模型数
据,填充Handler入参,开始执行Handler(Controller)。在填充Handler的入参过程中,根据配置,Spring将做一些额外的工作:
HttpMessageConveter:将请求消息 (如lsonxml等数据)转换成一个对象,将对象转换为指定的响应信
息。
数据转换:对请求消息进行数据转换。如String转换成IntegerDouble等数据格式化:
数据格式化。如将字符串转换成格式化数字或格式化日期等
数据验证:验证数据的有效性(长度,格式等),验证结果存储到BindingResult或Error中)
6.Handler执行完毕,返回一个ModelAndView(即模型和视图)给HandlerAdaptor
7.HandlerAdaptor话配器将执行结果ModelAndView返回给前端控制器。
8.前端控制器接收到ModelAndView后,请求对应的视图解析器。
9.视图解析器解析ModelAndView后返回对应View
10.渲染视图并返回渲染后的视图给前端控制器。
首先创建web项目哈
要想使用springMvc 首先肯定就是搭建环境,老套路了
<packaging>war</packaging>
<dependencies>
<dependency>
<!--springmvc是依赖于servlet的-->
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<!--provided指的是在编译和测试过程中有效,最后生成的war包时不会加入-->
<scope>provided</scope>
</dependency>
<dependency>
<!--这个不用多说了吧-->
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<dependency>
<!--json依赖-->
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<!--配置web服务器.我们使用tomcat-->
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<uriEncoding>UTF-8</uriEncoding><!--访问路径编解码字符集-->
</configuration>
<version>2.2</version>
</plugin>
</plugins>
在正式使用之前还需要对mvc进行初始化
我们先来了解一个类
AbstractDispatcherServletInitializer类
-
AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类
-
AbstractDispatcherServletInitializer提供三个接口方法供用户实现
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
//createServletApplicationContext()方法,创建Servlet容器时,加载SpringMVC对应的bean并放入WebApplicationContext对象范围中,而WebApplicationContext的作用范围为ServletContext范围,即整个web容器范围。
//加载springmvc配置类,产生springmvc容器(本质还是spring容器)
protected WebApplicationContext createServletApplicationContext() { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
//getServletMappings()方法,设定SpringMVC对应的请求映射路径,设置为/表示拦截所有请求,任意请求都将转入到SpringMVC进行处理。
设置由springmvc控制器处理的请求映射路径
protected String[] getServletMappings() {
return new String[]{"/"};
}
//createRootApplicationContext()方法,如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,使用方式同createServletApplicationContext()
加载spring配置类
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}
好了,接下来可以进行快速入门了
/**
* @author 王磊
* @date 2022/5/1
* mvc配置类
*/
@Configuration
@ComponentScan("com.xxx.controller")
@EnableWebMvc
public class SpringMvcConfig {}
/**
* @author 王磊
* @date 2022/5/1
controller层
*/
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("user save ...");
return "{'hello':'world'}";
}
}
浏览器效果:
@RequestMapping注解
-
名称:@RequestMapping
-
类型:方法注解
-
位置:SpringMVC控制器方法定义上方,类上面
-
作用:设置当前控制器方法请求访问路径
@ResponseBody注解
-
名称:@ResponseBody
-
类型:方法注解
-
位置:SpringMVC控制器方法定义上方
-
作用:设置当前控制器方法响应内容为当前返回值,无需解析
发送普通类型参数【重点】
五种类型参数传递
普通参数类型:
url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数
-
注意:如果同学们传递的参数是中文,你们会发现接收到的参数出现了中文乱码问题,我这里已经解决了,
-
原因:tomcat 8.5版本之后GET请求就不再出现中文乱码问题,但是我们使用的是tomcat7插件,所以会出现GET请求中文乱码问题。
-
解决:get请求:在ServletContainersInitConfig 加入设置一下字符编码
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
-
post请求: 在pom.xml添加tomcat7插件处配置UTF-8字符集,解决GET请求中文乱码问题。
<configuration>
<uriEncoding>UTF-8</uriEncoding><!--访问路径编解码字符集-->
</configuration>
接下来还有一个问题,如果请求参数名与形参名不同时,那又该怎么办呢?我们接下可以给大家介绍一个注解@RequestParam
@RequestMapping("/save")
@ResponseBody
public String save(@RequestParam("username") String name, int age){
System.out.println(name+age);
return "{'hello':'world'}";
}
@RequestParam
-
类型:形参注解
-
位置:SpringMVC控制器方法形参定义前面
-
作用:绑定请求参数与处理器方法形参间的关系
-
参数:
-
required:是否为必传参数
-
defaultValue:参数默认值
-
POJO类型参数【重点】
POJO参数:请求参数名与形参对象属性名相同,定义POJO类型形参即可接收参数
/**
* @author 王磊
* @date 2022/5/2
*/
public class User {
private String name;
private int age;
}
@RequestMapping("/save")
@ResponseBody
public String save(User user){
System.out.println(user);
return "{'hello':'world'}";
}
注意事项:请求参数key的名称要和POJO中属性的名称一致,否则无法封装
嵌套POJO类型参数
public class User {
private String name;
private int age;
private Address address;
}
public class Address {
private String province;
private String city;
private Address address;
}
嵌套POJO参数:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
//嵌套POJO参数:嵌套属性按照层次结构设定名称即可完成参数传递
@RequestMapping("/pojoContainPojoParam")
@ResponseBody
public String pojoContainPojoParam(User user){
System.out.println("pojo嵌套pojo参数传递 user ==> "+user);
return "{'module':'pojo contain pojo param'}";
}
注意事项:请求参数key的名称要和POJO中属性的名称一致,否则无法封装。
数组类型参数
数组参数:请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型即可接收参数
//数组参数:同名请求参数可以直接映射到对应名称的形参数组对象中
@RequestMapping("/arrayParam")
@ResponseBody
public String arrayParam(String[] likes){
System.out.println("数组参数传递 likes ==> "+ Arrays.toString(likes));
return "{'module':'array param'}";
}
集合类型参数
集合保存普通参数:请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系
//集合参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据
@RequestMapping("/listParam")
@ResponseBody
public String listParam(@RequestParam List<String> likes){
System.out.println("集合参数传递 likes ==> "+ likes);
return "{'module':'list param'}";
}
json数据参数传递
1:添加json数据转换相关坐标
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
2:设置发送json数据(请求body中添加json数据)
开启自动转换json数据的支持
@Configuration
@ComponentScan("com.itheima.controller")
//开启json数据类型自动转换
@EnableWebMvc
public class SpringMvcConfig {
}
注意事项:@EnableWebMvc注解功能强大,该注解整合了多个功能,此处仅使用其中一部分功能,即json数据进行自动类型转换
//集合参数:json格式
//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc
//2.使用@RequestBody注解将外部传递的json数组数据映射到形参的集合对象中作为数据
@RequestMapping("/listParamForJson")
@ResponseBody
public String listParamForJson(@RequestBody List<String> likes){
System.out.println("list common(json)参数传递 list ==> "+likes);
return "{'module':'list common for json param'}";
}
@EnableWebMvc注解介绍
-
名称:@EnableWebMvc
-
类型:==配置类注解==
-
位置:SpringMVC配置类定义上方
-
作用:开启SpringMVC多项辅助功能
@RequestBody注解介绍
-
名称:@RequestBody
-
类型:==形参注解==
-
位置:SpringMVC控制器方法形参定义前面
-
作用:将请求中请求体所包含的数据传递给请求参数,此注解一个处理器方法只能使用一次
传递json对象
POJO参数:json数据与形参对象属性名相同,定义POJO类型形参即可接收参数
//POJO参数:json格式
//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc
//2.使用@RequestBody注解将外部传递的json数据映射到形参的实体类对象中,要求属性名称一一对应
@RequestMapping("/pojoParamForJson")
@ResponseBody
public String pojoParamForJson(@RequestBody User user){
System.out.println("pojo(json)参数传递 user ==> "+user);
return "{'module':'pojo for json param'}";
}
传递json对象数组
-
POJO集合参数:json数组数据与集合泛型属性名相同,定义List类型形参即可接收参数
//集合参数:json格式
//1.开启json数据格式的自动转换,在配置类中开启@EnableWebMvc
//2.使用@RequestBody注解将外部传递的json数组数据映射到形参的保存实体类对象的集合对象中,要求属性名称一一对应
@RequestMapping("/listPojoParamForJson")
@ResponseBody
public String listPojoParamForJson(@RequestBody List<User> list){
System.out.println("list pojo(json)参数传递 list ==> "+list);
return "{'module':'list pojo for json param'}";
}
@RequestBody与@RequestParam区别
-
@RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded】
-
@RequestBody用于接收json数据【application/json】
-
应用后期开发中,发送json格式数据为主,@RequestBody应用较广如果发送非json格式数据,选用@RequestParam接收请求参数
日期类型参数传递【重点】
-
日期类型数据基于系统不同格式也不尽相同
-
2088-08-18
-
2088/08/18
-
08/18/2088
-
接收形参时,根据不同的日期格式设置不同的接收方式
//日期参数 http://localhost:80/dataParam?date=2088/08/08&date1=2088-08-18&date2=2088/08/28 8:08:08
//使用@DateTimeFormat注解设置日期类型数据格式,默认格式yyyy/MM/dd
@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(Date date,
@DateTimeFormat(pattern="yyyy-MM-dd") Date date1,
@DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss") Date date2){
System.out.println("参数传递 date ==> "+date);
System.out.println("参数传递 date1(yyyy-MM-dd) ==> "+date1);
System.out.println("参数传递 date2(yyyy/MM/dd HH:mm:ss) ==> "+date2);
return "{'module':'data param'}";
}
@DateTimeFormat注解介绍
-
名称:@DateTimeFormat
-
类型:==形参注解==
-
位置:SpringMVC控制器方法形参前面
-
作用:设定日期时间型数据格式
-
属性:pattern:指定日期时间格式字符串
3.3 工作原理
-
其内部依赖Converter接口
public interface Converter<S, T> {
@Nullable T convert(S var1);
}
-
请求参数年龄数据(String→Integer)
-
json数据转对象(json → POJO)
-
日期格式转换(String → Date)
传递日期类型参数必须在配置类上使用@EnableWebMvc注解。其功能之一:根据类型匹配对应的类型转换器。