官網 https://square.github.io/okhttp/
github地址 https://github.com/square/okhttp
okhttp4.x和okhttp3.x
4.x使用kotlin來編寫的
基本概念
Request
Request類封裝了請求報文信息:請求的Url地址、請求的方法(如GET、POST等)、各種請求頭(如Content-Type、Cookie)以及可選的請求體。一般通過內部類Request.Builder的鏈式調用生成Request對象。
Call
Call代表了一個實際的HTTP請求,它是連接Request和Response的橋樑,通過Request對象的newCall()方法可以得到一個Call對象。Call對象既支持同步獲取數據,也可以異步獲取數據。
執行Call對象的execute()方法,會阻塞當前線程去獲取數據,該方法返回一個Response對象。
執行Call對象的enqueue()方法,不會阻塞當前線程,該方法接收一個Callback對象,當異步獲取到數據之後,會回調執行Callback對象的相應方法。如果請求成功,則執行Callback對象的onResponse方法,並將Response對象傳入該方法中;如果請求失敗,則執行Callback對象的onFailure方法。
Response
Response類封裝了響應報文信息:狀態嗎(200、404等)、響應頭(Content-Type、Server等)以及可選的響應體。可以通過Call對象的execute()方法獲得Response對象,異步回調執行Callback對象的onResponse方法時也可以獲取Response對象。
目標明細
使用OkHttp執行get請求和帶參數的get請求;
使用OkHttp執行post請求、帶參數的post請求;
支持contentType爲none、application/json、form-data、application/x-www-form-urlencoded
圖從postman截取
代碼實現如下:
getUrl 方法: 用於拼接url、post或者get請求都可能會需要拼接url;url結尾?
後面的參數 Spring註解@requestParam獲取此參數;
Okhttp拼接功能蠻強大,沒有?會添加?拼接;有?會直接在後面添加參數。
curl -X GET "http://localhost:9099/requestDemo/getDemo?name=111&strDemo=222" -H "accept: */*"
getBody方法:用於拼接post請求的body內容;
@Slf4j
public class OkhttpUtils {
private static OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(6, TimeUnit.SECONDS).build();
private static final MediaType JSON = MediaType.parse("application/json");
private static final String MEDIATYPE_NONE = "none";
private static final String MEDIATYPE_JSON = "application/json";
private static final String MEDIATYPE_FORM = "form-data";
private static final String MEDIATYPE_FORM_URLENCODED = "application/x-www-form-urlencoded";
/**
* @Author JackZhou
* @Description 執行get請求
**/
public static String execRequest(String url, Map<String, String> headers){
Request.Builder requestBuilder = new Request.Builder().url(url);
if(headers != null && headers.size() >0 ){
headers.entrySet().stream().forEach(entry -> requestBuilder.header(entry.getKey(), entry.getValue()));
}
Request request = requestBuilder.url(url).build();
try {
Response response = okHttpClient.newCall(request).execute();
return response.body().string();
} catch (IOException e) {
log.info("執行http請求出錯,地址:{}", url, e);
return null;
}
}
/**
* @Author JackZhou
* @Description 執行post請求
**/
public static String execPostRequest(String url, Map<String, String> headers, RequestBody requestBody){
Request.Builder requestBuilder = new Request.Builder().url(url);
if(headers != null && headers.size() >0 ){
headers.entrySet().stream().forEach(entry -> requestBuilder.header(entry.getKey(), entry.getValue()));
}
Request request = requestBuilder.url(url).post(requestBody).build();
try {
Response response = okHttpClient.newCall(request).execute();
return response.body().string();
} catch (IOException e) {
log.info("執行http請求出錯,地址:{}", url, e);
return null;
}
}
/**
* @Author JackZhou
* @Description 得到post請求的RequestBody
**/
public static RequestBody getBody(String type, Map<String, String> formParam, String body){
switch (type) {
case MEDIATYPE_JSON:
if(StringUtils.isEmpty(body)){
RequestBody.create(null, "");
}
return RequestBody.create(JSON, body);
case MEDIATYPE_FORM:
MultipartBody.Builder formBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
if(formParam != null && formParam.size() >0 ){
formParam.entrySet().stream().forEach(entry -> formBuilder.addFormDataPart(entry.getKey(), entry.getValue()));
}
return formBuilder.build();
case MEDIATYPE_FORM_URLENCODED:
FormBody.Builder builder = new FormBody.Builder();
if(formParam != null && formParam.size() >0 ){
formParam.entrySet().stream().forEach(entry -> builder.add(entry.getKey(), entry.getValue()));
}
return builder.build();
case MEDIATYPE_NONE:
return RequestBody.create(null, "");
default:
throw new IllegalArgumentException("不支持的mediaType:" + type);
}
}
/**
* @Author JackZhou
* @Description 得到拼接後的url @RequestParam參數
**/
public static String getUrl(String url, Map<String, String> params){
HttpUrl.Builder builder = HttpUrl.parse(url).newBuilder();
if(params != null && params.size() > 0){
params.entrySet().stream().forEach(entry -> builder.addQueryParameter(entry.getKey(), entry.getValue()));
}
return builder.build().toString();
}
注意點,如果post請求的內容爲空,不能傳空的requestBody會報錯
java.lang.IllegalArgumentException: method POST must have a request body
#如果post請求的body和contentType爲空
RequestBody.create(null, "")
測試驗證
@Data
public class Person {
private String id;
private String name;
private int age;
}
@RestController
@Api(tags = "模擬不同的meidaType")
@RequestMapping(value = "/requestDemo")
public class MediaTypeController {
@ApiOperation("模擬普通get請求")
@RequestMapping(value = "/getDemo", method = RequestMethod.GET)
public String getDemo(@RequestParam(required = false) String name, @RequestParam(required = false) String strDemo){
return "success: " + name + ";strDemo:" + strDemo;
}
@ApiOperation("模擬普通post請求")
@RequestMapping(value = "/getPost", method = RequestMethod.POST)
public String postDemo(){
return "success";
}
@ApiOperation("模擬普通post 帶參數請求")
@RequestMapping(value = "/getPostParam", method = RequestMethod.POST)
public String postParamDemo(@RequestParam(required = false) String name, @RequestParam(required = false) String strDemo){
return "success:" + name;
}
@ApiOperation("模擬post xxx-form請求")
@RequestMapping(value = "/getPostModel", method = RequestMethod.POST)
public String postModelDemo(@ModelAttribute Person person){
if(person != null){
return "success:" + person.getName();
}else{
return "success";
}
}
@ApiOperation("模擬普通post 傳json請求")
@RequestMapping(value = "/getPostJson", method = RequestMethod.POST)
public String postJsonDemo(@RequestBody Person person){
if(person != null){
return "success:" + person.getName();
}else{
return "success";
}
}
@ApiOperation("模擬普通post form請求")
@RequestMapping(value = "/getPostForm", method = RequestMethod.POST)
public String postDemo(HttpServletRequest request){
System.out.println(request.getParameter("name"));
System.out.println(request.getParameter("strDemo"));
return "success";
}
}
偷懶,測試main方法;加到OkhttpUtils類中即可
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("name", "張三");
map.put("strDemo", "上山打老虎");
Map<String, String> pMap = new HashMap<>();
pMap.put("name", "張三");
pMap.put("id", "11111");
pMap.put("age", "111");
// 測試get請求、有參無參均可
// String getUrl = "http://localhost:9099/requestDemo/getDemo";
// log.info(execRequest(getUrl(getUrl, map), null));
// 測試基本的post url後面有參數或者沒有
// String postUrl = "http://localhost:9099/requestDemo/getPost";
// //String postUrl = "http://localhost:9099/requestDemo/getPostParam";
// log.info(execPostRequest(postUrl, null, getBody(MEDIATYPE_NONE, null, null)));
// log.info(execPostRequest(execRequest(getUrl(getUrl, map), null, getBody(MEDIATYPE_NONE, null, null)));
// 測試post的application/x-www-form-urlencoded 對應@ModelAttribute註解
// String postUrl = "http://localhost:9099/requestDemo/getPostModel";
// //log.info(execPostRequest(postUrl, null, getBody(MEDIATYPE_FORM_URLENCODED, null, null)));
// log.info(execPostRequest(postUrl, null, getBody(MEDIATYPE_FORM_URLENCODED, pMap, null)));
// 測試post的application/json 對應@RequestBody註解
// String postUrl = "http://localhost:9099/requestDemo/getPostJson";
// log.info(execPostRequest(postUrl, null, getBody(MEDIATYPE_JSON, null, "{ \"age\": 11, \"id\": \"sdsb111\", \"name\": \"張三\"}")));
// 測試post的form-data
// String postUrl = "http://localhost:9099/requestDemo/getPostForm";
// log.info(execPostRequest(postUrl, null, getBody(MEDIATYPE_FORM, map, null)));
}