请求与参数处理
1、请求路径
1.1 环境准备
-
入门案例基础上编写BookController和UserController
@Controller public class UserController { @RequestMapping("/save") @ResponseBody public String save(){ System.out.println("user save ..."); return "{'module':'user save'}"; } @RequestMapping("/delete") @ResponseBody public String save(){ System.out.println("user delete ..."); return "{'module':'user delete'}"; } } @Controller public class BookController { @RequestMapping("/save") @ResponseBody public String save(){ System.out.println("book save ..."); return "{'module':'book save'}"; } }
最终创建好的项目结构如下:
把环境准备好后,启动Tomcat服务器,后台会报错:
从错误信息可以看出:
- UserController有一个save方法,访问路径为
http://localhost/save
- BookController也有一个save方法,访问路径为
http://localhost/save
- 当访问
http://localhost/saved
的时候,到底是访问UserController还是BookController?
3.1.2 问题分析
团队多人开发,每人设置不同的请求路径,冲突问题该如何解决?
解决思路:为不同模块设置模块名作为请求路径前置
对于Book模块的save,将其访问路径设置http://localhost/book/save
对于User模块的save,将其访问路径设置http://localhost/user/save
这样在同一个模块中出现命名冲突的情况就比较少了。
3.1.3 解决方式
- 解决方案
@Controller
public class UserController {
@RequestMapping("/user/save")
@ResponseBody
public String save(){
System.out.println("user save ...");
return "{'module':'user save'}";
}
@RequestMapping("/user/delete")
@ResponseBody
public String save(){
System.out.println("user delete ...");
return "{'module':'user delete'}";
}
}
@Controller
public class BookController {
@RequestMapping("/book/save")
@ResponseBody
public String save(){
System.out.println("book save ...");
return "{'module':'book save'}";
}
}
问题是解决了,但是每个方法前面都需要进行修改,写起来比较麻烦而且还有很多重复代码,如果/user后期发生变化,所有的方法都需要改,耦合度太高。
- 优化方式
@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'}";
}
}
@Controller
@RequestMapping("/book")
public class BookController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("book save ...");
return "{'module':'book save'}";
}
}
注意:
- 当类上和方法上都添加了
@RequestMapping
注解,前端发送请求的时候,要和两个注解的value值相加匹配才能访问到。 - @RequestMapping注解value属性前面加不加
/
都可以
3.2、请求方式
关于请求参数的传递与接收是和请求方式有关系的,目前比较常见的两种请求方式为:
- GET
- POST
针对于不同的请求前端如何发送,后端如何接收?
3.2.1 环境准备
- 创建处理器方法
@Controller
public class UserController {
@RequestMapping("/user/save")
@ResponseBody
public String save(){
System.out.println("user save ...");
return "{'module':'user save'}";
}
}
- 使用PostMan进行GET调用与POST调用
GET请求与POST请求都能正常访问
3.2.2 技术分析
@RequestMapping没有设置请求方式,默认支持以下八种请求类型:
指定请求方式后将不再支持其他类型请求类型:
3.3、参数
3.3.1、基本数据类型
-
发送方式
-
URL地址传参
-
表单传参
-
-
接收方式
-
形参与参数名相同
此时可以直接获取请求参数:
-
形参与参数名不同
需要设置 @RequestParam 绑定请求参数与方法形参:
-
- 知识点:@RequestParam
名称 | @RequestParam |
---|---|
类型 | 形参注解 |
位置 | SpringMVC控制器方法形参定义前面 |
作用 | 绑定请求参数与处理器方法形参间的关系 |
相关参数 | required:是否为必传参数 defaultValue:参数默认值 |
3.3.2、POJO
简单数据类型一般处理的是参数个数比较少的请求,如果参数比较多,那么后台接收参数的时候就比较复杂,这个时候我们可以考虑使用POJO数据类型。
- POJO参数:请求参数名与形参对象属性名相同,定义POJO类型形参即可接收参数
- 新增POJO类
public class User {
private String name;
private Integer age;
//setter...getter...略
}
-
URL地址请求或表单请求
-
后台接收参数
//POJO参数:请求参数与形参对象中的属性对应即可完成参数传递
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
System.out.println("pojo参数传递 user ==> "+user);
return "{'module':'pojo param'}";
}
注意:
- POJO参数接收,前端GET和POST发送请求数据的方式不变。
- 请求参数key的名称要和POJO中属性的名称一致,否则无法封装。
3.3.3、嵌套POJO
1、新增POJO类
public class User {
private String name;
private Integer age;
private Address address;
//setter...getter...略
}
public class Address {
private String province;
private String city;
//setter...getter...略
}
2、URL地址请求或表单请求
请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
发送请求和参数:
3、后台接收参数
//POJO参数:请求参数与形参对象中的属性对应即可完成参数传递
@RequestMapping("/pojoParam")
@ResponseBody
public String pojoParam(User user){
System.out.println("pojo参数传递 user ==> "+user);
return "{'module':'pojo param'}";
}
注意:
请求参数key的名称要和POJO中属性的名称一致,否则无法封装
3.3.4、数组
请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型即可接收参数
1、URL地址请求或表单请求
2、后台接收参数
//数组参数:同名请求参数可以直接映射到对应名称的形参数组对象中
@RequestMapping("/arrayParam")
@ResponseBody
public String arrayParam(String[] likes){
System.out.println("数组参数传递 likes ==> "+ Arrays.toString(likes));
return "{'module':'array param'}";
}
3.3.5、集合(List、Map)
1、List
数组能接收多个值,那么集合是否也可以实现这个功能呢?
-
发送请求和参数:
-
错误接收方式
//集合参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据
@RequestMapping("/listParam")
@ResponseBody
public String listParam(List<String> likes){
System.out.println("集合参数传递 likes ==> "+ likes);
return "{'module':'list param'}";
}
-
运行报错
-
错误原因:
SpringMVC将List看做是一个POJO对象来处理,将其创建一个对象并准备把前端的数据封装到对象中,但是List是一个接口无法创建对象,所以报错。
- 正确接收方式
使用@RequestParam
注解
//集合参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据
@RequestMapping("/listParam")
@ResponseBody
public String listParam(@RequestParam List<String> likes){
System.out.println("集合参数传递 likes ==> "+ likes);
return "{'module':'list param'}";
}
- 集合保存普通参数:请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系
- 对于简单数据类型使用数组会比集合更简单些。
2.Map
- 发送请求和参数:
请求参数需要设置map的key值
- 接收方式
同List接收方式,需要使用@RequestParam
注解
@RequestMapping("/mapParam")
@ResponseBody
public String mapParam(@RequestParam Map<String,String> maps) {
System.out.println(maps);
return "{'module':'mapParam'}";
}
3.5.6、Date日期类型
1、URL地址请求或表单请求
2、后台接收参数
@RequestMapping("/dateParam")
@ResponseBody
public String dateParam(Date date,@DateTimeFormat(pattern = "yyyy-MM-dd") Date date2,@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date date3){
System.out.println("date:"+date);
System.out.println("date2:"+date2);
System.out.println("date3:"+date3);
return "{'module':'dateParam'}";
}
注意:
- SpringMvc默认时间格式为 yyyy/MM/dd
- 其他时间格式需要使用@DateTimeFormat转换
- 知识点1:@DateTimeFormat
名称 | @DateTimeFormat |
---|---|
类型 | 形参注解 |
位置 | SpringMVC控制器方法形参前面 |
作用 | 设定日期时间型数据格式 |
相关属性 | pattern:指定日期时间格式字符串 |
3.5.7、File文件类型
1、前期准备
- 添加fileupload依赖
<!--添加fileupload依赖-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
- 配置解析器
SpringMvcConfig 中配置 multipartResolver解析器,这里Bean的名称是固定的,否则无法生效
@Bean("multipartResolver")
public CommonsMultipartResolver multipartResolver (){
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setDefaultEncoding("UTF-8");
resolver.setMaxUploadSize(1024*1024);
return resolver;
}
2、POST请求方式
post请求选择 form-data 方式传递文件类型参数
3、后台接收参数
使用 MultipartFile 类型接收文件参数
@RequestMapping("/fileParam")
@ResponseBody
public String fileParam(MultipartFile file){
if(!file.isEmpty()){
try {
file.transferTo(new File("D://test.txt"));
} catch (IOException e) {
e.printStackTrace();
}
}
return "{'module':'file'}";
}
3.5.7、JSON类型
现在比较流行的开发方式为异步调用。前后台以异步方式进行交换,传输的数据使用的是JSON,所以前端如果发送的是JSON数据,后端该如何接收?
1、前期准备
- SpringMVC默认使用的是jackson来处理json的转换,所以需要在pom.xml添加jackson依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
- 开启SpringMVC注解支持
在SpringMVC的配置类中开启SpringMVC的注解支持,这里面就包含了将JSON转换成对象的功能。
@Configuration
@ComponentScan("com.itheima.controller")
//开启json数据类型自动转换
@EnableWebMvc
public class SpringMvcConfig {
}
2、json请求与接收
注意: 接收json数据,需要在形参变量前加 @RequestBody注解
- JSON对象数据
-
前端请求
-
后端接收
@RequestMapping("/pojoParamForJson")
@ResponseBody
public String pojoParamForJson(@RequestBody User user) {
System.out.println(user);
return "{'module':'pojoParamForJson'}";
}
- JSON普通数组
-
前端请求
-
后端接收
@RequestMapping("/arrayParamForJson")
@ResponseBody
public String arrayParamForJson(@RequestBody String[] likes){
System.out.println(Arrays.toString(likes));
return "{'module':'arrayParamForJson'}";
}
- JSON对象数据
-
前端请求
-
后台接收参数
@RequestMapping("/arrayPojoParamForJson")
@ResponseBody
public String arrayPojoParamForJson(@RequestBody List<User> list){
System.out.println(list);
return "{'module':'arrayPojoParamForJson'}";
}
3.5.8、中文乱码处理
1、GET请求
-
URL地址传参中文
-
响应结果中文乱码:
-
解决方式
修改pom.xml来解决GET请求中文乱码问题
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port><!--tomcat端口号-->
<path>/</path> <!--虚拟目录-->
<uriEncoding>UTF-8</uriEncoding><!--访问路径编解码字符集-->
</configuration>
</plugin>
</plugins>
</build>
2、POST请求
-
POST表单传参
-
中文乱码
-
解决方式
配置过滤器
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
//乱码处理
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
}
CharacterEncodingFilter是在spring-web包中,所以用之前需要导入对应的jar包。