SpringBoot接口接收json参数
前言
通常来讲,HTTP 方法会映射为 CRUD 动作,但这并不是严格的限制,有时候 PUT 也可以用来创建新的资源,POST 也可以用来更新资源。所以在平时的 Web 开发中,你可能常看到method 的值是 GET 和 POST,但是我们需要养成一个好的编码习惯。
CRUD 动作 |
HTTP 方法 |
Create |
POST |
Read |
GET |
Update |
PUT(全部资源) 或 PATCH(部分资源) |
Delete |
DELETE |
前提
首先在controller上加上注解:@RestController
- @RestController
- @RequestMapping("/user")
- @Api(tags = "user", description = "用户控制器")
- public class UserController {
- // ...
- }
详细介绍
一、GET
1)@PathVariable 获取路径参数。即 url/{id} 这种形式。
- @GetMapping("/getDetail/{id}")
- @ApiOperation(value = "根据id获取用户")
- public RbacUser getDetail(@PathVariable Long id) {
- return userService.getById(id);
- }
2)@RequestParam 获取查询参数。即 url?name=xx 这种形式
主要有参数:
value
:参数名字,即入参的请求参数名字,如username表示请求的参数区中的名字为username的参数的值将传入;
required
:是否必须,默认是true,表示请求中一定要有相应的参数,否则会报错;
- @GetMapping("/getByAccount")
- @ApiOperation(value = "根据账号获取用户")
- public RbacUser getByAccount(@RequestParam(required = false) String account) {
- return userService.getByAccount(account);
- }
3) 直接封装DTO参数形式
- @GetMapping("/find")
- @ApiOperation(value = "根据条件获取用户")
- public List<RbacUser> find(RbacUserDTO rbacUserDTO) {
- return userService.find(rbacUserDTO);
- }
二、DELETE
@PathVariable 获取路径参数。即 url/{id} 这种形式。
- @DeleteMapping("/delete/{id}")
- @ApiOperation(value = "删除用户")
- public void delete(@PathVariable Long id) {
- userService.delete(id);
- }
三、POST/PUT/PATCH
@RequestBody 将HTTP请求正文插入方法中,使用适合的 HttpMessageConverter 将请求体写入某个对象。
- @PostMapping("/create")
- @ApiOperation(value = "创建用户")
- public RbacUser getByAccount(@RequestBody @Validated RbacUserDTO rbacUserDTO) {
- return userService.save(rbacUserDTO);
- }
@Validated
:对数据进行校验,以下注解报错会直接返回,如果校验类中包含一个对象引用属性,需要在属性上加上@Valid注解

具体参数检验请参看下面
Springboot restFul 参数检验
概述
对请求参数进行检验,这在web中开始经常能碰到,如果用一个个if/else去做判断,相信这样的代码可读性会比较差
JSR-303 是java为bean数据合法性校验提供的标准框架,是Java EE6中的一项子规范,叫做BeanValidation。JSR303通过在Bean属性上标注@NotNull、@Max等标准的注解指定校验规则,并通过这些标准的验证接口对Bean进行验证。
规定一些检验规范即校验注解,如@Null, @NotNull, @Pattern,位于javax.validation.constraints包下,只提供规范 不提供实现。
在Spring中,有两种方式可以验证输入,一是利用Spring自带的验证框架,二是利用JSR-303的实现,一般建议使用JSR-303的实现,比如Hibernate-Validator。
Hibernate-Validator 是JSR-303的实现。Hibernate Validator提供了JSR-303规范中所有内置constraint的实现,除此之外还有一些附加的constraint,如@Email, @Length, @Range等,位于org.hibernate,validator.constraints包下。
spring-boot-starter-web包里面已经有了hibernate-vlidator包,不需要额外引用hibernate validator依赖。
同时Spring为了给开发者提供便捷,对Hibernate-Validator进行了二次封装,封装了LocalValidatorFactorBean作为validator的实现,这个类兼容了Spring的Validation体系和Hibernate的Validation体系,LocalValidatorFactorBean已经成为了Validator的默认实现。
说明:JSR-349是JSR-303的升级版,添加了一些新特性
如下图,是spring boot 2.1.1中hibernate依赖情况:

