springMVC的注解@RequestParam与@RequestBody

@RequestParam

简介

You can use the @RequestParam annotation to bind Servlet request parameters (that is, query parameters or form data) to a method argument in a controller.

可以使用@RequestParam注释将Servlet请求参数(即查询参数或表单数据)绑定到控制器中的方法参数。

@RequestParam注释简单类型

官方解释:

By default, any argument that is a simple value type (as determined by BeanUtils#isSimpleProperty) and is not resolved by any other argument resolver, is treated as if it were annotated with @RequestParam.

默认情况下,任何简单值类型的参数(由BeanUtils#isSimpleProperty确定),且不由任何其他参数解析器解析,将被视为使用@RequestParam注释。

BeanUtils#isSimpleProperty的源码如下:

public static boolean isSimpleProperty(Class<?> type) {
	Assert.notNull(type, "'type' must not be null");
	return isSimpleValueType(type) || type.isArray() && isSimpleValueType(type.getComponentType());
}

public static boolean isSimpleValueType(Class<?> type) {
	return Void.class != type && Void.TYPE != type && (ClassUtils.isPrimitiveOrWrapper(type) || Enum.class.isAssignableFrom(type) || CharSequence.class.isAssignableFrom(type) || Number.class.isAssignableFrom(type) || Date.class.isAssignableFrom(type) || Temporal.class.isAssignableFrom(type) || URI.class == type || URL.class == type || Locale.class == type || Class.class == type);
}

结论:在使用springMVC的时候,参数的类型为BeanUtils#isSimpleProperty认定为简单类型的,且不由任何其他参数解析器解析,都可以省略@RequestParam,示例1如下:

// 示例1
@Controller
public class TestController {
    @GetMapping("test/get")
    @ResponseBody
    public Object methodGet(Integer id, String name) {
        return "{\"id\": " + id + ", \"name\": " + name + "}";
    }
}

/*
    测试1
    http://localhost:8080/test/get?id=1&name=name01
    返回:
    {"id": 1, "name": name01}

    测试2
    http://localhost:8080/test/get?id=1
    返回:
    {"id": 1, "name": null}
*/
@RequestParam的required参数

官方解释:

By default, method parameters that use this annotation are required, but you can specify that a method parameter is optional by setting the @RequestParam annotation’s required flag to false or by declaring the argument with an java.util.Optional wrapper.
默认情况下,使用此注释的方法参数是必需的,但是您可以通过将@RequestParam注释的required标志设置为false或使用java.util.Optional包装器声明参数来指定方法参数是可选的。

示例如下

// 示例2
@Controller
public class TestController {
    @GetMapping("test/get")
    @ResponseBody
    public Object methodGet(@RequestParam Integer id, @RequestParam String name) {
        return "{\"id\": " + id + ", \"name\": " + name + "}";
    }
}

/*
    测试
    http://localhost:8080/test/get?id=1
    返回:
    {   
        "status": 400,
        "error": "Bad Request",
        "trace": "org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'name' for method parameter type String is not present....."
        "message": "Required request parameter 'name' for method parameter type String is not present"
        "path": "/test/get"
    }
*/

// 示例3
@Controller
public class TestController {
    @GetMapping("test/get")
    @ResponseBody
    public Object methodGet(@RequestParam Integer id, @RequestParam(required = false) String name) {
        return "{\"id\": " + id + ", \"name\": " + name + "}";
    }
}

/*
    测试
    http://localhost:8080/test/get?id=1
    返回:
    {"id": 1, "name": null}
*/
@RequestParam的接收数组, 列表参数

官方解释:

Declaring the argument type as an array or list allows for resolving multiple parameter values for the same parameter name.
将参数类型声明为数组或列表,允许为相同的参数名称解析多个参数值。

示例如下:

// 示例4
@Controller
public class TestController {
    @GetMapping("test/get")
    @ResponseBody
    public Object methodGet(@RequestParam Integer[] arr) {
        return arr;
    }
}    
    
/*
    测试1
    http://localhost:8080/test/get?arr=1&arr=2
    返回:
    [
        1,
        2
    ]

    测试2
    http://localhost:8080/test/get?arr=1,2,3
    返回
    [
        1,
        2,
        3
    ]
*/

// 示例5
@Controller
public class TestController {
    @GetMapping("test/get")
    @ResponseBody
    public Object methodGet(@RequestParam List<Integer> list) {
        return list;
    }
} 

/*
    测试
    http://localhost:8080/test/get/8?list=11,22,33
    返回:
    [
        11,
        22,
        33
    ]
*/
@RequestParam的接收Map, MultiValueMap参数

官方解释:

When an @RequestParam annotation is declared as a Map or MultiValueMap, without a parameter name specified in the annotation, then the map is populated with the request parameter values for each given parameter name.

当@RequestParam注释声明为Map或MultiValueMap,而没有在注释中指定参数名时,那么映射将使用每个给定参数名的请求参数值填充。

示例如下:

// 示例4
@Controller
public class TestController {
    @GetMapping("test/get")
    @ResponseBody
    public Object methodGet(@RequestParam Map<String, Object> params) {
        return params;
    }
}  

/*
    测试
    http://localhost:8080/test/get/5?id=1&name=01&age=22&date=2001-01-01
    返回:
    {
        "id": "1",
        "name": "01",
        "age": "22",
        "date": "2001-01-01"
    }
*/
@RequestParam处理POST请求表单application/x-www-form-urlencoded类型

示例如下:

// 示例
@Controller
public class TestController {
	/**
     * 测试@RequestParam 接收表单数据 application/x-www-form-urlencoded类型
     */
    @PostMapping("test/form/1")
    @ResponseBody
    public Object methodForm1(@RequestParam Map<String, Object> params) {
        return params;
    }
}  

测试1,使用postman 构造一个表单请求如下:
springMVC的注解@RequestParam与@RequestBody_第1张图片
测试2,使用@RequestParam可以同时接收url路径以及请求body中的参数
springMVC的注解@RequestParam与@RequestBody_第2张图片

@RequestParam处理POST请求表单multipart/form-data类型

示例如下:

// 示例
@Controller
public class TestController {
    /**
     * 测试@RequestParam 接收表单数据 multipart/form-data类型
     */
    @PostMapping("test/form/2")
    @ResponseBody
    public Object methodForm2(@RequestParam MultipartFile file, @RequestParam String name) {
        return name + "-------" + file.getOriginalFilename();
    }
}

测试:
springMVC的注解@RequestParam与@RequestBody_第3张图片

@RequestBody

简介:

You can use the @RequestBody annotation to have the request body read and deserialized into an Object through an HttpMessageConverter

您可以使用@RequestBody注释通过HttpMessageConverter将请求体读取并反序列化为一个Object

@RequestBody与@Validated/@Valid 组合使用

官方解释:

You can use @RequestBody in combination with javax.validation.Valid or Spring’s @Validated annotation, both of which cause Standard Bean Validation to be applied.

您可以将@RequestBody与javax. validate .valid或Spring的@Validated注释结合使用,这两者都会应用标准Bean验证。

By default, validation errors cause a MethodArgumentNotValidException, which is turned into a 400 (BAD_REQUEST) response.

默认情况下,验证错误会导致MethodArgumentNotValidException,该异常将转换为400 (BAD_REQUEST)响应。

Alternatively, you can handle validation errors locally within the controller through an Errors or BindingResult argument, as the following example shows

或者,您可以通过errors或BindingResult参数在控制器内部本地处理验证错误,

注意:如果要与使用@Validated需要引入hibernate-validator或者validation-api

<dependency>
	<groupId>org.hibernategroupId>
	<artifactId>hibernate-validatorartifactId>
	<version>5.3.6.Finalversion>
dependency>

示例如下:

// 实体类 
@Data
@Accessors(chain = true)
public class User {
    @Max(Integer.MAX_VALUE)
    private Integer id;

    @NotBlank // @NotBlank 验证元素不为空(不为null或者去除首尾空格后长度为0,用于字符串会去除首尾空格)
    @Size(max = 16, min = 1) // 验证数据的长度必须是在1~16
    private String name;
    
    @Max(200) // 验证最大的数值为200
    @Min(0) // 验证最小数值为0
    private Integer age;
}

@Controller
public class TestController {
    @PostMapping("test/post/1")
    @ResponseBody
    public Object methodPost1(@RequestBody @Validated User user) {
        return user;
    }
}

/*
测试(使用 application/json)

你可能感兴趣的:(spring,java,spring)