Spring Boot 学习研究笔记(十五) @RequestMapping 注解及参数接收、校验详解(2)

简介: Spring Boot 学习研究笔记(十五) @RequestMapping 注解及参数接收、校验详解

(3)、@GetMapping 入参注解注意事项

   GET 请求当使用 @RequestParm 注解和不加注解时,只能接收到 params 携带的参数 ,参数放在请求头 和请求体中均接受不到。

GET 请求 不可以使用 @RequestBody 注解

 

 

 

11、@PostMapping注解说明

(1)、@PostMapping是@RequestMapping(method = RequestMethod.POST) 快捷方式

(2)、@GetMapping 入参注解注意事项

 POST请求 当使用 @RequestParm 注解 和 不加注解时,只能接收到 params 和请求体xxx格式携带的参数,加注解无法接收到对象参数。

POST请求 当使用 @RequestBody注解 ,只能接收到请求体JSON格式和表单携带的参数 其他类型参数均接受不到

POST请求接收一个参数 不可以使用 @RequestBody 注解。

 

二、参数接收

1、Body参数

Body参数一般是POST请求,主要有两种方式

  • 以JSON格式接收可通过@RequestBody获取对应的参数
  • 以form表单形式提交的,暂无注解适配,可直接对象接收

    (1)、JSON参数接收
    例如:添加用户的接口, 前端PostMan 请求信息如下:

 

后端接收代码1:

@PostMapping(value = "/user/map")
public ResultVO createUser(@RequestBody Map<String,Object> user)
{  
  String name=user.get("name").toString();  
  return RV.success(user);
}

后端接收代码2:

@PostMapping(value = "/user")
public ResultVO createUser2(@RequestBody User user)
{  
  System.out.println("User Info:"+user.toString());  
  return RV.success(user);
}

 

(2)、FORM 参数接收

form方式提交,在PostMan中对应参数如下

 

 

对应后端接收代码:

@PostMapping(value = "/user/form")
public ResultVO createUser3(User user)
{   
 System.out.println("User Info:"+user.toString()); 
 return RV.success(user);
}

2、请求头和Cookie参数

  • @RequestHeader,是直接获取请求头HttpServletRequest对象里面Header中的参数
  • @CookieValue 可以直接获取HttpServletRequest对象里面Cookies中的参数

通过注解的方式获取,分别如下

@GetMapping("demo3")
public void demo3(@RequestHeader(name = "myHeader") String myHeader,        @CookieValue(name = "myCookie") String myCookie) 
{   
  System.out.println("myHeader=" + myHeader);   
  System.out.println("myCookie=" + myCookie);
}

通过硬编码的获取方式为

@GetMapping("/demo3")
public void demo3(HttpServletRequest request) 
{  
 System.out.println(request.getHeader("myHeader")); 
 for (Cookie cookie : request.getCookies()) 
 {       
   if ("myCookie".equals(cookie.getName())) 
  {          
   System.out.println(cookie.getValue());
  }  
 }
}

由上可以看出,通过注解的方式可以极大简化编码,使我们的代码变得美观大方,如果通过request对象直接获取,也是可以的,这个主要是看什么样的需求,一般情况下,通过注解的方式基本上能满足我们的绝大部分需求,所以在项目中我们比较推荐直接通过注解的方式获取参数。

 

3、文件上传参数

文件上传主要是基于@RequestParam 结合MultipartFile对象;如下示例;

这里需要注意,前端的传入需要用表单方式提交,并且在Head的Content-Type里面加入,如下信息

Content-Type: application/x-www-form-urlencoded

 

 

对应后端代码如下

@Value("${file.upload.url}")
private String filePath;
@RequestMapping("/upload")
public ResultVO httpUpload(@RequestParam("files") MultipartFile files[]){ 
 for(int i=0;i<files.length;i++)
 {       
     String fileName = files[i].getOriginalFilename();  // 文件名       
     File dest = new File(filePath+'/'+fileName);       
     if (!dest.getParentFile().exists()) {      
       dest.getParentFile().mkdirs();       
     }    
     try {         
       files[i].transferTo(dest);      
     } catch (Exception e) {  
      log.error("{}",e);     
      return RV.result(ErrorCode.UPLOAD_FILE_ERROR,e);   
     }   
    }   
    return RV.success(null);
 }

