Jersey Restful接口如何獲取參數的問題
緣起
工作時使用java開發服務器後臺,用Jersey寫Restful接口,發現有一個Post方法始終獲取不到參數,查瞭半天,發現時獲取參數的註釋不太對,將@formparam寫成瞭@queryparam,發現瞭這個改過來就好瞭,順便整理瞭一下不同參數的作用。
簡述
獲取URI的參數
獲取Get請求的參數
獲取Post類型的參數
添加參數默認值
獲取Map參數
1.@PathParam
使用該註釋獲取參數時可以獲取URI中制定規則的參數
例如:
//該類的路徑為/user @GET @Path("{username"}) @Produces(MediaType.APPLICATION_JSON) public User getUser(@PathParam("username") String userName) { ...}
當瀏覽器請求
http://localhost:8080/user/jack
時,username的值就是jack。請註意,這裡的username並不是說key的值就是username,value是jack,而是說/user/後面就跟著username,這裡的username隻是一個變量。
2.@QueryParam
該參數用於獲取Get請求中的查詢參數,他和上一個的區別是它是通過URI中的?符號來實現的。
比如:
@GET @Path("/user") @Produces("text/plain") public User getUser(@QueryParam("name") String name, @QueryParam("age") int age) { ...}
當url的請求是
http://localhost:8080/user?name=cesar&age=21
時,此時函數獲取的參數就是name=cesar而age=21;
3.@FormPara
顧名思義,是從Post請求的表單中獲取數據。
@POST @Consumes("application/x-www-form-urlencoded") publicvoid post(@FormParam("name") String name) { // Store the message }
4.默認參數值DefaultValue
當你希望在函數獲取參數時參數有一個默認值,那麼就可以使用該註釋,它的使用方法如下
@GET @Path("/user") @Produces("text/plain") public User getUser(@QueryParam("name") String name, @DefaultValue("26") @QueryParam("age") int age) { ...}
那麼當請求age參數時如果age沒有賦值,就會默認為26.
5.使用Map的參數@Context
在一個大型的server中,由於參數的多變,參數結構的調整很容易遇到問題,這時候就可以考慮使用@Context來進行註釋瞭。例子如下:
@GET public String get(@Context UriInfo ui) { MultivaluedMap<String, String> queryParams = ui.getQueryParameters(); MultivaluedMap<String, String> pathParams = ui.getPathParameters(); }
從例子中我們可以看出,其實Context就是其他幾個參數的集合而已,隻要熟練掌握瞭這幾種參數以及他們代表的意義,你就可以熟練的操作Jersey瞭!
Restful接口傳入多參數的問題及解決方案
結論:
restful風格的接口不支持多個參數
註:本文指的是通過json序列化參數的情況
1. 前置
一個定義用來測試的MyParam類
public class MyParam { private String str; private Integer integer; // 省略 getter和setter…… }
我在做測試的是用瞭Chrome的插件Advanced REST client,可以模擬瀏覽器發送各種請求,並自定義header和body。
測試的時候需要使用post方式,並在http請求header中加入
accept: application/json content-type: application/json
然後在htpp請求的Body中,輸入json格式的參數,如{“str”:”bb”,”integer”:3}。
以下是幾種多參數接口的形式,以及輸入參數,以及解析結果。
2. 第一種:兩個String參數
@POST @Path("demo") public Result function(String param1, String param2);
傳入的參數:
{"param1":"bb","param2":"cc"}
解析出來的參數:
param1: “{“param1″:”bb”,”param2″:”cc”}”
param2: “”
這樣的風格,傳輸過來的參數,讀取的時候會讀取request body中的inputStream,然後兩個參數循環解析,解析完第一個參數的時候,會關閉inputStream,第二個參數再去讀取inputStream的時候,讀取到的就是空。
這樣的話,傳入的參數全部會賦值給第一個String對象,而第二個String解析出來後就是空字符串。
3. 第二種:一個對象參數,一個String參數
對於 第一個參數是封裝對象的情況,能解析出來第一個對象,而第二個參數也是拿不到。
這種情況下不會報錯,隻是解析第一個對象的時候沒有問題,解析第二個String拿到的就是空字符串。
@POST @Path("demo") @Consumes({MediaType.JSON}) public Result function(MyParam myParam, String param);
傳入的參數:
{"str":"helo","integer":2},"string":"test"
解析出來的參數:
param1: 能正確解析對象myParam,其兩個屬性能正確賦值。
param2: “”
4. 第三種:一個String參數,一個對象參數
如果把兩個參數的位置交換,則會把傳入的參數全部解析給第一個String,而解析第二個對象的時候,由於拿到的數據是空,所以會報錯。如下:
@POST @Path("demo") public Result function(String param, MyParam myParam);
傳入的參數:
{"str":"helo","integer":2},"string":"test"
解析出來的參數:
param1: “{“str”:”helo”,”integer”:2},”string”:”test””
param2: 會報錯
5.解決方法
要解決傳入多個參數的問題,有幾個思路:
1. 封裝對象,把要傳的多個參數封裝成一個對象傳入
2. 在訪問路徑中嵌入變量,使用@PathVariable註解,在請求路徑中寫 “/demo/{1}/{2}”,然後在請求路徑中相應的位置替換為要穿的參數即可,這種也隻適用於包裝類,如String。
3. 改變請求的content type,使用content-type: application/x-www-form-urlencoded,這種使用form表單提交的形式,可以傳入兩個參數,要結合使用@FormParam註解
6.關於使用form形式傳入參數
接口的定義形式要修改
@POST @Path("demo") @Consumes({MediaType.APPLICATION_FORM_URLENCODED}) public Result function(@FormParam(value="string1")String string1, @FormParam(value="string2")String string2);
請求時,header參數要修改
accept: application/json content-type: application/x-www-form-urlencoded
請求Body中使用form形式
string1=wo&string2=kan
然後就可以正確解析到兩個參數的值
解析出來的參數:
string1: wo
string2: kan
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- 使用Spring處理x-www-form-urlencoded方式
- golang gin框架獲取參數的操作
- Vue之請求如何傳遞參數
- SpringMvc接受請求參數的幾種情況演示
- SpringBoot 設置傳入參數非必要的操作