常用注解
属性 |
描述 |
举例 |
@AssertTrue |
应用于boolean属性,该属性值必须为true |
@AssertTrue
boolean isOkay;
|
@AssertFalse |
应用于boolean属性,该属性值必须为false |
@AssertFalse
boolean isOkay;
|
@DecimalMax |
只能小于或等于指定值 |
@DecimalMax("1.1")
BigDecimal price;
|
@DecimalMin |
只能大于或等于指定值 |
@DecimalMin("1.1")
BigDecimal price;
|
@Digits |
该属性值必须在指定范围内,interger属性定义该数值的最大整数部分,fraction属性定义该数值的最大 小数部分 |
@Digits(integer=5, fraction=2)
BigDecimal price;
|
@Future |
检查该字段是否是属于未来的日期 |
@Future
Date shippingDate;
|
@Max |
该字段的值只能小于或等于该值 |
@Max(20)
int age;
|
@Min |
该字段的值只能大于或等于该值 |
@Min(20)
int age;
|
@NotNull |
该字段不能为Null |
@NotNull
String name;
|
@Null |
该字段必须是Null |
@Null
String dest;
|
@Past |
该字段必须是过去的一个日期 |
@Past
Date birthDate;
|
@Size |
检查该字段的size是否在min和max之间,可以是字符串、数组、集合、Map等 |
@Size(min=2, max=10)
String description;
|
@Pattern |
该属性值必须与指定的常规表达式相匹配 |
@Pattern(regexp="\\d{3}")
String areaCode;
|
@NotBlank |
只用于String, 不能为Null且trim()之后size>0 |
@NotBlank
String src;
|
@NotEmpty |
不能为Null,且size>0 |
@NotEmpty
String src;
|
@Email |
被注释的元素必须是电子邮箱地址 |
|
@Length |
被注释的字符串String 大小必须在指定范围内 |
@Length(min=6, max=12, message="密码长度必须在6~12")
String src;
|
@Range |
BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型,验证注解的元素值在最小值和最大值之间 |
|
@Valid |
指定递归验证(下篇讲)关联的对象;
如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证
|
|
简单应用举例
需要检验的Bean定义:
- public class StudentBean implements Serializable{
- @NotBlank(message = "用户名不能为空")
- private String name;
- @Min(value = 18, message = "年龄不能小于18岁")
- private Integer age;
- @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手机号格式错误")
- private String phoneNum;
- @Email(message = "邮箱格式错误")
- private String email;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Integer getAge() {
- return age;
- }
-
- public void setAge(Integer age) {
- this.age = age;
- }
-
- public String getPhoneNum() {
- return phoneNum;
- }
-
- public void setPhoneNum(String phoneNum) {
- this.phoneNum = phoneNum;
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
- }
返回错误字段定义:
- public class ArgumentsInvalidResponseBean {
- private String argumentName;
- private String exceptionMsg;
-
- public ArgumentsInvalidResponseBean() {
- }
-
- public ArgumentsInvalidResponseBean(String argumentName, String exceptionMsg) {
- this.argumentName = argumentName;
- this.exceptionMsg = exceptionMsg;
- }
-
- public String getArgumentName() {
- return argumentName;
- }
- public void setArgumentName(String argumentName) {
- this.argumentName = argumentName;
- }
-
- public String getExceptionMsg() {
- return exceptionMsg;
- }
- public void setExceptionMsg(String exceptionMsg) {
- this.exceptionMsg = exceptionMsg;
- }
- }
全局异常处理:
- @ExceptionHandler(MethodArgumentNotValidException.class)
- @ResponseBody
- public List<ArgumentsInvalidResponseBean> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex){
- System.out.println("===================methodArgumentNotValidExceptionHandler Occur============");
-
- List<ArgumentsInvalidResponseBean> argumentsInvalidResponseBeanList = new ArrayList<>();
- for (FieldError error : ex.getBindingResult().getFieldErrors()){
- ArgumentsInvalidResponseBean bean = new ArgumentsInvalidResponseBean();
- bean.setArgumentName(error.getField());
- bean.setExceptionMsg(error.getDefaultMessage());
-
- argumentsInvalidResponseBeanList.add(bean);
- }
- return argumentsInvalidResponseBeanList;
- }
测试代码:
- @RestController
- public class CheckController {
- @PostMapping("stu")
- public String addStu(@Valid @RequestBody StudentBean studentBean){
- return "add student success";
- }
- }
在PostMan中测试:

注意这里,年龄和邮箱是有错误的,运行后查看返回值,具体如下:

自定义校验
新建注解类 MyConstraint:
- @Target({ElementType.METHOD, ElementType.FIELD})
- @Retention(RetentionPolicy.RUNTIME)
- @Constraint(validatedBy = MyConstraintValidator.class)
- public @interface MyConstraint {
- String message() default "这是一个自定义注解,检测输入是否大写";
- Class<?>[] groups() default {};
-
- Class<? extends Payload>[] payload() default {};
- }
实现MyConstraintValidator:
- public class MyConstraintValidator implements ConstraintValidator<MyConstraint, String> {
- @Override
- public void initialize(MyConstraint constraintAnnotation) {
- System.out.println("+++++++++++++myConstraint init");
- }
-
- @Override
- public boolean isValid(String o, ConstraintValidatorContext constraintValidatorContext) {
- if (!o.equals(o.toUpperCase())){
- System.out.println("输入信息必须是大写");
- return false;
- }
- return true;
- }
- }
当输入信息不是全大写字符时,则检验不通过
使用:
在上面StudentBean中加入检验
- @MyConstraint
- private String className;
测试:

结果如下:

这时说明自定义检验可以工作了
抛出BindException而非MethodArgumentNotValidException
当请求中 Content-Type为“application/x-www-form-urlencoded”时,Spring会把数据解析成 web form data而非json,会使用 FormHttpMessageConverter来转换post的body 并且异常转为BindException。
如果我们想要Spring把POST数据认为是json并且使用MappingJackson2HttpMessageConverter来解析数据,可以把Content-Type设置成 application/json
以上为个人经验,希望能给大家一个参考,也希望大家多多支持w3xue。