溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

SpringBoo中Get請求參數(shù)有哪些

發(fā)布時間:2021-11-17 09:20:18 來源:億速云 閱讀:128 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容介紹了“SpringBoo中Get請求參數(shù)有哪些”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

I. 環(huán)境搭建

首先得搭建一個web應(yīng)用才有可能繼續(xù)后續(xù)的測試,借助SpringBoot搭建一個web應(yīng)用屬于比較簡單的活;

創(chuàng)建一個maven項目,pom文件如下

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.7</version>
    <relativePath/> <!-- lookup parent from update -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

添加項目啟動類Application.cass

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}

在演示請求參數(shù)的解析實例中,我們使用終端的curl命令來發(fā)起http請求(主要原因是截圖上傳太麻煩,還是終端的文本輸出比較方便;缺點是不太直觀)

II. GET請求參數(shù)解析

接下來我們正式進入?yún)?shù)解析的妖嬈姿勢篇,會介紹一下常見的一些case(并不能說包含了所有的使用case)

下面所有的方法都放在 ParamGetRest 這個Controller中

@RestController
@RequestMapping(path = "get")
public class ParamGetRest {
}

1. HttpServletRequest

直接使用HttpServletRequest來獲取請求參數(shù),屬于比較原始,但是靈活性最高的使用方法了。

常規(guī)使用姿勢是方法的請求參數(shù)中有一個HttpServletRequest,我們通過ServletRequest#getParameter(參數(shù)名)來獲取具體的請求參數(shù),下面演示返回所有請求參數(shù)的case

@GetMapping(path = "req")
public String requestParam(HttpServletRequest httpRequest) {
    Map<String, String[]> ans = httpRequest.getParameterMap();
    return JSON.toJSONString(ans);
}

測試case,注意下使用curl請求參數(shù)中有中文時,進行了url編碼(后續(xù)會針對這個問題進行說明)

?  ~ 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獲取請求參數(shù),還有另外一種使用case,不通過參數(shù)傳遞的方式獲取Request實例,而是借助RequestContextHolder;這樣的一個好處就是,假設(shè)我們想寫一個AOP,攔截GET請求并輸出請求參數(shù)時,可以通過下面這種方式來處理

@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=一灰灰%

2. 方法參數(shù)

這種解析方式比較厲害了,將GET參數(shù)與方法的參數(shù)根據(jù)參數(shù)名進行映射,從感官上來看,就像是直接調(diào)用這個一樣

@GetMapping(path = "arg")
public String argParam(String name, Integer age) {
    return "name: " + name + " age: " + age;
}

針對上面提供的方式,我們的測試自然會區(qū)分為下面幾種,看下會怎樣

  • 正好兩個參數(shù),與定義一直

  • 缺少一個請求參數(shù)

  • 多一個請求參數(shù)

  • 參數(shù)類型不一致

# 參數(shù)解析正常
?  ~ curl 'http://127.0.0.1:8080/get/arg?name=%E4%B8%80%E7%81%B0%E7%81%B0&age=19'
name: 一灰灰 age: 19%
# 缺少一個參數(shù)時,為null
?  ~ curl 'http://127.0.0.1:8080/get/arg?name=%E4%B8%80%E7%81%B0%E7%81%B0'
name: 一灰灰 age: null% 
# 多了一個參數(shù),無法被解析
?  ~ 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可以看出,利用方法參數(shù)解析GET傳參時,實際效果是:

  • 方法參數(shù)與GET傳參,通過參數(shù)簽名進行綁定

  • 方法參數(shù)類型,需要與接收的GET傳參類型一致

  • 方法參數(shù)非基本類型時,若傳參沒有,則為null;(也就是說如果為基本類型,無法轉(zhuǎn)null,拋異常)

  • 實際的GET傳參可以多于方法定義的參數(shù)

接下來給一個數(shù)組傳參解析的實例

@GetMapping(path = "arg2")
public String argParam2(String[] names, int size) {
    return "name: " + (names != null ? Arrays.asList(names) : "null") + " size: " + size;
}

測試case如下,傳數(shù)組時參數(shù)值用逗號分隔;基本類型,必須傳參,否則解析異常

?  ~ 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

3. RequestParam 注解

這種方式看起來和前面有些相似,但更加靈活,我們先看一下注解

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
  // 指定請求參數(shù)名
	String value() default "";
	// 指定請求參數(shù)名
	String name() default "";
	// true表示發(fā)起請求時這個參數(shù)必須存在
	boolean required() default true;
	String defaultValue() default ValueConstants.DEFAULT_NONE;
}

有兩個參數(shù)需要注意,一個是name表示這個參數(shù)與GET傳參的哪個關(guān)聯(lián);required表示這個參數(shù)是否可選

下面是一個簡單的使用方式

@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");
}

測試如下:

# 三個參數(shù)全在
?  ~ 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]% 
# 必選參數(shù)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,這個參數(shù)就與指定的GETGET傳參關(guān)聯(lián);如果不指定時,則根據(jù)參數(shù)簽名來關(guān)聯(lián)

下面給出兩個更有意思的使用方式,一個是枚舉參數(shù)解析,一個是Map容納參數(shù),一個是數(shù)組參數(shù)解析

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 Map<String, Object> params) {
    return params.toString();
}

// 注意下面這個寫法,無法正常獲取請求參數(shù),這里用來對比列出
@GetMapping(path = "mapper2")
public String mapperParam2(Map<String, Object> params) {
    return params.toString();
}


@GetMapping(path = "ano1")
public String anoParam1(@RequestParam(name = "names") List<String> names) {
    return "name: " + names;
}

// 注意下面這個寫法無法正常解析數(shù)組
@GetMapping(path = "arg3")
public String anoParam2(List<String> 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

從測試結(jié)果可以知道:

  • GET傳參映射到枚舉時,根據(jù)enum.valueOf()來實例的

  • 如果希望使用Map來容納所有的傳參,需要加上注解@RequestParam

  • 如果參數(shù)為List類型,必須添加注解@RequestParam;否則用數(shù)組來接收


4. PathVariable

從請求的url路徑中解析參數(shù),使用方法和前面的差別不大

@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;
}

上面是一個常見的使用方式,對此我們帶著幾個疑問設(shè)計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中獲取參數(shù)時,對url有相對嚴(yán)格的要求,注意使用


5. POJO

這種case,我個人用得比較多,特別是基于SpringCloud的生態(tài)下,借助Feign來調(diào)用第三方微服務(wù),可以說是很舒爽了;下面看一下這種方式的使用姿勢

首先定義一個POJO

@Data
public class BaseReqDO implements Serializable {
    private static final long serialVersionUID = 8706843673978981262L;

    private String name;

    private Integer age;

    private List<Integer> uIds;
}

提供一個服務(wù)

@GetMapping(path = "bean")
public String beanParam(BaseReqDO req) {
    return req.toString();
}

POJO中定義了三個參數(shù),我們再測試的時候,看一下這些參數(shù)是否必選

# GET傳參與POJO中成員名進行關(guān)聯(lián)
?  ~ 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中成員為基本類型,則參數(shù)必傳
?  ~ curl 'http://127.0.0.1:8080/get/bean?name=yihuihui&age=18'
BaseReqDO(name=yihuihui, age=18, uIds=null)%

“SpringBoo中Get請求參數(shù)有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI