Skip to main content
Version: Next

HTTP Body

POSTPUT等请求方法中,通常使用 HTTP 请求体进行传输数据。在 Forest 中有多种方式设置请求体数据。

@Body 注解#

您可以使用@Body注解修饰参数的方式,将传入参数的数据绑定到 HTTP 请求体中。

@Body注解修饰的参数一定会绑定到请求体中,不用担心它会出现在其他地方

/** * 默认body格式为 application/x-www-form-urlencoded,即以表单形式序列化数据 */@Post(    url = "http://localhost:/user",    headers = {"Accept:text/plain"})String sendPost(@Body("username") String username,  @Body("password") String password);

表单格式#

上面使用 @Body 注解的例子用的是普通的表单格式,也就是contentType属性为application/x-www-form-urlencoded的格式,即contentType不做配置时的默认值。

表单格式的请求体以字符串 key1=value1&key2=value2&...&key{n}=value{n} 的形式进行传输数据,其中value都是已经过 URL Encode 编码过的字符串。


/** * contentType属性设置为 application/x-www-form-urlencoded 即为表单格式, * 当然不设置的时候默认值也为 application/x-www-form-urlencoded, 也同样是表单格式。 * 在 @Body 注解的 value 属性中设置的名称为表单项的 key 名, * 而注解所修饰的参数值即为表单项的值,它可以为任何类型,不过最终都会转换为字符串进行传输。 */@Post(    url = "http://localhost:8080/user",    contentType = "application/x-www-form-urlencoded",    headers = {"Accept:text/plain"})String sendPost(@Body("key1") String value1,  @Body("key2") Integer value2, @Body("key3") Long value3);

调用后产生的结果可能如下:

POST http://localhost:8080/hello/userHEADER:    Content-Type: application/jsonBODY:    key1=xxx&key2=1000&key3=9999

@Body注解修饰的参数为一个对象,并注解的value属性不设置任何名称的时候,会将注解所修饰参数值对象视为一整个表单,其对象中的所有属性将按 属性名1=属性值1&属性名2=属性值2&...&属性名{n}=属性值{n} 的形式通过请求体进行传输数据。

/** * contentType 属性不设置默认为 application/x-www-form-urlencoded * 要以对象作为表达传输项时,其 @Body 注解的 value 名称不能设置 */@Post(    url = "http://localhost:8080/hello/user",    headers = {"Accept:text/plain"})String send(@Body User user);

调用后产生的结果如下:

POST http://localhost:8080/hello/userHEADER:    Content-Type: application/jsonBODY:    username=foo&password=bar

JSON格式#

@JSONBody注解#

发送JSON非常简单,只要用@JSONBody注解修饰相关参数就可以了。

@Post("/register")String registerUser(@JSONBody MyUser user);
@Post("/test/json")String postJsonMap(@JSONBody Map mapObj);

@Body注解 + contentType#

除了@JSONBody注解,使用@Body注解也可以,只要将contentType属性或Content-Type请求头指定为application/json便可。

@Post(    url = "http://localhost:8080/hello/user",    contentType = "application/json")String send(@Body User user);

调用后产生的结果如下:

POST http://localhost:8080/hello/userHEADER:    Content-Type: application/jsonBODY:    {"username": "foo", "password": "bar"}

XML格式#

@XMLBody注解#

发送XML也非常简单,只要用@XMLBody注解修饰相关参数就可以了。

@Post(url = "/message")String sendXmlMessage(@XMLBody MyMessage message);
@Post(url = "/test/xml")String postXmlBodyString(@XMLBody String xml);

@Body注解 + contentType + filter#

使用@Body注解发送XML数据较为特殊,除了指定contentType属性或Content-Type请求头为application/xml外,还需要设置@Bodyfilter属性为xml

@Post(    url = "http://localhost:8080/hello/user",    contentType = "application/xml")String send(@Body(filter = "xml") User user);

此外,这里的User对象也要绑定JAXB注解:

@XmlRootElement(name = "misc")public User {
    private String usrname;
    private String password;
    public String getUsername() {        return username;    }
    public void setUsername(String username) {        this.username = username;    }
    public String getPassword() {        return password;    }
    public void setPassword(String password) {        this.password = password;    }}

调用传入User对象后的结果如下:

POST http://localhost:8080/hello/userHEADER:    Content-Type: application/xmlBODY:    <misc><username>foo</username><password>bar</password></misc>

data 属性#

您也可以通过@Request、以及@Get@Post等请求注解的data属性把数据添加到请求体。需要注意的是只有当typePOSTPUTPATCH这类 HTTP Method 时,data属性中的值才会绑定到请求体中,而GET请求在有些情况会绑定到url的参数中。

具体type属性和data属性数据绑定位置的具体关系如下表:

typedata属性数据绑定位置支持的contentTypeContent-Type请求头
GETurl参数部分只有application/x-www-form-urlencoded
POST请求体任何contentType
PUT请求体任何contentType
PATCH请求体任何contentType
HEADurl参数部分只有application/x-www-form-urlencoded
OPTIONSurl参数部分只有application/x-www-form-urlencoded
DELETEurl参数部分只有application/x-www-form-urlencoded
TRACEurl参数部分只有application/x-www-form-urlencoded

data属性在POST请求中绑定请求体

public interface MyClient {
    @Request(            url = "http://localhost:8080/hello/user",            type = "post",            data = "username=foo&password=bar",            headers = {"Accept:text/plain"}    )    String dataPost();}

该接口调用后所实际产生的 HTTP 请求如下:

POST http://localhost:8080/hello/userHEADER:    Accept:text/plainBODY:    username=foo&password=bar

data属性中进行数据绑定:

public interface MyClient {
    /**     * 这里 data 属性中设置的字符串内容会绑定到请求体中     * 其中 {0} 和 {1} 为参数序号绑定,会将序号对应的参数绑定到字符串中对应的位置     * {0} 会替换为 username 的值,{1} 会替换为 password 的值     */    @Request(            url = "http://localhost:8080/hello/user",            type = "post",            data = "username={0}&password={1}",            headers = {"Accept:text/plain"}    )    String dataPost(String username, String password);}
提示

其中{数字}的语法用到了《参数序号引用

如果调用方代码如下所示:

myClient.dataPost("foo", "bar");

实际产生的 HTTP 请求如下:

POST http://localhost:8080/hello/userHEADER:    Accept: text/plainBODY:    username=foo&password=bar

您可以直接把 JSON 数据加入到请求体中,其中header设置为Content-Type: application/json

public interface MyClient {
    @Request(            url = "http://localhost:8080/hello/user",            type = "post",            data = "{\"username\": \"${0}\", \"password\": \"${1}\"}",            headers = {"Content-Type: application/json"}    )    String postJson(String username, String password);}

如果调用方代码如下所示:

myClient.postJson("foo", "bar");

实际产生的 HTTP 请求如下:

POST http://localhost:8080/hello/userHEADER:    Content-Type: application/jsonBODY:    {"username": "foo", "password": "bar"}

把 XML 数据加入到请求体中,其中header设置为Content-Type: application/json

public interface MyClient {
    @Request(            url = "http://localhost:8080/hello/user",            type = "post",            data = "<misc><username>${0}</username><password>${1}</password></misc>",            headers = {"Content-Type: application/xml"}    )    String postXml(String username, String password);}

如果调用方代码如下所示:

myClient.postXml("foo", "bar");

实际产生的 HTTP 请求如下:

POST http://localhost:8080/hello/userHEADER:    Content-Type: application/xmlBODY:    <misc><username>foo</username><password>bar</password></misc>