Springmvc传参总结

我们前端向springmvc进行传参的时候,主要是用到了以下三种方法:

  1. 使用表单来提交
  2. ajax使用formdata发送
  3. ajax使用前端对象{..}发送

使用表单

前端使用form表单进行提交,这样是最简单的方法,我们需要注意,如果我们没有设置@RequestParam指定名称的话,我们接收的变量名要和前端发送的key值相同。我们也可以让springmvc自己把我们传入的key,value绑定成已有对象,接下来进行实例:

jsp

1
2
3
4
5
6
7
8
9
10
11
<form action="testDatePojo" method="post">
姓名<input name="username" ><br>
密码<input name="password" ><br>
生日<input name="birthday" ><br>
<input type="radio" name="gender" value="0">man<br>
<input type="radio" name="gender" value="1">woman<br>
<input type="checkbox" name="hobby" value="basketball">篮球<br>
<input type="checkbox" name="hobby" value="football">足球<br>
<input type="checkbox" name="hobby" value="badball">羽毛球<br>
<input type="submit" value="pojosubmit">
</form>

pojo

这里使用了@DateTimeFormat指定了我们日期的转换格式,其实springmvc帮我们定义了一个日期转换器Convertor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.zgy.springmvc.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private String username;
private String password;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
private String gender;
private String[] hobby;

}

controller

1
2
3
4
5
@RequestMapping("/testPojo")
public String testPojo(User user){
System.out.println(user);
return "success";
}

使用FormData

使用FormData的时候,我们需要在后端加入传文件的两个依赖,配置CommonsMultipartResolver这样springmvc才能够正常解析。

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>

jsp

需要注意的是我们前端ajax需要加上以下两个参数,这个和传送文件一样。

1
2
processData: false, // jQuery不要去处理发送的数据
contentType:false,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<%@page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<script src="js/jquery.min.js"></script>
<script>
let form_data = new FormData();
form_data.set("username","123");
form_data.set("password","123");
form_data.set("birthday","2022-12-01");
form_data.set("gender","1");
form_data.set("hobby","123");

let click1 = ()=>{
alert("123");
console.log(form_data);
$.ajax({
type:"post",
processData: false, // jQuery不要去处理发送的数据
contentType:false,
url:"http://localhost:8080/springmvc_param_war_exploded/testPojo",
data:form_data,
// data:form_data,
success(res){
console.log(res);
console.log("123123");
}
});

};
</script>
</head>
<body>
<button onclick="click1()">123</button>
</body>
</html>

controller

我们可以使用对象接收,包装。

1
2
3
4
5
@RequestMapping("/testPojo")
public String testPojo(User user){
System.out.println(user);
return "success";
}

同样我们可以使用@RequestParam来指定接收的参数

1
2
3
4
5
@RequestMapping("/testPojo")
public String testPojo(@RequestParam("username") String user){
System.out.println(user);
return "success";
}

使用对象传输

我们在前端使用ajax传输对象其实就是传输JSON格式的内容,其中我们的contentType应该是application/json,用来指名我们传输的是JSON文件。需要注意的是data里面不能直接传输对象,我们需要JSON.stringfy()将对象转换成JSON字符串格式,因为JSON其实是字符串不是对象。同样因为我们后端接收JSON转换成java对象,同样用到了我们的jackson,需要导入以下jar包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.14.1</version>
</dependency>

jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<%@page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<script src="js/jquery.min.js"></script>
<script>
let click1 = ()=>{
alert("123");
console.log(form_data);
$.ajax({
type:"post",
contentType:"application/json",
dataType : 'json',
url:"http://localhost:8080/springmvc_param_war_exploded/testJson",
data:JSON.stringify({
"username":"张歌"
}),
success(res){
console.log(res);
console.log("123123");
}
});
};
</script>
</head>
<body>
<button onclick="click1()">123</button>
</body>
</html>

controller

我们需要使用@RequestBody注解,将我们传过来的JSON数据转换成我们的java对象,这个原理和@ResponseBody一样。

1
2
3
4
5
6
@ResponseBody
@RequestMapping("/testJson")
public String testPojo1(@RequestBody Map<String, String> requestBody){
System.out.println(requestBody);
return "success";
}

我们同样可以转换成对象

1
2
3
4
5
6
@ResponseBody
@RequestMapping("/testJson")
public String testPojo1(@RequestBody User requestBody){
System.out.println(requestBody);
return "success";
}

总结

contentType 常见的格式

  1. text/plain :纯文本格式
  2. application/json: JSON数据格式
  3. application/x-www-form-urlencoded中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)使用的是url 编码格式。
  4. multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

form 非编码格式 - Multipart From (文件流的格式)

contentType:false的原因

由于 涉及文件上传,表单的 提交必须采取非编码格式 即,’content-type’:multipart/form-data;boundary=${boundary}${boundary} 为一分割字符串。但是,重点来了ajax 只要主动设置 content-typemultipart/form-data,不加后面的boundary,会自动加到传输的格式中,导致后端取不到值。如果加了boundary,又导致直接formData都取不到值。最终解决方案就是,content-type不进行设置,只将data改为 formData格式。浏览器会自动识别,自动设置为content-type:multipart/form-data;boundary=随机值 的形式。最终上传成功。

processData: false的原因

默认情况下,processData 的值是 true,其代表以对象的形式上传的数据都会被转换为字符串的形式上传。而当上传文件的时候,则不需要把其转换为字符串,因此要改成false,如果要用 ajax 上传文件,则需要使用 FormData 对象来作为数据,而不能使用 formserialize 方法(原因是 serialize 方法得到的数据是一个字符串,其不支持二进制数据传输,因此无法上传文件)