前言
最近有專案需求是通過gitlab的api獲取其中的資料。來記錄一下我的踩坑的過程。
首先先嚐試了獲取users資料,即所有使用者的資料。
這裡是gitlab官方API文件 https://docs.gitlab.com/ee/ap...
這裡說一下我剛開始的做法和老師建議的做法。
最開始的做法
1. 獲取Admin access token
首先我們需要獲取gitlab的Admin access token, 並且在請求的時候附帶這個token,gitlab才能認證我們的身份並返回資料。
1.登入 GitLab。 2.登入後,點選右上角的頭像圖示然後選擇 Preferences。
3.在 access token 介面就可以新建token了。
當你是group的管理員之後,就可以通過該token獲取users了。
2.使用spring boot單元測試發起請求
這裡我使用了apache發起http請求,並使用了fastjson處理請求後所返回的json資料。
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.9</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
以下是我測試的程式碼。來解釋一下:
- 首先定義你的要請求的url,格式如程式碼。也可以看官方文件。
- 構建Http請求類,並設定引數。引數必須要有private_token。這裡我加的 without_project_bots可以過濾機器人user。
- 使用execute函式發起get請求,並接收返回的json資料。
- 從json陣列轉換成實體陣列
這樣就獲得了我們需要的資料。
@Test
void getUsers() throws IOException, URISyntaxException {
String url = "https://your gitlab address/api/v4/users";
CloseableHttpClient httpclients = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
// 設定引數資訊
URI uri = new URIBuilder(httpGet.getURI())
.addParameter("private_token", "your amind token")
.addParameter("without_project_bots", "true")
.build();
((HttpRequestBase) httpGet).setURI(uri);
// 發起請求
CloseableHttpResponse response = httpclients.execute(httpGet);
// 處理資料
HttpEntity httpEntity = (HttpEntity) response.getEntity();
String result = EntityUtils.toString(httpEntity,"UTF-8");
// 從json轉換成實體
final ObjectMapper objectMapper = new ObjectMapper();
User[] langList = objectMapper.readValue(result, User[].class);
logger.debug(String.valueOf(langList));
response.close();
}
期間我遇到的問題
1. java需要新增證照
由於我們發起的請求地址是HTTPS的,而https是對連結加了安全證照SSL的。
對方的介面需要特定的證照才能請求。如果伺服器中沒有相關連結的SSL證照,就會報sun.security.validator.ValidatorException錯誤。
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
最開始我是把證照新增到本地中的,新增方法大概參考瞭如下部落格
https://www.cnblogs.com/zoro-...
這樣就把證照新增到了本地的java金鑰庫中。
但是這樣只有本地能夠正常使用這個專案。因為在並沒有把證照新增到專案中。所以這也說明了這種方法並不普適。
所以我們需要把證照放在src/main/resourse中,部署https。下面我會說一下如何新增。
2. 沒有配置資料來源
Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]
由於我只是在單元測試中測試,專案剛初始化,並沒有連線資料庫,也就是並沒有配置資料來源。
所以因為沒有向 Spring Boot 傳遞足夠的資料來配置資料來源,導致發生了該報錯。
所以,如果我們暫時不需要資料來源,就可以使用exclude={DataSourceAutoConfiguration.class}自動配置。 這樣就可以解決報錯
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
public class NonlycodeApplication {
}
3. json資料的屬性多於實體的屬性
在我請求到資料後,可以看到gitlab給我們返回來的資料有很多。有theme_id, note,is_admin等資訊。
但是, 我定義的實體中目前只定義了幾條需要的資訊,比如id ,name,username等資訊。
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
private String email = "";
private Integer following = 0;
private Integer followers = 0;
private String name = "";
private String password = "yunzhi";
@Column(nullable = false, unique = true)
private String username;
在json轉化資料的時候,遇到這種情況就會報錯。並且報錯說:not marked as ignorable。
所以我們需要新增註釋,把不需要的資料給忽略掉。
我的解決方法是新增 @JsonIgnoreProperties(ignoreUnknown = true)
。
最後報錯消失。
@JsonIgnoreProperties(ignoreUnknown = true)
@Entity
public class User implements Serializable {
使用RestTemplate通過證照認證訪問https
傳統情況下在java程式碼裡訪問restful服務,一般使用Apache的HttpClient。如同我上面的程式碼。不過此種方法使用起來太過繁瑣。spring提供了一種簡單便捷的模板類來進行操作,這就是RestTemplate。
1. 獲取證照
我參考了這篇文章來生成自簽名證照。
https://www.baeldung.com/spri...
或者可以下載網站的證照,參考這篇文章來操作
https://fullstackdeveloper.gu...
把生成的檔案匯入到專案resourses/keystore中
2. 配置application.yml
填寫一下自己配置的password和alias別名等
server:
ssl:
key-store-type: PKCS12
key-store: classpath:keystore/baeldung.p12
key-store-password: changeit
key-alias: baeldung
port: 8443
spring:
security:
user:
name: root
password: 1234
4. 配置restTemplate
配置restTemplate,使其載入專案中的證照
- 新建CustomConfiguration類
- 重寫restTemplate()函式
注意一下自己的檔名,以及剛才自己設定的key-store密碼
@Configuration
public class CustomConfiguration {
@Bean
RestTemplate restTemplate() throws Exception {
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(new URL("file:src/main/resources/keystore/baeldung.p12"), "changeit".toCharArray()).build();
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);
HttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(socketFactory)
.build();
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(factory);
}
}
3. 編寫程式碼
controller層:
@RestController
@RequestMapping("user")
public class UserController {
@Autowired
UserService userService;
@GetMapping("/getUsers")
@JsonView(GetUsersJsonView.class)
public User[] getUsers() throws JsonProcessingException {
return this.userService.getUsers();
}
public class GetUsersJsonView {
}
}
service層:
注意填寫自己的url和token。 邏輯跟之前的程式碼差不多。
@Override
public User[] getUsers() throws JsonProcessingException {
String url = "https://your gitlab address /api/v4/users/" +
"?private_token={private_token}&without_project_bots={without_project_bots}";
final Map<String, String> variables = new HashMap<>();
variables.put("private_token", "your token");
variables.put("without_project_bots", "true");
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class, variables);
// 從json轉換成實體
final ObjectMapper objectMapper = new ObjectMapper();
User[] userList = objectMapper.readValue(response, User[].class);
return userList;
}
4. url訪問
可能是因為spring security, 需要登入。 我們輸入application.yml中配置好的賬號密碼
5. 結果
可能是jsonView沒配置好,頁面顯示空資訊。之後再弄一下。
但是經過打斷點列印, 顯示成果獲取到了gitlab中的users資訊。
總結
經過這次對gitlab API的請求嘗試,感覺自己對如何進行請求、如何處理返回的json資料有了更深的理解。同時也感覺自己對https,以及SSL證照等的理解還不足,之後還需要補一下相關知識。