---
title: 'Spring Boot Webclient and gson'
disqus: hackmd
---
###### tags: `SpringBoot`
Spring Boot Webclient
===
[TOC]
## 筆記目的
了解如何使用webclient 套件去打API,簡單來說,你使用postman可以透過get request或是 post request去取得某些資源,而這些資源常常是所謂的**json**格式的資料,我們要如何不使用postman,而使用後端程式去取得url上的**json**資料後,我們要把它存成**javabean**
* [stackoverflow](https://stackoverflow.com/questions/48828603/how-to-create-request-with-parameters-with-webflux-webclient/52013826)
## 思路方向
其實分成兩個部份來思考,第一個部分是給定URL後,怎麼把資源給get回來?第二部分則是取回來的資源,型態是甚麼,又需要怎麼把他給變成Javabean?
變成JAVAbean最大的好處就是可以直接`get`還有`set`去把它做取值還有變更值的動作,而且也可以省掉一些使用其他非gson套件的錯誤
非常簡單的說我們做的事情可以歸納如下:某個url上面有json資料,我們用webclient套件拿到,並且把她轉換成String,最後在透過gson套件,把String轉換成JAVAbean。
**pom.xml**
```xml=
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20210307</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.2</version>
</dependency>
```
## 設計BEAN
先把JAVABEAN給設計出來,設計的方式要取決於,你的資源的樣子
舉例而言,我的資源長這樣
```json
{
"access_token": "ya29.a0ARrdaM8zl28w8Cfke6aYXcp2CjO5NDboDITXSHC8YQukR8_c946QXVgAHukIJV-MUPeZkhRFl_kpF4RaUWp9FZZyG9XkjSTBEUQ4SSETRewRlYKg9zdwd5zYVzH8z2O-rXU4k532TDy-H9im5-zCsUTqzFTxRA",
"expires_in": 3599,
"scope": "https://www.googleapis.com/auth/drive",
"token_type": "Bearer"
}
```
那JAVABean就要長這樣
```java=
package com.example.value.bean;
public class GoogleAccessTokenBean {
private String access_token;
private String expires_in;
private String scope;
private String token_type;
public GoogleAccessTokenBean() {
// super();
// TODO Auto-generated constructor stub
}
public GoogleAccessTokenBean(String access_token, String expires_in, String scope, String token_type) {
super();
this.access_token = access_token;
this.expires_in = expires_in;
this.scope = scope;
this.token_type = token_type;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getExpires_in() {
return expires_in;
}
public void setExpires_in(String expires_in) {
this.expires_in = expires_in;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getToken_type() {
return token_type;
}
public void setToken_type(String token_type) {
this.token_type = token_type;
}
}
```
## 取得資源
### Tool Class
```java=
package com.example.value;
import org.springframework.web.reactive.function.client.WebClient;
public class WebclientTool {
public static String getJsonFromUrl(String url) {
WebClient client = WebClient.create();
String responseSpec = client.post()
.uri(url)
.retrieve().bodyToMono(String.class).block();
return responseSpec;
}
}
```
> 要注意的地方在於我使用client.post代表是post request,如果想要換成
### Main Class
```java=
package com.example.value;
import org.json.JSONObject;
import org.springframework.web.reactive.function.client.WebClient;
import com.example.value.bean.GoogleAccessTokenBean;
import com.google.gson.Gson;
public class GetToken {
public static void main(String[] args) {
String Accesstokenurl="XXXXXXXXXXXXXXX";
String Accesstoken=WebclientTool.getJsonFromUrl(Accesstokenurl);
Gson gson = new Gson();
GoogleAccessTokenBean data = gson.fromJson(Accesstoken, GoogleAccessTokenBean.class);
String token=data.getAccess_token();
System.out.println("mytoken from gson"+":"+token);
JSONObject object = new JSONObject(Accesstoken);
// System.out.println(object.toString());
// System.out.println(object.get("token_type"));
String tokenJson = String.valueOf(object.get("access_token")) ;
System.out.println("mytoken from JSONObject"+":"+tokenJson);
// System.out.println(joke);
}
}
```
## 簡單的範例,根本文關係不大
> 但這個範例可以直接run
### Main Class
```java=
package com.example.value;
import org.springframework.web.reactive.function.client.WebClient;
public class GetJoke {
public static void main(String[] args) {
WebClient client = WebClient.create();
WebClient.ResponseSpec responseSpec = client.get()
.uri("https://v2.jokeapi.dev/joke/Any")
.retrieve();
String responseBody = responseSpec.bodyToMono(String.class).block();
System.out.println(responseBody);
}
}
```
### result
```json=
{
"error": false,
"category": "Dark",
"type": "twopart",
"setup": "I told my psychiatrist I got suicidal tendencies.",
"delivery": "He said from now on I have to pay in advance.",
"flags": {
"nsfw": false,
"religious": false,
"political": false,
"racist": false,
"sexist": false,
"explicit": false
},
"id": 93,
"safe": false,
"lang": "en"
}
```
## 複雜的範例


## 遇到的問題
1. 資料被切斷

2. [passing URI Parameters (path parameters, and query parameters) in a WebClient Requests.](https://www.amitph.com/spring-webclient-request-parameters/)
3. 接回來之後怎麼轉成物件?
5. set header?
6. logic string to json,json to object?
## 資料太長怎辦
```java=
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(16 *1024 * 1024)).build();
WebClient webClient = WebClient.builder().exchangeStrategies(exchangeStrategies).build();
String listCampaignFromAllieUrl="http://ai-ext.allproducts.com/Allie/api/optimizationList?platform=Google&status=ACTIVE";
String responseSpec = webClient.post().uri(listCampaignFromAllieUrl).retrieve().bodyToMono(String.class).block();
System.out.println(responseSpec.length());
System.out.println(responseSpec);
```