理解并使用这个注解——@RequestParam

@RequestParam 说明

RequestParam注解在springmvc的作用是:将请求参数绑定到控制器的方法的参数上

用来处理 Content—Type:application/x-www-form-urlencoded 编码的内容,在http协议中,
不指 定Content-Type 则默认传递的就是 application/x-www-form-urlencoded 类型。

RequestParam 可以接受简单类型的属性,也可以接受对象类型。实质是将 Request.getParameter()
中的Key-Value 参 数Map 利用 Spring 的转化机制 ConversionService 配置,转化成参数接收对象或字段。

在Content-Type:application/x-www-form-urlencoded的请求中,get 方式中 queryString 的值,
和 post 方式中 body data 的值都会被 Servlet 接受到并转化到 Request.getParameter() 参数集中,
所以 @RequestParam 可以获取的到。

tip: application/x-www-form-urlencoded 是最常见的POST提交数据方式,也是原生form默认的提交方式,
支持GET/POST等方法,所有数据变成键值对的形式key1=value1&key2=value2的形式,并且特殊字符需要转义成utf-8编码,如空格会变成 %20

@RequestParam 使用示例

示例代码如下

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

/**
 * @FileName: TestUserController
 * @Author: fjp
 * @Date: 2020/6/16 14:56
 * @Description: 测试一个User对象的RequestParam注解
 * History:
 * <author>          <time>          <version>
 * fjp           2020/6/16           版本号
 */

@RestController
public class TestUserController {
	
    @PostMapping("/user")
	public String testUser(String name, String age) {
		return new User(name, age).toString();
	}
	
	@PostMapping("/user1")
	public String testUser1(@RequestParam("name") String name, @RequestParam("name") String age) {
		return new User(name, age).toString();
	}
	
	@PostMapping("/user2")
	public String testUser2(@RequestParam("name1") String name, @RequestParam("age1") String age) {
		return new User(name, age).toString();
	}
	
	@PostMapping("/user3")
	public String testUser3(User user) {
		return user.toString();
	}
	
	@PostMapping("/user4")
	public String testUser4(@Valid Info info) {
		return info.toString();
	}
	
	@PostMapping("/user5")
	public String testUser5(User user, Info info) {
	    return new UserInfo(user,info).toString();
	}
	
	@PostMapping("/user6")
	public String testUser6(UserInfo userInfo) {
		return userInfo.toString();
	}
	
	@PostMapping("/user7")
	public String testUser7(@RequestParam("userInfo") UserInfo userInfo) {
		return userInfo.toString();
	}
}

class User {
	public User() {
	}

	public User(String name, String age) {
		this.name = name;
		this.age = age;
	}
	
	private String name;
	
	private String age;
	
	@Override
	public String toString() {
		final StringBuilder sb;
		sb = new StringBuilder();
		sb.append('{');
		sb.append("\"name\":\"").append(name).append('\"');
		sb.append(",\"age\":\"").append(age).append('\"');
		sb.append('}');
		return sb.toString();
	}
	
	public String getName() {
		return this.name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getAge() {
		return this.age;
	}
	
	public void setAge(String age) {
		this.age = age;
	}
}

class Info {
	public Info() {
	}
	
	public Info(String profile) {
		this.profile = profile;
	}
	
	@NotBlank
	private String profile;
	
	
	public String getProfile() {
		return profile;
	}
	
	public void setProfile(String profile) {
		this.profile = profile;
	}
	
	@Override
	public String toString() {
		final StringBuilder sb;
		sb = new StringBuilder();
		sb.append('{');
		sb.append("\"profile\":\"").append(profile).append('\"');
		sb.append('}');
		return sb.toString();
	}
}

class UserInfo {
	private User user;
	private Info info;
	
	public UserInfo() {
	}
	
	public UserInfo(User user, Info info) {
		this.user = user;
		this.info = info;
	}
	
	public User getUser() {
		return this.user;
	}
	
	public void setUser(User user) {
		this.user = user;
	}
	
	public Info getInfo() {
		return this.info;
	}
	
	public void setInfo(Info info) {
		this.info = info;
	}
	
	@Override
	public String toString() {
		final StringBuilder sb;
		sb = new StringBuilder();
		sb.append('{');
		sb.append("\"user\":").append(user);
		sb.append(",\"info\":").append(info);
		sb.append('}');
		return sb.toString();
	}
}

class StringToUserInfoConverter implements Converter<String, UserInfo> {
	
