【API知識】RestTemplate的使用

前言

  在某種狀況下,後臺服務可能須要訪問另外一臺服務器的REST接口。之前估計很多人用的都是HttpRequest類來着,結合Paser解析JSON格式的Body。如今Spring Boot的Web Starter就自帶了RestTemplate,直接用它的就行了。最好不要再往項目裏導新的依賴。這裏作了點整理,分享出來。發數據庫

簡單的請求

1、GET請求數組

案例以下:服務器

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<CustomClass>  responseEntity = restTemplate.getForEntity(url, CustomClass.class);
CustomClass response = responseEntity.getBody();

(1)getForEntity 顧名思義就是發送GET請求,並獲得一個對象app

(2)這裏的URL應該是完整的,即應該是這樣的格式:"http://域名:端口/xxx/yyy"ide

(3)CustomClass是你本身定義的類,tempalte會將請求響應的JSON格式的body解析成CustomClass。函數

(4)ResponseEntity是請求響應的結果,能夠獲取響應碼,以及最重要的響應Bodypost

注意:因爲RestTemplate是使用Jackson來進行映射的,而Jackson本質上是用setter/getter來實現的。其中JSON字符串轉對象須要setter,對象轉JSON字符串須要getter。這裏是字符轉對象,因此你定義的類必須有setter。this

2、POST請求url

案例以下:spa

...
restTemplate.postForEntity(url, ParamObject, Response.class);
...

基本操做同上,不過postForEntity的第二個參數是請求對象,底層會將其轉爲JSON字符存入請求Body中

傳輸form/data

1、普通的表單請求

//用MultiValueMap存儲表單數據
MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
param.add("param1","1232");
param.add("param2","12312");
//用HttpEntity進行包裝
HttpEntity<MultiValueMap<String,Object>> httpEntity = new HttpEntity<>(param);
//發送請求
ResponseEntity<Response> responseEntity = restTemplate.postForEntity(url, httpEntity, Response.class);

這就相對於提交了一個普通的表單

2、帶文件的表單請求

有時候咱們須要把本地文件經過Post請求發送給另外一個應用,能夠這麼作。而對方接收的時候就用@RequestParam("file") MultipartFile來接收。

MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
//FileSystemResource是一個包裝類,好統一處理
param.add("file", new FileSystemResource(new File(filePath)));
...

(1)網頁上經過表單上傳文件,默認標識符就是"file"

(2)通過FileSystemResource包裝後,RestTemplate會利用File對象的InputStream從磁盤中讀入文件內容,並寫入HTTP請求body中。

3、帶文件的表單請求——文件從客戶端而來(MultipartFile)

//file由客戶端上傳過來,直接轉發,不通過磁盤
@PostMapping("/some-url") 
public SomeResponse function(@RequestParam("file") MultipartFile file, ...) {
    ...
    MultiValueMap<String, Object> param = new LinkedMultiValueMap();
    param.add("file", new MultipartFileResource(file));
    ...
}

MultipartFileResource相似FileSystemResource

4、帶文件的表單請求——本地沒有文件,只有文件的文本內容

可能存在這種狀況,即你本地保存的是文本文件的內容,(如保存在數據庫中,用text存儲。由於這樣比較方便管理)而另外一個服務器須要以文件的形式接收你的文本內容。即它會用一個MultipartFile來接收。這時候首先你從數據庫中把文本內容讀出來,傳統數據庫存儲位置就在磁盤,這已是不小的開銷了,難道你還要把文本以文件的形式寫到磁盤再傳輸嗎?這種操做是很是愚蠢的。既然咱們已經知道請求本質上傳遞的是字節數組,那何不就仿造FileSystemResource寫一個適配類呢?

//該類與FileSystemResouce同父類
public class TextFeignFileResource extends AbstractResource {
    //文本的字節信息
    private byte[] bytes;
    //當前讀到的位置
    private int index = 0;
    //文件名
    private String filename;

    //構造函數須要兩個參數,一個是文件名,隨便取
    //另外一個就是文本內容,String類型足夠存文本的
    public TextFeignECLFileResource(String filename, String content) {
        this.filename = filename;
        this.bytes = content.getBytes();
    }

    @Override
    public String getDescription() {
        return null;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return new InputStream() {
            //注意這裏的返回值int是一個八位的字節的數值表示
            //並非讀取到的字節個數
            @Override
            public int read() throws IOException { 
                if (index >= bytes.length)
                    return -1; //返回-1是標準,表示讀取結束
                return bytes[index++];
            }
        };
    }

    @Override
    public boolean exists() {
        return true;
    }

    @Override
    public boolean isFile() {
        return true;
    }

    @Override
    public boolean isReadable() {
        return true;
    }

    @Override
    public long contentLength() throws IOException {
        return bytes.length;
    }

    @Override
    public String getFilename() {
        return filename;
    }
}

使用方式:

MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
param.add("file", new TextFeignFileResource("test.txt", "hello world"));

注意:這裏之因此能這麼作是由於普通的文本文件沒有文件頭等額外的描述信息

 19-05-16補充

 使用Jodd的Http API會更方便一點。

相關文章
相關標籤/搜索