扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
本篇内容介绍了“SpringBoo中Get请求参数有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
10年积累的成都网站设计、成都网站制作经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先网站设计后付款的网站建设流程,更有志丹免费网站建设让你可以放心的选择与我们合作。
首先得搭建一个web应用才有可能继续后续的测试,借助SpringBoot搭建一个web应用属于比较简单的活;
创建一个maven项目,pom文件如下
org.springframework.boot spring-boot-starter-parent 2.1.7 UTF-8 UTF-8 Finchley.RELEASE 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-maven-plugin spring-milestones Spring Milestones https://repo.spring.io/milestone false
添加项目启动类Application.cass
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class); } }
在演示请求参数的解析实例中,我们使用终端的curl命令来发起http请求(主要原因是截图上传太麻烦,还是终端的文本输出比较方便;缺点是不太直观)
接下来我们正式进入参数解析的妖娆姿势篇,会介绍一下常见的一些case(并不能说包含了所有的使用case)
下面所有的方法都放在 ParamGetRest
这个Controller中
@RestController @RequestMapping(path = "get") public class ParamGetRest { }
直接使用HttpServletRequest
来获取请求参数,属于比较原始,但是灵活性最高的使用方法了。
常规使用姿势是方法的请求参数中有一个HttpServletRequest
,我们通过ServletRequest#getParameter(参数名)
来获取具体的请求参数,下面演示返回所有请求参数的case
@GetMapping(path = "req") public String requestParam(HttpServletRequest httpRequest) { Mapans = httpRequest.getParameterMap(); return JSON.toJSONString(ans); }
测试case,注意下使用curl请求参数中有中文时,进行了url编码(后续会针对这个问题进行说明)
➜ ~ curl 'http://127.0.0.1:8080/get/req?name=yihuihiu&age=19' {"name":["yihuihiu"],"age":["19"]}% ➜ ~ curl 'http://127.0.0.1:8080/get/req?name=%E4%B8%80%E7%81%B0%E7%81%B0&age=19' {"name":["一灰灰"],"age":["19"]}%
使用HttpServletRequest获取请求参数,还有另外一种使用case,不通过参数传递的方式获取Request实例,而是借助RequestContextHolder
;这样的一个好处就是,假设我们想写一个AOP,拦截GET请求并输出请求参数时,可以通过下面这种方式来处理
@GetMapping(path = "req2") public String requestParam2() { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); String name = request.getParameter("name"); return "param Name=" + name; }
测试case
➜ ~ curl 'http://127.0.0.1:8080/get/req2?name=%E4%B8%80%E7%81%B0%E7%81%B0&age=19' param Name=一灰灰%
这种解析方式比较厉害了,将GET参数与方法的参数根据参数名进行映射,从感官上来看,就像是直接调用这个一样
@GetMapping(path = "arg") public String argParam(String name, Integer age) { return "name: " + name + " age: " + age; }
针对上面提供的方式,我们的测试自然会区分为下面几种,看下会怎样
正好两个参数,与定义一直
缺少一个请求参数
多一个请求参数
参数类型不一致
# 参数解析正常 ➜ ~ curl 'http://127.0.0.1:8080/get/arg?name=%E4%B8%80%E7%81%B0%E7%81%B0&age=19' name: 一灰灰 age: 19% # 缺少一个参数时,为null ➜ ~ curl 'http://127.0.0.1:8080/get/arg?name=%E4%B8%80%E7%81%B0%E7%81%B0' name: 一灰灰 age: null% # 多了一个参数,无法被解析 ➜ ~ curl 'http://127.0.0.1:8080/get/arg?name=%E4%B8%80%E7%81%B0%E7%81%B0&age=19&id=10' name: 一灰灰 age: 19% # 类型不一致,500 ➜ ~ curl 'http://127.0.0.1:8080/get/arg?name=%E4%B8%80%E7%81%B0%E7%81%B0&age=haha' -i HTTP/1.1 500 Content-Length: 0 Date: Sat, 24 Aug 2019 01:45:14 GMT Connection: close
从上面实际的case可以看出,利用方法参数解析GET传参时,实际效果是:
方法参数与GET传参,通过参数签名进行绑定
方法参数类型,需要与接收的GET传参类型一致
方法参数非基本类型时,若传参没有,则为null;(也就是说如果为基本类型,无法转null,抛异常)
实际的GET传参可以多于方法定义的参数
接下来给一个数组传参解析的实例
@GetMapping(path = "arg2") public String argParam2(String[] names, int size) { return "name: " + (names != null ? Arrays.asList(names) : "null") + " size: " + size; }
测试case如下,传数组时参数值用逗号分隔;基本类型,必须传参,否则解析异常
➜ ~ curl 'http://127.0.0.1:8080/get/arg2?name=yihui,erhui&size=2' name: null size: 2% ➜ ~ curl 'http://127.0.0.1:8080/get/arg2?name=yihui,erhui' -i HTTP/1.1 500 Content-Length: 0 Date: Sat, 24 Aug 2019 01:53:30 GMT Connection: close
这种方式看起来和前面有些相似,但更加灵活,我们先看一下注解
@Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestParam { // 指定请求参数名 String value() default ""; // 指定请求参数名 String name() default ""; // true表示发起请求时这个参数必须存在 boolean required() default true; String defaultValue() default ValueConstants.DEFAULT_NONE; }
有两个参数需要注意,一个是name表示这个参数与GET传参的哪个关联;required表示这个参数是否可选
下面是一个简单的使用方式
@GetMapping(path = "ano") public String anoParam(@RequestParam(name = "name") String uname, @RequestParam(name = "age", required = false) Integer age, @RequestParam(name = "uids", required = false) Integer[] uids) { return "name: " + uname + " age: " + age + " uids: " + (uids != null ? Arrays.asList(uids) : "null"); }
测试如下:
# 三个参数全在 ➜ ~ curl 'http://localhost:8080/get/ano?name=%E4%B8%80%E7%81%B0%E7%81%B0blog&age=18&uids=1,3,4' name: 一灰灰blog age: 18 uids: [1, 3, 4]% # age不传 ➜ ~ curl 'http://localhost:8080/get/ano?name=%E4%B8%80%E7%81%B0%E7%81%B0blog&uids=1,3,4' name: 一灰灰blog age: null uids: [1, 3, 4]% # 必选参数name不传时 ➜ ~ curl 'http://localhost:8080/get/ano?uids=1,3,4' -i HTTP/1.1 500 Content-Length: 0 Date: Sat, 24 Aug 2019 13:09:07 GMT Connection: close
使用RequestParam
注解时,如果指定了name/value
,这个参数就与指定的GETGET传参关联;如果不指定时,则根据参数签名来关联
下面给出两个更有意思的使用方式,一个是枚举参数解析,一个是Map容纳参数,一个是数组参数解析
public enum TYPE { A, B, C; } @GetMapping(path = "enum") public String enumParam(TYPE type) { return type.name(); } @GetMapping(path = "enum2") public String enumParam2(@RequestParam TYPE type) { return type.name(); } @GetMapping(path = "mapper") public String mapperParam(@RequestParam Mapparams) { return params.toString(); } // 注意下面这个写法,无法正常获取请求参数,这里用来对比列出 @GetMapping(path = "mapper2") public String mapperParam2(Map params) { return params.toString(); } @GetMapping(path = "ano1") public String anoParam1(@RequestParam(name = "names") List names) { return "name: " + names; } // 注意下面这个写法无法正常解析数组 @GetMapping(path = "arg3") public String anoParam2(List names) { return "names: " + names; }
测试case如下
➜ ~ curl 'http://localhost:8080/get/enum?type=A' A% ➜ ~ curl 'http://localhost:8080/get/enum2?type=A' A% ➜ ~ curl 'http://localhost:8080/get/mapper?type=A&age=3' {type=A, age=3}% ➜ ~ curl 'http://localhost:8080/get/mapper2?type=A&age=3' {}% ➜ ~ curl 'http://localhost:8080/get/ano1?names=yi,hui,ha' name: [yi, hui, ha]% ➜ ~ curl 'http://localhost:8080/get/arg3?names=yi,hui,ha' -i HTTP/1.1 500 Content-Length: 0 Date: Sat, 24 Aug 2019 13:50:55 GMT Connection: close
从测试结果可以知道:
GET传参映射到枚举时,根据enum.valueOf()
来实例的
如果希望使用Map来容纳所有的传参,需要加上注解@RequestParam
如果参数为List类型,必须添加注解@RequestParam
;否则用数组来接收
从请求的url路径中解析参数,使用方法和前面的差别不大
@GetMapping(path = "url/{name}/{index}") public String urlParam(@PathVariable(name = "name") String name, @PathVariable(name = "index", required = false) Integer index) { return "name: " + name + " index: " + index; }
上面是一个常见的使用方式,对此我们带着几个疑问设计case
只有name没有index,会怎样?
有name,有index,后面还有路径,会怎样?
➜ ~ curl http://127.0.0.1:8080/get/url/yihhuihui/1 name: yihhuihui index: 1% ➜ ~ curl 'http://127.0.0.1:8080/get/url/yihhuihui' -i HTTP/1.1 500 Content-Length: 0 Date: Sat, 24 Aug 2019 13:27:08 GMT Connection: close ➜ ~ curl 'http://127.0.0.1:8080/get/url/yihhuihui/1/test' -i HTTP/1.1 500 Content-Length: 0 Date: Sat, 24 Aug 2019 13:27:12 GMT Connection: close
从path中获取参数时,对url有相对严格的要求,注意使用
这种case,我个人用得比较多,特别是基于SpringCloud的生态下,借助Feign来调用第三方微服务,可以说是很舒爽了;下面看一下这种方式的使用姿势
首先定义一个POJO
@Data public class BaseReqDO implements Serializable { private static final long serialVersionUID = 8706843673978981262L; private String name; private Integer age; private ListuIds; }
提供一个服务
@GetMapping(path = "bean") public String beanParam(BaseReqDO req) { return req.toString(); }
POJO中定义了三个参数,我们再测试的时候,看一下这些参数是否必选
# GET传参与POJO中成员名进行关联 ➜ ~ curl 'http://127.0.0.1:8080/get/bean?name=yihuihui&age=18&uIds=1,3,4' BaseReqDO(name=yihuihui, age=18, uIds=[1, 3, 4])% # 没有传参的属性为null;因此如果POJO中成员为基本类型,则参数必传 ➜ ~ curl 'http://127.0.0.1:8080/get/bean?name=yihuihui&age=18' BaseReqDO(name=yihuihui, age=18, uIds=null)%
“SpringBoo中Get请求参数有哪些”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流