SpringMVC
SpringMVC简介
MVC
MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发。
Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
View(视图) - 视图代表模型包含的数据的可视化。
Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。
SpringMVC概述
- SpringMVC是一种基于Java实现MVC模型的轻量级Web框架
- 优点
使用简单,开发便捷(相当于Servlet)
入门案例
@Controller
-
名称:@Controller
-
类型:类注解
-
位置:SpringMVC控制器类定义上方
-
作用:设定SpringMVC的核心控制器bean
-
范例:
@Controller public class UserController{ }
-
相关属性
value(默认):请求访问路径
@ResponseBody
@ResponseBody的作用其实是将java对象转为json格式的数据。
- 名称:@ResponseBody
- 类型:方法注解
- 位置:SpringMVC控制器方法定义上方
- 作用:设置当前控制器方法响应内容为当前返回值,无需解析
- 范例:
@ResquestMappering("/save")
@ResponseBody
public String save(){
System.out.println("user save...");
return "{'info':'springmvc'}";
}
SpringMVC入门课程开发总结(1 + N)
- 一次性工作
创建工程,设置服务器,加载工程
导入坐标
创建web容器启动类,加载SpringMVC配置,并设置SpringMVC请求拦截路径
SpringMVC核心配置类(设置配置类,扫描controller包,加载Controller控制器bean)
- 多次工作
定义处理器请求的控制器类
定义处理请求的控制方法,并配置映射路径(@RequestMapping)与返回json数据(@ResponseBody)
入门案例工作流程分析
- 启动服务器初始化过程
-
服务器启动,执行ServletContainersInitConfig类,初始化Web容器
-
执行createServletApplicationContext方法,创建了WebApplicationContext对象
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMVCConfig.class);
return ctx;
}
- 加载SpringMVCConfig
package com.test.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.test.controller")
public class SpringMVCConfig {
}
- 执行@ComponentScan加载对应的bean
- 加载UserController,每个@RequestMapping的名称对应一个具体的方法
package com.test.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
//1.导包
//2.定义controller
//2.1使用@Controller定义bean
@Controller
public class UserController {
//2.2设置当前操作的访问路径
@RequestMapping("/save")
//2.3设置当前操作的返回值类型
@ResponseBody
public String save(){
System.out.println("user save...");
return "{'module':'springmvc'}";
}
}
- 执行getServletMappings方法,定义所有的请求都通过SpringMVC
bean加载控制
Controller加载控制与业务bean加载控制
- SpringMVC相关bean(表现层bean)
- Spring控制的bean
业务bean(Service)
功能bean(DataSource等)
- SpringMVC相关bean加载控制
SpringMVC加载的bean对应的包均在com.test.controller包内
- Spring 相关bean加载控制
方式一:Spring加载的bean设定扫描范围为精准范围为com.test,例如:service包,dao包等。
方式二:Spring加载的bean设定是扫描范围为com.test,排除掉controller包内的bean
方式三:不区分Spring与SpringMVC的环境,加载到同一个环境中
- 名称:@ComponentScan
- 类型:类注解
- 范例:
@Configuration
@ComponentScan(value = "com.test",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
class = Controller.class
)
)
public class SpringConfig {
}
- 属性
excludeFilters :排除扫描路径中加载的bean,需要指定类别(type)与具体项(classes)
includeFilters :加载指定的bean,需要指定类别(type)与具体项(classes)
//方式一:Spring加载的bean设定扫描范围为精准范围
@ComponentScan({"com.test.dao","com.test.service"})
//方式二:Spring加载的bean设定是扫描范围为com.test,排除掉controller包内的bean
@ComponentScan(value = "com.test",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
))
简化ServletContainersInitConfig的书写
原来:
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
//加载springMVC容器配置
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMVCConfig.class);
return ctx;
}
//设置哪些请求归属springMVC处理
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
//加载spring容器配置
@Override
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringConfig.class);
return ctx;
}
}
AbstractAnnotationConfigDispatcherServletInitializer 为AbstractDispatcherServletInitializer 的子类实现了创建对象
简化:
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMVCConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
SpringMVC设置请求映射路径
- 名称:@RequestMapping
- 类型:方法注解 类注解
- 位置:SpringMVC控制器方法定义上方
- 作用:设置当前控制器方法请求访问路径,如果设置在类上统一设置当前控制器方法请求访问路径前缀
package com.test.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save() {
System.out.println("user save...");
return "{'module' : 'user save'}";
}
@RequestMapping("/delete")
@ResponseBody
public String delete() {
System.out.println("user delete...");
return "{'module' : 'user delete'}";
}
}
- 属性
value(默认):请求访问路径,或者访问路径前缀
请求与响应
请求方式
- Get请求
普通参数:url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数
当然正常开发过程中不会出现中文参数在url链接中(这里只是一个测试)
接收参数只需在方法后添加形参即可
@RequestMapping("/save")
@ResponseBody
public String save(String name, int age, String addr) {
System.out.println("user save name : " + name + "\tage : " + age + "\taddr : " + addr);
return "{'module' : 'user save'}";
}
- Post请求
普通参数:form表单请求传参,表单参数名与形参变量名相同,定义形参即可接收参数
跟我们之前在Java web中玩的时候一样都会出现中文乱码的问题 , 添加一个过滤器将编码转为UTF-8即可,只需要到ServletContainersInitConfig配置中添加一句,SpringMVC已经内部写好了一个过滤器对象,我们只需调用就行,代码具体如下:
//乱码处理
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};//{filter,filter1,filter2}
}
五种类型参数传递
- 名称:@RequestParam
- 类型:形参注解
- 位置:SpringMVC控制器方法形参定义前面
- 作用:绑定请求参数与处理器方法形参间的关系(只能获取参数于请求中,如果存在于请求体中则无法使用@RequestParam)
- 范例:
//请求参数名与形参名不同
@RequestMapping("/save1")
@ResponseBody
public String save1(@RequestParam("name") String userName, int age, String addr) {
System.out.println("user save name : " + userName + "\tage : " + age + "\taddr : " + addr);
return "{'module' : 'user save'}";
}
- 参数
required:是否为必传参数
defaultValue:参数默认值
基本数据类型
包括使用@RequestParam注解的参数
参数是通过参数名进行匹配的,所以绑定也有点类似于取别名
@RequestMapping("/save")
@ResponseBody
public String save(String name, int age, String addr) {
System.out.println("user save name : " + name + "\tage : " + age + "\taddr : " + addr);
return "{'module' : 'user save'}";
}
//请求参数名与形参名不同
@RequestMapping("/save1")
@ResponseBody
public String save1(@RequestParam("name") String userName, int age, String addr) {
System.out.println("user save name : " + userName + "\tage : " + age + "\taddr : " + addr);
return "{'module' : 'user save'}";
}
POJO参数
POJO参数:请求参数名与形参对象属性名相同,定义POJO类型形参即可接收参数
//POJO类型的参数
//User{name='zxy', age=15}
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
System.out.println(user);
return "{'module' : 'user pojoParam'}";
}
如果参数名称与引用类对象属性不一致,不会出现错误但是会存入null
嵌套POJO参数(参数中嵌套了另一个POJO类对象)
嵌套POJO参数:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
//POJO类型(包含引用类型)的参数
//User{name='zxy', age=15, address=Address{city='广东', country='中国'}}
@RequestMapping("/pojoConParam")
@ResponseBody
public String pojoConParam(User user){
System.out.println(user);
return "{'module' : 'user pojoConParam'}";
}
数组参数
数组参数:请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型形参即可接收参数
//数组参数
//[乒乓球, 羽毛球, 篮球]
@RequestMapping("/arrayParam")
@ResponseBody
public String pojoConParam(String[] likes){
System.out.println(Arrays.toString(likes));
return "{'module' : 'user arrayParam'}";
}
集合保存普通参数
集合保存普通参数:请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系
//集合类型
//[乒乓球, 羽毛球, 篮球]
@RequestMapping("/listParam")
@ResponseBody
public String listParam(@RequestParam List<String> likes){
System.out.println(likes);
return "{'module' : 'user arrayParam'}";
}
JSON数据传递参数
使用Json写入List
- 导包:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency
- 核心配置中写入
@EnableWebMvc
package com.test.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan("com.test.controller")
//将数据由json转换为我们需要的数据类型
@EnableWebMvc
public class SpringMVCConfig {
}
- 在Psotman中写Json的格式
- 参数前写入
@RequestBody
(因为Json数据存在于请求体中,非请求中,所以无法使用@RequestParam)
//集合参数:json模式
//[game, music, travel]
@RequestMapping("/listParamForJson")
@ResponseBody
public String listParamForJson(@RequestBody List<String> likes){
System.out.println(likes);
return "{'module' : 'user listParamForJson'}";
}
使用Json写入POJO
- 在Psotman中写Json的格式
- 参数前写入
@RequestBody
//POJO参数:json模式
//User{name='lvjian', age=15, address=Address{city='广东', country='中国'}}
@RequestMapping("/pojoParamForJson")
@ResponseBody
public String pojoParamForJson(@RequestBody User user){
System.out.println(user);
return "{'module' : 'user pojoParamForJson'}";
}
使用Json写入List<POJO>
- 在Psotman中写Json的格式
[
{
"name": "lvjian",
"age" : 15,
"address":{
"city":"广东",
"country":"中国"
}
},
{
"name": "chunmu",
"age" : 16,
"address":{
"city":"广东",
"country":"中国"
}
}
]
- 参数前写入
@RequestBody
//集合参数:json格式
@RequestMapping("/listPojoParamForJson")
@ResponseBody
public String listPojoParamForJson(@RequestBody List<User> list){
System.out.println(list);
return "{'module' : 'user listPojoParamForJson'}";
}
注意:@EnableWebMvc注解功能强大,该注解整合了多个功能,此处仅使用其中一部分功能,即json数据进行自动类型转换
@EnableWebMvc
- 名称:@EnableWebMvc
- 类型:配置类注解
- 位置:SpringMVC配置类定义上方
- 作用:开启SpringMVC多项辅助功能
- 范例
package com.test.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan("com.test.controller")
//将数据由json转换为我们需要的数据类型
@EnableWebMvc
public class SpringMVCConfig {
}
@RequestBody
- 名称:@RequestBody
- 类型:形参注解
- 位置:SpringMVC控制器方法形参定义里面
- 作用:将请求中请求体所包含的数据传递给请求参数,此注解一个处理器方法只能使用一次
- 范例:
//集合参数:json格式
@RequestMapping("/listPojoParamForJson")
@ResponseBody
public String listPojoParamForJson(@RequestBody List<User> list){
System.out.println(list);
return "{'module' : 'user listPojoParamForJson'}";
}
@RequestBody与@RequestParam区别
- 区别 :
@RequestParam用于接收url地址传参,表单传承【application/x-www-form-urlencoded】
@RequestBody用于接收json数据【application/json】
- 应用:
后期开发中,发送json数据为主,@RequestBody应用较广
如果发送非json格式数据,选用@RequestParam接收请求参数
日期类型参数传递
接收参数是,根据不同的日期格式设置不同的接收方式
//日期类型
@RequestMapping("/dateParam")
@ResponseBody
public String dateParam(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' : 'user dateParam'}";
}
http://localhost:8080/springmvc_02_request_mapping/user/dateParam?date=2088/08/08&date1=2088-08-08&date2=2088/08/28 8:28:28
@DataTimeFormat
- 名称:@DataTimeFormat
- 类型:形参注解
- 位置:SpringMVC控制器方法形参前面
- 作用:设定日期时间型数据格式
- 范例:
//日期类型
@RequestMapping("/dateParam")
@ResponseBody
public String dateParam(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' : 'user dateParam'}";
}
-
属性:pattern:日期时间格式字符串
其中包含了Converter接口,可以使日期格式转换(String—>Date)
-
@EnableWebMvc功能之一:根据类型匹配对应的类型转换器
@ResponseBody
通过继承了HttpMessageConverter(类型转换器)接口
- 名称L:@ResponseBody
- 类型:方法注解
- 位置SpringMVC控制器方法定义上方
- 作用:设置当前控制器返回值作为响应体
- 范例:
//响应纯文本页面
@RequestMapping("/toText")
@ResponseBody
public String toText (){
System.out.println("返回纯文本数据");
return "respose text";
}
REST风格
- REST,表现形式状态转换
- 优点:
隐藏资源的访问行为,无法通过地址得知对资源是何种操作
书写简化
REST风格简介
- 按照REST风格访问资源时使用行为动作区分区分对资源进行了何种操作
- 根据REST风格对资源进行访问称为RESTful
注意事项:
上述行为时约定方式,约定不是规范,可以打破,所以称REST风格,和不是 REST规范
描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如:users、books、accounts……
代码:
@Controller
public class UserController {
@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String save() {
System.out.println("user save");
return "{'module' : 'user save'}";
}
@RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id) { //@PathVariable路径变量
System.out.println("user delete...");
return "{'module' : 'user delete'}";
}
@RequestMapping(value = "/users", method = RequestMethod.PUT)
@ResponseBody
public String update(@RequestBody User user) {
System.out.println("user update..." + user);
return "{'module' : 'user update'}";
}
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
@ResponseBody
public String getById(@PathVariable Integer id){
System.out.println("user getById..." + id);
return "{'module' : 'user getById'}";
}
@RequestMapping(value = "/users", method = RequestMethod.GET)
@ResponseBody
public String getAll() {
System.out.println("user getAll...");
return "{'module' : 'user getAll'}";
}
}
@RequestMapping
- 名称:@RequestMapping
- 类型:方法注解
- 位置:SpringMVC控制器方法定义上方
- 作用:设置当前控制器方法请求访问路径
- 范例:
@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String save() {
System.out.println("user save");
return "{'module' : 'user save'}";
}
- 属性
value : 请求访问路径
method:http请求动作,标准动作(GET / POST / PUT / DELETE)
@PathVariable
- 名称:@PathVariable
- 类型:形参注解
- 位置:SpringMVC控制器方法形参定义前面
- 作用:绑定路径参数与处理器方法形参的关系,要求路径参数名与形参名一一对应
- 范例:
@RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id) { //@PathVariable路径变量
System.out.println("user delete...");
return "{'module' : 'user delete'}";
}
@RequestBody、@RequestParam、@PathVarible
- 区别 :
@RequestParam用于接收url地址传参,表单传承【application/x-www-form-urlencoded】
@RequestBody用于接收json数据【application/json】
@PathVaribale用于接收路径参数,使用(参数名称)描述路劲参数
- 应用:
后期开发中,发送json数据为主,@RequestBody应用较广
如果发送非json格式数据,选用@RequestParam接收请求参数
采用RESTful进行开发,当参数数量较少时,例如1个,可以采用@PathVariable接收请求路径变量,通常用于传递id值
@RestController
- 名称:@RestController
- 类型:类注解
- 位置:基于SpringMVC的RESTful开发控制器类定义上方
- 作用设置当前控制器为RESTful风格,等同于@Controller与@ResponseBody两个注解组合功能
- 范例:
@RestController
@RequestMapping("/users")
public class UserController {
}
@GetMapping @PostMapping @PutMapping @DeleteMapping
- 名称:@GetMapping @PostMapping @PutMapping @DeleteMapping
- 类型:方法注解
- 位置:基于SpringMVC的RESTful开发控制器方法定义上方
- 作用:设置当前控制器方法请求访问路径与请求动作
- 范例:
@PostMapping
public String save() {
System.out.println("user save");
return "{'module' : 'user save'}";
}
@DeleteMapping("/{id}")
public String delete(@PathVariable Integer id) { //@PathVariable路径变量
System.out.println("user delete...");
return "{'module' : 'user delete'}";
}
@PutMapping
public String update(@RequestBody User user) {
System.out.println("user update..." + user);
return "{'module' : 'user update'}";
}
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println("user getById..." + id);
return "{'module' : 'user getById'}";
}
@GetMapping
public String getAll() {
System.out.println("user getAll...");
return "{'module' : 'user getAll'}";
}
- 属性
value(默认):请求访问路径
使用addResourceHandlers进行放行,由于
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
对文件起到拦截的作用所以无法访问页面文件
package com.test.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
//放行,当访问/pages/????时候,走/pages目录下的数据
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
}
}