springboot装配OkHttp组件
在SpringBoot应用中,发送Http通常我们使用RestTemplate,但有部分组件底层是使用OkHttp进行Http的操作,而且OKHttp也是一个很优秀的HTTP组件。
RestTempate的springboot封装参考:https://www.cnblogs.com/yangzhilong/p/6640207.html
application.yml
okhttp: connect-timeout-ms: 500 keep-alive-duration-sec: 5000 max-idle: 100 read-timeout-ms: 500 write-timeout-ms: 500
Configuration:
import java.util.concurrent.TimeUnit; import javax.annotation.Resource; import javax.validation.constraints.NotNull; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; import com.longge.gateway.util.OkHttpUtils; import lombok.Getter; import lombok.Setter; import okhttp3.ConnectionPool; import okhttp3.OkHttpClient; /** * @author roger yang * @date 9/16/2019 */ public class OkHttpConfiguration { @Resource private OkHttpConfig okHttpConfig; @Bean public OkHttpClient okHttpClient() { OkHttpClient client = new OkHttpClient.Builder() .retryOnConnectionFailure(false) .connectionPool(pool()) .connectTimeout(okHttpConfig.getConnectTimeoutMs(), TimeUnit.MILLISECONDS) .readTimeout(okHttpConfig.getReadTimeoutMs(), TimeUnit.MILLISECONDS) .writeTimeout(okHttpConfig.getWriteTimeoutMs(),TimeUnit.MILLISECONDS) .build(); OkHttpUtils.setOkHttpClient(client); return client; } @Bean public ConnectionPool pool() { return new ConnectionPool(okHttpConfig.getMaxIdle(), okHttpConfig.getKeepAliveDurationSec(), TimeUnit.SECONDS); } @Component @ConfigurationProperties(prefix = "okhttp") @Getter @Setter @Validated static class OkHttpConfig { @NotNull private Long connectTimeoutMs; @NotNull private Long readTimeoutMs; @NotNull private Long writeTimeoutMs; @NotNull private Integer maxIdle; @NotNull private Long keepAliveDurationSec; } }
Util帮助类:
import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Map; import java.util.Objects; import com.alibaba.fastjson.JSONObject; import lombok.NonNull; import okhttp3.Callback; import okhttp3.FormBody; import okhttp3.Headers; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; /** * 参数中Callback表示发送异步请求 * @author roger yang * @date 9/16/2019 */ public class OkHttpUtils { private static OkHttpClient okHttpClient; public static void setOkHttpClient(OkHttpClient client) { okHttpClient = client; } /** * GET Method begin--------------------------------- */ public static <T> T get(@NonNull String url, Class<T> clasz) { return get(url, null, null, clasz); } public static void get(@NonNull String url, Callback callback) { get(url, null, null, callback); } public static <T> T get(@NonNull String url, Map<String, String> queryParameter, Class<T> clasz) { return get(url, null, queryParameter, clasz); } public static void get(@NonNull String url, Map<String, String> queryParameter, Callback callback) { get(url, null, queryParameter, callback); } public static <T> T get(@NonNull String url, Map<String, String> headerParameter, Map<String, String> queryParameter, Class<T> clasz) { Request request = processGetParameter(url, headerParameter, queryParameter); try (Response resp = okHttpClient.newCall(request).execute();) { return processResponse(resp, clasz); } catch (Exception e) { throw new RuntimeException(e); } } public static void get(@NonNull String url, Map<String, String> headerParameter, Map<String, String> queryParameter, Callback callback) { Request request = processGetParameter(url, headerParameter, queryParameter); okHttpClient.newCall(request).enqueue(callback); } private static Request processGetParameter(String url, Map<String, String> headerParameter, Map<String, String> queryParameter) { Request.Builder builder = new Request.Builder(); if (!isEmptyMap(headerParameter)) { builder.headers(Headers.of(headerParameter)); } if (isEmptyMap(queryParameter)) { builder.url(url); } else { boolean hasQuery = false; try { hasQuery = new URL(url).getQuery().isEmpty(); } catch (MalformedURLException e) { throw new RuntimeException("url is illegal"); } StringBuilder sb = new StringBuilder(url); if (!hasQuery) { sb.append("?1=1"); } queryParameter.forEach((k, v) -> { sb.append("&").append(k).append("=").append(v); }); builder.url(sb.toString()); } return builder.build(); } /** * POST Method With JSON begin--------------------------------- */ public static <T> T postJson(@NonNull String url, Class<T> clasz) { return postJson(url, null, null, clasz); } public static void postJson(@NonNull String url, Callback callback) { postJson(url, null, null, callback); } public static <T> T postJson(@NonNull String url, Map<String, String> headerParameter, Class<T> clasz) { return postJson(url, headerParameter, null, clasz); } public static void postJson(@NonNull String url, Map<String, String> headerParameter, Callback callback) { postJson(url, headerParameter, null, callback); } public static <T> T postJson(@NonNull String url, Map<String, String> headerParameter, Object bodyObj, Class<T> clasz) { Request request = processPostJsonParameter(url, headerParameter, bodyObj); try (Response resp = okHttpClient.newCall(request).execute();) { return processResponse(resp, clasz); } catch (Exception e) { throw new RuntimeException(e); } } public static void postJson(@NonNull String url, Map<String, String> headerParameter, Object bodyObj, Callback callback) { Request request = processPostJsonParameter(url, headerParameter, bodyObj); okHttpClient.newCall(request).enqueue(callback); } private static Request processPostJsonParameter(String url, Map<String, String> headerParameter, Object bodyObj) { Request.Builder builder = new Request.Builder().url(url); if(!Objects.isNull(bodyObj)) { RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), JSONObject.toJSONString(bodyObj)); builder.post(body); } else { RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), "{}"); builder.post(body); } if (!isEmptyMap(headerParameter)) { builder.headers(Headers.of(headerParameter)); } return builder.build(); } /** * POST Method With Form begin--------------------------------- */ public static <T> T postForm(@NonNull String url, Class<T> clasz) { return postForm(url, null, null, clasz); } public static void postForm(@NonNull String url, Callback callback) { postForm(url, null, null, callback); } public static <T> T postForm(@NonNull String url, Map<String, String> headerParameter, Class<T> clasz) { return postForm(url, headerParameter, null, clasz); } public static void postForm(@NonNull String url, Map<String, String> headerParameter, Callback callback) { postForm(url, headerParameter, null, callback); } public static <T> T postForm(@NonNull String url, Map<String, String> headerParameter, Map<String, String> parameters, Class<T> clasz) { Request request = processPostFormParameter(url, headerParameter, parameters); try (Response resp = okHttpClient.newCall(request).execute();) { return processResponse(resp, clasz); } catch (Exception e) { throw new RuntimeException(e); } } public static void postForm(@NonNull String url, Map<String, String> headerParameter, Map<String, String> parameters, Callback callback) { Request request = processPostFormParameter(url, headerParameter, parameters); okHttpClient.newCall(request).enqueue(callback); } private static Request processPostFormParameter(String url, Map<String, String> headerParameter, Map<String, String> parameters) { Request.Builder builder = new Request.Builder().url(url); if(!Objects.isNull(parameters)) { FormBody.Builder formBuilder = new FormBody.Builder(); parameters.forEach((k, v) -> { formBuilder.add(k, v); }); builder.post(formBuilder.build()); } if (!isEmptyMap(headerParameter)) { builder.headers(Headers.of(headerParameter)); } return builder.build(); } @SuppressWarnings("unchecked") private static <T> T processResponse(Response resp, Class<T> clasz) throws IOException { if (resp.isSuccessful()) { if (Objects.equals(Void.class, clasz)) { return null; } String respStr = resp.body().string(); if(Objects.equals(String.class, clasz)) { return (T)respStr; } return JSONObject.parseObject(respStr, clasz); } return null; } private static boolean isEmptyMap(Map<? extends Object, ? extends Object> map) { return Objects.isNull(map) || map.isEmpty(); } }
GitHub地址:https://github.com/yangzhilong/new-gateway-test.git
如果想要OkHttp的装配是非自动的,可以采用自定义@EnableXX注解来实现。
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.context.annotation.Import; import com.longge.gateway.configuration.OkHttpConfiguration; /** * @author roger yang * @date 9/16/2019 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(OkHttpConfiguration.class) public @interface EnableOkHttp { }
然后把OkHttpConfiguration类的@Configuration注解去掉,当你要用时在启动类加上@EnableOkHttp即可。