Okhttp基础使用和注意事项

基本概念

官网 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;

                       Okhttp拼接url功能不错,没有?会自动添加?;有?会直接在后面添加参数。

curl -X GET "http://localhost:9099/requestDemo/getDemo?name=111&strDemo=222" -H "accept: */*"

getBody方法:用于拼接post请求的body内容;以下是OkHttp的几种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();
    }

测试验证

@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)));
 
    }

注意事项

 1、如果post请求的内容为空,不能传空的requestBody会报错  

java.lang.IllegalArgumentException: method POST must have a request body 

### 添加以下代码

#如果post请求的body和contentType为空
RequestBody.create(null, "")

2、Response需要关闭

有些方法会关闭资源,有些不会,这一点要注意。

response.body().string(); //stirng里面会关闭资源
response.isSuccessful(); //如果判断是否 需要response.close()

3、推荐使用OkhttpClient单例

4、压缩支持

默认开启压缩支持,不需要手动设置(手动设置需要更多设置); 原理:使用拦截器,解析压缩数据

5、默认开启Keep-Alive;

猜你喜欢

转载自blog.csdn.net/Zzhou1990/article/details/106169157