三、参数校验

在Controller层的参数校验可以分为两种场景,单个参数校验和实体参数校验

(1)、单个参数校验

后端代码如下

@RestControllerpublic class ValidateController 
{  
 @GetMapping("/getUser")    
 @Validated   
    public ResultVO getUserStr(@NotNull(message = "name 不能为空")  String name,                               @Max(value = 99, message = "不能大于99岁") Integer age) 
    {       
     return RV.success("name: " + name + " ,age:" + age);   
    }
}

在Postman请求如下,可以看到请求后,返回了系统异常,应该是被全局异常拦截了.

 

 

我们再看后台打印的日志:

 

如果我们系统中有很多地方都用到了参数校验,那么我们最好是能够在全局异常拦截处直接拦截ConstraintViolationException异常,并进行统一处理,可以在我们前面章节讲到的,在加了@RestControllerAdvice注解的GlobalException类中加入如下拦截的新方法;由于ConstraintViolationException继承了ValidationException异常类,所以我们可以直接拦截父类异常,直接进行多个不同的校验异常进行处理.

@RestControllerAdvice
public class GlobalException 
{  
 @ExceptionHandler(value = ValidationException.class)  
    public  ResultVO validationException(ValidationException e){   
      Map map=new HashMap();   
      if(e instanceof ConstraintViolationException){  
       ConstraintViolationException exs = (ConstraintViolationException) e;                 Set<ConstraintViolation>> violations = exs.getConstraintViolations();        
       for (ConstraintViolation> item : violations) {          
             //打印验证不通过的信息              
              System.out.println(item.getMessage());  
                map.put(item.getPropertyPath(),item.getMessage());          
      }       
     }     
     return RV.result(ErrorCode.FORM_VALIDATION_ERROR,map) ; 
    }
 }

同样,再通过Postman请求后,得到如下结果

 

(2、)实体参数校验

一般我们在传入参数比较少的情况下,就直接用上面的方法进行了验证了,但是,如果我们传入的是一个对象,直接在方法上一个一个属性设置,就显得有点不美观了,因此我们一般都是封装一个接收参数的对象。如下面实例提供的,添加用户接口,我们对用户对象的变量设置了校验规则,如下

@Dataclass Person 
{    
 @NotNull(message = "名称不能为空")  
    @Max(value = 30, message = "名称不能超过30个字符")  
    String name; 
    @Max(value = 200, message = "年龄不能超过200岁吧")  
    @NotNull(message = "年龄不能为空")  
    Integer age;  
    @NotNull(message = "地址信息不能为空")  
    String address;
}

在Controller类中我们增加添加用户的方法,这里我们需要注意,我们只需要在方法对应的参数Person对象前面加上@Valid注解即可

@PostMapping(value = "/person")    
public ResultVO<Person> addPerson(@RequestBody @Valid Person person) 
{        //此处略过处理业务的代码...      
     return RV.success(person); 
}

其实大家可能就会问,那要是参数校验不同过,这里应该是抛出什么异常呢,当我们执行如上代码,设定超出范围的参数后,在后端可以看到异常如下

 

 

可以看到,这里抛出的MethodArgumentNotValidException与上面的异常截然不同;相同道理,我依然在GlobalException类中加入对MethodArgumentNotValidException异常的全局拦截即可

@ExceptionHandler(value = MethodArgumentNotValidException.class)  
 public  ResultVO methodArgumentNotValidException(MethodArgumentNotValidException e){           List<ObjectError> errors = e.getBindingResult().getAllErrors();     
   String[] errMessage=new String[errors.size()];    
     for (int i = 0; i < errors.size(); i++) {         
      ObjectError error=errors.get(i);           
      errMessage[i]=error.getDefaultMessage();  
            System.out.println(error.getCode()+":"+error.getDefaultMessage());   
     }       
        return RV.result(ErrorCode.METHOD_ARGS_VALID_ERROR,errMessage) ;  
  }

