一、@RequestParam
package org.springframework.web.bind.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
boolean required() default true;
String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}
前端代码:
<form action="student/addStudent" method="post">
<p>学生姓名:<input type="text" name="username"></p>
<p>学生密码:<input type="password" name="password"></p>
<p>学生年龄:<input type="text" name="age"></p>
<p>学生地址:<input type="text" name="address"></p>
<p><input type="submit" value="表单提交数据"></p>
</form>
<a href="student/addStudent?username=张三&password=123456&age=28&address=江苏南京">超链接提交数据</a>
后端代码:
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
// 声明此控制器的请求路径。由于路径类型是String数组,所以可设置多个路径({"..", "..", ..})。
@RequestMapping("/student")
public class StudentController {
// 如果控制器参数名与前端传递过来的数据的key名称一致,那么@RequestParam注解可省略。此时控制器参数效果与@RequestParam(value = "key", required = false)一致。
@RequestMapping("/addStudent")
public void addStudent(@RequestParam(value = "username", required = false) String username,
@RequestParam(value = "password", required = false) String password,
@RequestParam(value = "age", required = false, defaultValue = "0") Integer age,
@RequestParam(value = "address", required = false) String address) {
System.out.println(username+", "+password+", "+age+", "+address);
}
}
运行测试:
required = true (默认):表单提交未赋值时,它也传递了数据给服务器(传递"" 字符串),因此String 类型参数不会报错。但是int 和Integer 类型会报错,因为"" 无法转换为int 和integer 类型(解决方法:设置required = false 【此时age 为Integer 类型时值为null ,为int 类型时依旧报错,因为null 无法赋值给int 类型】或者设置默认值defaultValue = "0" )。 |
required = false :表单提交没有赋值的默认传值"" (不是null )。上述代码中参数age 为int 类型,如果没有默认值且表单提交未赋值,那么程序报错,因为"" 字符串无法强转为int 类型(解决方法:将age 类型由int 改为Integer ,此时给age 赋值"" 时,虽然Integer 类型不能接收"" 类型的值,但是它可被null 赋值,所以此时age 结果为null )。 |
required = true (默认):使用GET提交时所有参数都要加上,否则报错。因为不加参数的话就不会传值给服务端(与表单提交不一样)。 |
required = false :URL后加键值对提交数据(GET提交数据)时没有写的参数默认值为null 。上述代码中参数age 为int 类型,如果没有默认值且GET提交未写参数,那么程序报错,因为null 无法赋值给int 类型参数(解决方法:将age 类型由int 改为Integer ,此时给age 赋值时,结果为null )。 |
注意1:在Spring MVC中,接收参数时操作的都是对象,这也是为什么设置了required = false
后,如果控制器没有收到参数,其值为null
的原因。因此在开发中控制器接收参数时,尽量使用对象类型(Integer
等)。
注意2:控制器使用@RequestParam
注解接收数据时可接收请求行和编码格式为application/x-www-form-urlencoded
的请求体数据,不能接收请求头中的数据。
二、@RequestHeader
package org.springframework.web.bind.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestHeader {
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
boolean required() default true;
String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}
// 变量与@RequestParam一致,用法也是一样的。
前端代码:
<input type="button" value="AJAX提交数据" id="btn1">
<script type="text/javascript" src="static/js/jquery-3.7.1.min.js"></script>
<script type="text/javascript">
$("#btn1").click(function () {
$.ajax({
<!--在url中使用?key=value传值,此为请求行传值-->
url:"student/addStudent",
type:"post",
<!--此为请求头传值,注意:请求头中值不能有中文,否则执行无反应-->
headers:{
username:"lisi",
password:"123456",
age:25,
address:"China"
},
<!--回调方法-->
success:function (res) {
console.log(res);
}
});
});
</script>
后端代码:
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
// 声明此控制器的请求路径。由于路径类型是String数组,所以可设置多个路径({"..", "..", ..})。
@RequestMapping("/student")
public class StudentController {
// 与@RequestParam不同的是,即使控制器参数名与前端传递过来的数据的key名称一致,@RequestHeader注解也不可省略。
@RequestMapping("/addStudent")
public void addStudent(@RequestHeader("username") String username,
@RequestHeader("password") String password,
@RequestHeader("age") Integer age,
@RequestHeader("address") String address) {
System.out.println(username+", "+password+", "+age+", "+address);
}
}
注意:控制器接收请求头中的数据只能使用@RequestHeader
注解。
三、@RequestBody
package org.springframework.web.bind.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
boolean required() default true;
}
前端代码:
<input type="button" value="AJAX提交数据" id="btn1">
<script type="text/javascript" src="static/js/jquery-3.7.1.min.js"></script>
<script type="text/javascript">
$("#btn1").click(function () {
let obj = {};
obj.username="张三";
obj.password="123456";
obj.age=24;
obj.address="江西省南昌市";
$.ajax({
<!--在url中使用?key=value传值,此为请求行传值-->
url:"student/addStudent",
type:"post",
<!--此为请求体传值,一般用来传递一个对象结构,此时需要声明传递的数据类型。如下所示-->
<!--
1、
data: obj,
2、
data:JSON.stringify(obj),
3、
contentType:"application/json",
data:obj,
4、
contentType:"application/json",
data:JSON.stringify(obj),
-->
<!--回调方法-->
success:function (res) {
console.log(res);
}
});
});
</script>
后端代码接收数据的对象:
package model;
import lombok.*;
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public class Student {
private String username;
private String password;
private Integer age;
private String address;
}
后端代码1:
package controller;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.io.IOException;
@Controller
@RequestMapping("/student")
public class StudentController {
// 使用Servlet(需要导入Servlet依赖)读取AJAX发送过来的请求体中的数据。注意前端请求体中发送的数据的编码方式。
@RequestMapping("/addStudent")
public void addStudent(HttpServletRequest request) {
StringBuffer str = new StringBuffer();
try (ServletInputStream inputStream = request.getInputStream();) {
byte[] bytes = new byte[1024];
int len = -1;
while ((len = inputStream.read(bytes)) != -1) {
str.append(new String(bytes, 0, len));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
// 此时需对字符串按照&进行切分,然后判断=左边的key值并将其赋值给Student对象。很麻烦!
System.out.println(str.toString());
}
}
1,2,3,4运行结果依次为:
username=%E5%BC%A0%E4%B8%89&password=123456&age=24&address=%E6%B1%9F%E8%A5%BF%E7%9C%81%E5%8D%97%E6%98%8C%E5%B8%82
23-Sep-2023 11:10:39.549 警告 [http-nio-8080-exec-6] org.springframework.web.servlet.DispatcherServlet.noHandlerFound No mapping for POST /javastudy_war_exploded/student/student/addStudent
{"username":"寮犱笁","password":"123456","age":24,"address":"姹熻タ鐪佸崡鏄屽競"}
23-Sep-2023 11:11:02.509 警告 [http-nio-8080-exec-10] org.springframework.web.servlet.DispatcherServlet.noHandlerFound No mapping for POST /javastudy_war_exploded/student/student/addStudent
username=%E5%BC%A0%E4%B8%89&password=123456&age=24&address=%E6%B1%9F%E8%A5%BF%E7%9C%81%E5%8D%97%E6%98%8C%E5%B8%82
23-Sep-2023 11:11:26.794 警告 [http-nio-8080-exec-2] org.springframework.web.servlet.DispatcherServlet.noHandlerFound No mapping for POST /javastudy_war_exploded/student/student/addStudent
{"username":"寮犱笁","password":"123456","age":24,"address":"姹熻タ鐪佸崡鏄屽競"}
23-Sep-2023 11:11:58.561 警告 [http-nio-8080-exec-9] org.springframework.web.servlet.DispatcherServlet.noHandlerFound No mapping for POST /javastudy_war_exploded/student/student/addStudent
后端代码2:
package controller;
import model.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/student")
public class StudentController {
@RequestMapping("/addStudent")
public void addStudent(@RequestBody Student student) {
System.out.println(student);
}
}
注意:Spring MVC默认采用Jackson解析Json,因此需要导入依赖包。(jackson-databind包含另外两个包,因此只需导入其一个包即可)
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.15.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.15.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
如果不导入包,那么1,2,3,4运行结果依次为:
23-Sep-2023 10:52:05.173 警告 [http-nio-8080-exec-3] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/x-www-form-urlencoded;charset=UTF-8' is not supported]
23-Sep-2023 10:52:34.162 警告 [http-nio-8080-exec-7] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/x-www-form-urlencoded;charset=UTF-8' is not supported]
23-Sep-2023 10:53:22.281 警告 [http-nio-8080-exec-10] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/json;charset=UTF-8' is not supported]
23-Sep-2023 10:53:48.441 警告 [http-nio-8080-exec-4] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/json;charset=UTF-8' is not supported]
导入包后,1,2,3,4运行结果依次为:
23-Sep-2023 10:56:54.217 警告 [http-nio-8080-exec-5] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/x-www-form-urlencoded;charset=UTF-8' is not supported]
23-Sep-2023 10:57:23.723 警告 [http-nio-8080-exec-9] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/x-www-form-urlencoded;charset=UTF-8' is not supported]
23-Sep-2023 10:58:06.777 警告 [http-nio-8080-exec-2] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token 'username': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')]
Student(username=张三, password=123456, age=24, address=江西省南昌市)
23-Sep-2023 10:58:31.156 警告 [http-nio-8080-exec-4] org.springframework.web.servlet.DispatcherServlet.noHandlerFound No mapping for POST /javastudy_war_exploded/student/student/addStudent