	@SneakyThrows
	@Override
	public UserInfo convert(String from) {
		//System.out.println("from = " + from);
		return new ObjectMapper().readValue(from, UserInfo.class);
	}
}

@Configuration
class WebConfig implements WebMvcConfigurer {
	
	@Override
	public void addFormatters(FormatterRegistry registry) {
		registry.addConverter(new StringToUserInfoConverter());
	}
}


@RequestParam 示例调用结果

调用上方各接口的参数及结果如下所示:

0. 接口地址: /user
   请求参数: name  :  test  
              age  :  12
   响应结果: {"name":"test","age":"12"}
   
1. 接口地址: /user1
   请求参数: name  :  test  
              age  :  12
   响应结果: {"name":"test","age":"12"}
   
2. 接口地址: /user2
   请求参数: name1  :  test  
              age1  :  12
   响应结果: {"name":"test","age":"12"}
   
3. 接口地址: /user3
   请求参数: name  :  test  
              age  :  12
   响应结果: {"name":"test","age":"12"}
   
4. 接口地址: /user4
   请求参数: profile  :  info class
   响应结果: {"info":"info class"}
   
5. 接口地址: /user5
   请求参数: name  :  test  
              age  :  12
              profile  :  info class
   响应结果: {"user":{"name":"test","age":"12"},"info":{"profile":"info class"}}
   
6. 接口地址: /user6
   # 若未添加自定义转换类
   请求参数: userInfo  :  {"user":{"name":"test","age":"12"},"info":{"profile":"info class"}}  
   响应结果: {"user":null,"info":null}
   
   # 若添加自定义转换类
   请求参数: userInfo  :  {"user":{"name":"test","age":"12"},"info":{"profile":"info class"}}
   响应结果: {"user":{"name":"test","age":"12"},"info":{"profile":"info class"}}
   
7. 接口地址: /user7
   请求参数: userInfo  :  {"user":{"name":"test","age":"12"},"info":{"profile":"info class"}}
   响应结果: {"user":{"name":"test","age":"12"},"info":{"profile":"info class"}}

@RequestParam 总结
  1. 请求参数名与方法参数形参名不一致时使用 @RequestParam

通过使用 @RequestParam 在控制器中将请求参数绑定到方法参数,而不需要请求参数名与方法形参名完全一致。(如/user1,/user2中请求参数完全不同)

  1. 合并参数为一个简单对象

尽管 @RequestParam 注解能够将请求参数绑定到控制器的方法的参数上,并能通过参数 value 设置请求的参数名称(如/user2),但是在多个参数的情况下,过长的参数列表也会让代码的可读性变得很差。
解决这个这个问题最简单的方式就是,将这组参数合并到一个简单的对象(POJO)中,即如上方代码将参数合并成对象 User(如/user3)。

  1. 合并参数到多个简单对象

并非强制要求把所有的参数全部封装到一个对象中,完全可以按照功能将请求参数分布到多个POJO中(如/user5)。

  1. 设置是否包含参数、默认值

@RequestParam(value=“参数名”,required=“true|false”,defaultValue="")
value : 参数名称
required : 是否包含改参数,默认为true,参数必须在请求中,此时参数不存在则报错
defaultValue : 默认参数值,设置默认值后,required 为 true 自动失效转为 false,若没传参数值,则将使用设置的默认值。

  1. 方便进行参数校验

使用 @RequestParam 注解,可以对绑定的参数进行校验(Java Bean Validation 框架或自定义参数校验),如果参数校验失败,可以将违反定义的约束的行为作为集合返回或拒绝该请求。在 controller 方法中的参数 POJO 前添加 @Valid 注解,Spring 将在绑定参数前自动执行校验操作;也可通过创建对应 validator 对象的方式进行手动校验。如 /user4 中添加 @Valid 注解进行参数绑定前校验(需在实体类成员变量上添加对应约束注解)。

  1. 多个同名请求参数的值只保留第一个

@RequestParam 注解会在接收时将多个同名参数的值只保留第一个,后面的会忽略。若未添加注解,则会将同名请求值以逗号分隔进行拼接。

  1. 将单个对象绑定到请求参数

通过实现一个自定义的 Converter (即 StringToUserInfoConverter ),自行重写请求参数到实体类的转换,然后添加到解析请求参数的 converter 集合中(即 WebConfig ),这样就可以将 @RequestParam 应用到对应的请求参数上,将请求参数值绑定到实体类(如/user7)。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值