Validated与Valid区别

  • @Validated: 用在方法的入参上无法单独提供嵌套验证功能。不能用在成员属性(字段)上,也无法提示框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证
  • @Valid:用在方法入的参上无法单独提供嵌套验证功能。能够用在成员属性(字段)上,提示验证框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。

如上Person对象,如果里面再有一个对象,比如还是Person,在提交的过程中,需要这种嵌套验证,就需要通过使用Valid的嵌套验证功能,即可将代码修改如下;

@Dataclass Person 
{   
 @NotNull(message = "名称不能为空") 
    @Size(min = 2,max = 30, message = "名称长度限定在2-30之间的长度")  
    String name;  
    @Max(value = 200, message = "年龄不能超过200岁吧")  
    @NotNull(message = "年龄不能为空")  
    Integer age;   
    @NotNull(message = "地址信息不能为空")  
    String address;  
    @Valid  
    Person p;
 }

常用参数校验的注解

这里我们主要介绍在springboot中的几种参数校验方式。常用的用于参数校验的注解如下:

  • @AssertFalse 所注解的元素必须是Boolean类型,且值为false
  • @AssertTrue 所注解的元素必须是Boolean类型,且值为true
  • @DecimalMax 所注解的元素必须是数字,且值小于等于给定的值
  • @DecimalMin 所注解的元素必须是数字,且值大于等于给定的值
  • @Digits 所注解的元素必须是数字,且值必须是指定的位数
  • @Future 所注解的元素必须是将来某个日期
  • @Max 所注解的元素必须是数字,且值小于等于给定的值
  • @Min 所注解的元素必须是数字,且值小于等于给定的值
  • @Range 所注解的元素需在指定范围区间内
  • @NotNull 所注解的元素值不能为null
  • @NotBlank 所注解的元素值有内容
  • @Null 所注解的元素值为null
  • @Past 所注解的元素必须是某个过去的日期
  • @PastOrPresent 所注解的元素必须是过去某个或现在日期
  • @Pattern 所注解的元素必须满足给定的正则表达式
  • @Size 所注解的元素必须是String、集合或数组,且长度大小需保证在给定范围之内
  • @Email 所注解的元素需满足Email格式
相关文章
|
4月前
|
XML JSON Java
【SpringBoot(三)】从请求到响应再到视图解析与模板引擎,本文带你领悟SpringBoot请求接收全流程!
Springboot专栏第三章,从请求的接收到视图解析,再到thymeleaf模板引擎的使用! 本文带你领悟SpringBoot请求接收到渲染的使用全流程!
370 3
|
7月前
|
前端开发 Java 数据库连接
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
|
7月前
|
人工智能 JSON Java
Spring Boot 如何接收并处理不确定类型的请求参数?
在 Spring Boot 中,当需要处理结构不确定的 JSON 数据时,可以使用 `Map` 类型灵活接收键值对数据。对于更复杂的场景,可通过 Jackson 注解支持多态类型、自定义反序列化器,或在接收后动态解析 JSON 数据,提升处理灵活性和扩展性。
242 0
|
12月前
|
Java Spring
SpringBoot 实战 不同参数调用不同实现
本文介绍了如何在实际工作中根据不同的入参调用不同的实现,采用`map+enum`的方式实现优雅且严谨的解决方案。通过Spring Boot框架中的工厂模式或策略模式,避免了使用冗长的`if...else...`语句。文中详细展示了定义接口、实现类、枚举类以及控制器调用的代码示例,确保用户输入的合法性并简化了代码逻辑。
462 1
SpringBoot 实战 不同参数调用不同实现
|
12月前
|
消息中间件 Java Kafka
【Azure Kafka】使用Spring Cloud Stream Binder Kafka 发送并接收 Event Hub 消息及解决并发报错
reactor.core.publisher.Sinks$EmissionException: Spec. Rule 1.3 - onSubscribe, onNext, onError and onComplete signaled to a Subscriber MUST be signaled serially.
224 5
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
160 5
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
1036 2
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
2321 1
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
359 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现