有不少同事在工作过程中,会遇到分不清如何获得请求参数值的情况,明明自己测试过的接口是可以获得参数的值的,而给第三方调用的时候就不可以,这些情况不甚枚举。下面博主就给大家详细介绍SpringMVC获得请求参数获取的几种方法。
首先介绍几种常见的Request请求方式
首先介绍几种常见的Request请求方式,以PostMan发起请求为例
- get方法:最为简单,既将参数添加到请求URL当中,如:http://localhost:8080/demo/web/getrequestvalue/addUserByBeanUseRequestBody?age=10&name=yun
- post(Content-Type: application/x-www-form-urlencoded):浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样(略掉无关的请求头):
POST http://www.example.com HTTP/1.1 Content-Type: application/x-www-form-urlencoded;charset=utf-8 title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
- post(Content-Type: multipart/form-data):使用表单上传文件时,必须让 form 的 enctyped 等于这个值。用于上传文件与KeyValue共同存在的请求。
- post(Content-Type: application/json):现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。使用最为广泛。
通过HttpServletRequest接收
最原始的方法,在业务代码开发中,不推荐使用,无法到达高效开发的目的。
/**
* 最原始的方法,在业务代码开发中,不推荐使用,无法到达高效开发的目的:</br>
* 通过HttpServletRequest接收:
* get方式可以获得参数的值
* post方式(Content-Type: application/x-www-form-urlencoded)可以获得参数的值
* post方式(Content-Type: multipart/form-data)可以获得参数的值
* post方式(Content-Type: application/json)无法获得参数的值
*/
@RequestMapping("/addUserByServletRequest")
public ApiResponse addUserByServletRequest(HttpServletRequest request){
User user = new User();
user.setName(request.getParameter("name"));
user.setAge(Integer.parseInt(request.getParameter("age")));
log.debug(logSintring+user);
return new ApiResponse.ApiResponseBuilder().data(user).build();
}
将请求Key作为接口入参方式
/**
* 将请求Key作为接口入参方式,也是较为传统的方法,无法到达高效开发的目的:</br>
* get方式可以获得参数的值
* post方式(Content-Type: application/x-www-form-urlencoded)可以获得参数的值
* post方式(Content-Type: multipart/form-data)可以获得参数的值
* post方式(Content-Type: application/json)无法获得参数的值,报错:"Optional int parameter '**' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type."
*/
@RequestMapping("/addUserByKeyByKey")
public ApiResponse addUserByKeyByKey(String name, int age){
User user = new User();
user.setName(name);
user.setAge(age);
log.debug(logSintring+user);
return new ApiResponse.ApiResponseBuilder().data(user).build();
}
通过POJOBean作为RestApi接口的入参
/**
* 通过POJOBean作为RestApi接口的入参(SpringMVC做映射),此种方式在实际业务开发中较为实用:</br>
* get方式可以获得参数的值
* post方式(Content-Type: application/x-www-form-urlencoded)可以获得参数的值
* post方式(Content-Type: multipart/form-data)可以获得参数的值
* post方式(Content-Type: application/json)无法获得参数的值。这种方式必须使用@RequestBody注解在入参当中。
*/
@RequestMapping("/addUserByBean")
public ApiResponse addUserByBean(User user){
log.debug(logSintring+user);
return new ApiResponse.ApiResponseBuilder().data(user).build();
}
通过POJOBean前面加@RequestBody注解作为RestApi接口的入参
/**
* 通过POJOBean前面加@RequestBody注解作为RestApi接口的入参(SpringMVC做映射),此种方式在实际业务开发中较为实用,配合研发规范,可以达到较高效开发效率:</br>
* get方式不支持,报错:Required request body is missing:
* post方式(Content-Type: application/x-www-form-urlencoded)不可以,报错:Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
* post方式(Content-Type: multipart/form-data)不可以,报错:Content type 'multipart/form-data;boundary=----WebKitFormBoundaryQQDXKavdsLyPAphR;charset=UTF-8' not supported
* post方式(Content-Type: application/json)可以获得参数的值
*/
@RequestMapping("/addUserByBeanUseRequestBody")
public ApiResponse addUserByBeanUseRequestBody(@RequestBody User user){
log.debug(logSintring+user.toString());
return new ApiResponse.ApiResponseBuilder().data(user).build();
}
通过@PathVariable注解获得请求URL中的参数值
/**
* 通过@PathVariable注解获得请求URL中的参数值,此种方式在实际业务开发中较为少见,此种情况符合Restful规范,但是使用不是很方便,尤其是在做接口自动化测试的时候,数据加密也比较困难,建议较少使用:</br>
* get方式支持,需要请求URL路径中有这些信息
* post方式:不管是哪种方式都不支持。 如果post请求的URL路径符合PathVariable也是规则,也是可以获得参数的
*/
@RequestMapping("/addUserByPathValue/{useName}/{userAge}")
public ApiResponse addUserByPathValue(@PathVariable String useName, @PathVariable("userAge") int age){
User user = new User();
user.setAge(age);
user.setName(useName);
log.debug(logSintring+user);
return new ApiResponse.ApiResponseBuilder().data(user).build();
}
通过@RequestParam注解获得请参数值
/**
* 通过@RequestParam注解获得请参数值,此种方式在实际业务开发中使用较多,此种情况符合Restful规范,但是使用不是很方便,尤其是在做接口自动化测试的时候,数据加密也比较困难,建议较少使用:</br>
* get方式支持,需要请求URL路径中有这些信息
* post方式(Content-Type: application/x-www-form-urlencoded)可以。 但是 required = false, defaultValue = "99" 不起作用,即age必须要有此请求参数
* post方式(Content-Type: multipart/form-data) 可以。 但是 required = false, defaultValue = "99" 不起作用,即age必须要有此请求参数
* post方式(Content-Type: application/json) 不可以。
*/
@RequestMapping("/addUserByRequestParam")
public ApiResponse addUserByRequestParam(@RequestParam("name") String userName,
@RequestParam(value = "age", required = false, defaultValue = "99") int userAge){
User user = new User(userName,userAge);
log.debug(logSintring+user);
return new ApiResponse.ApiResponseBuilder().data(user).build();
}
最佳实践
如上有这么多获得请求参数值的方法,那么在实际工作中,哪些最建议使用呢。 现在大家的开发模式都是前后端分离开发,所以使用“post方式(Content-Type: application/json)”作为Ajax最为常见,故Spring端使用“@RequestBody Bean”获得请求参数值最为方便高效,使用频率也最高。用此方式再配合"hibernate validate"工具,可以很方便的做参数校验工作。 在一个人数较多的研发团队中,使用此规范(虽然很多时间不符合Restful风格),可以让团队产生很高的研发效率,此种规范产生的接口文档,在给测试人员做接口自动化测试工作中,也会带来很大的便捷性,不然不同的请求风格、不同的请求类型与或者参数的方法,将大大降低测试人员做接口自动化脚本编写的速度。本博文的示例代码见GitHub《https://github.com/yun19830206/JavaTechnicalSummary/blob/master/Rd_Standard/src/main/java/com/cloud/rdstandard/web/GetHttpRequestParamValueDemo.java》