Custom of using simple-http

Recently wrote a component to send a http request, the request is sent to achieve the overall use of Okhttp, just based on Okhttp done on the basis of the package again, and use the same mybatis only need to write interface can be, you can directly call the business layer and it can be integrated and spring. API can be used to call the third party or reptile.
maven dependence

        <dependency>
            <groupId>com.github.zw201913</groupId>
            <artifactId>simple-http</artifactId>
            <version>1.0.0.RELEASE</version>
        </dependency>

github address: the Simple-HTTP

springboot integration

1. Let's look at how direct and springboot integration:

import com.github.zw201913.simplehttp.annotation.EnableSimpleHttp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//开启SimpleHttp
@EnableSimpleHttp
@SpringBootApplication
public class SimpleHttpApplication {

    public static void main(String[] args) {
        SpringApplication.run(SimpleHttpApplication.class, args);
    }
}

After opening SimpleHttp, we first use it to access it http://www.baidu.com try:

@SimpleHttpService
public interface SimpleHttp {
    /**
     * 发送get请求访问http://www.baidu.com
     * @return
     */
    @Get("http://www.baidu.com")
    String baidu();
}

Next, we can call this interface uses:

@Service
public class TestService {
     // 在spring中使用SimpleHttp
    @Autowired private SimpleHttp simpleHttp;

    public String baidu() {
        return simpleHttp.baidu();
    }
}

See here, it should be very clear, our focus is how to write SimpleHttp Interface (ps: the interface name can easily take your own).

//如果想要url作为参数传入
@Get
String list(@Url String url);
//传入一个参数为id的字段
@Get
String find(@Url String url, @Field("id") Integer id);
//需要设置请求头的
@Get
String find(@Url String url, @Field("id") Integer id, @Header("Content-Type") String contentType);
//多个参数和请求头设置
@Get
String find(@Url String url, @Field Map<String, Object> params, @Header Map<String, String> headers);

If a custom object:

    //@Data是lombok的注解,可以避免手写get,set方法
    // 请求参数实体类
    @Data
    public class PageParam {
        private String search;
        private int page;
        private int size;
    }
    // 请求头实体类
    @Data
    public class RequestHeader {
        private String cookie;
        private String userAgent;
        private String host;
    }

@Get
String find(@Url String url, @Field PageParam params, @Header RequestHeader headers);

If the entity class name actually requested field name and different:

    // 请求参数实体类
    @Data
    public class PageParam {
        @Field("name")
        private String search;
        private int page;
        private int size;
    }
    // 请求头实体类
    @Data
    public class RequestHeader {
        private String cookie;
        @Header("User-Agent")
        private String userAgent;
        private String host;
    }

You can even write:

   @Data
    public class PageParamAndRequestHeader {
        @Field("name")
        private String search;
        @Field
        private int page;
        @Field
        private int size;
        @Header
        private String cookie;
        @Header("User-Agent")
        private String userAgent;
        @Header
        private String host;
    }
// 至于下面方法的参数修饰到底是使用@Field 还是@Header ,那就看你的心情了
@Get
String find(@Url String url, @Field PageParamAndRequestHeader paramsAndHeaders);

Of course, in addition to Get request, as well as Post, Put, Delete, Patch ...... there WebSocket

Upload a file and parameters:

// 带一个文件上传的,对应spring mvc里面的
// public User add(@RequestPart("user") User user, @RequestPart("image") MultipartFile[] image) 
@Post
String add(@Url String url, @Field("user") Map<String, Object> user, @Field("image") File file);

// 和上面接口一样,只不过把Map改成了自定义的User
@Post
String add(@Url String url, @Field("user")  User user, @Field("image") File file);

If a file is not enough:

// 对应的服务端接口:
// public User add(@RequestPart("user") User user, @RequestPart("image1") MultipartFile[] image1, @RequestPart("image2") MultipartFile[] image2) 
@Post
String add(@Url String url, @Field("user")  User user, @Field("image1") File[] file, @Field("image2") File[] file);

More interfaces, in addition to the file, a plurality of parameters are be the same, using a method analogous with the file.
If you do not need to upload files, and the server is @RequestBody:

// 默认是对应服务端的@RequestBody,且格式化方式是JSON
// 如果发现有File或File[]参数,会自动对应@RequestPart,且携带的其他参数格式化方式是JSON
// 对应服务端接口
// public User add(@RequestBody User user)
@Post
String add(@Url String url, @Field User user);

// 同上
@Post
String add(@Url String url, @Field Map<String,Object> user);

If you need to monitor progress of the upload file how to do?


import com.github.zw201913.simplehttp.core.http.ProgressListener;

// 添加ProgressListener上传进度监听器
@Post
String add(
            @Field("user") User user,
            @Field("image1") File[] file1,
            @Field("image2") File[] file2, ProgressListener progressListener);

As long as a transfer in progress listener object parameter, you can get the current schedule, for example:

ProgressListener progressListener = (totalLength, currentLength) -> {
                    int progress = (int) (100 * currentLength / totalLength);
                    System.out.println(progress + "%");
                }

Of course, there will be only the file upload progress bar.
You may also need to send an asynchronous request:

import okhttp3.Callback;

// 添加异步回调Callback对象,这个时候方法就不需要返回值了
@Post
void add(@Url String url, @Field User user, Callback callback);

E.g:

Callback callback = new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {}

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        if (response.isSuccessful()) {
                            String result = response.body().string();
                            System.out.println(result);
                        }
                    }
                })

A great possibility to request you to send the required data format than JSON, XML or whatever may be the data format

public interface RequestParamsHandler {

    String JSON_UTF8 = "application/json;charset=utf-8";

    /**
     * 处理请求参数
     *
     * @param params
     * @param files
     */
    RequestBody handle(Map<String, Object> params, Map<String, File[]> files);
}

Such as the need to request parameters into XML format, we just need to implement a custom RequestParamsHandler:

public class XMLRequestParamsHandler implements RequestParamsHandler {

        @Override
        public RequestBody handle(Map<String, Object> params, Map<String, File[]> files) {
            //实现将params转换成XML格式,并且返回一个RequestBody对象
            return null;
        }
    }
@Post(handler = XMLRequestParamsHandler.class)
String add(@Url String url, @Field User user)

In this case, we can send the XML data formatting requirements are requested.
In addition to the request parameters can customize the process, we also want to return the result can customize
the current default returns the result can be a void, String, Response, the three returned results are automatically handled without any special settings. If you need other than the return type, you need to customize ResponseHandler

public interface ResponseHandler {
    /**
     * 处理响应对象
     *
     * @param response
     * @param <T>
     * @return
     */
    <T> T handle(Response response);
}
    public class MyResponseHandler implements ResponseHandler {

        @Override
        public User handle(Response response) {
            //处理Response,将返回数据转换成指定对象
            return new User();
        }
    }

@Post
User add(@Url String url, @Field User user, ResponseHandler responseHandler)

If you want to customize OkHttpClient, you can achieve BaseOkHttpClientFactory:

public abstract class BaseOkHttpClientFactory {

    /** final是为了保持单例 */
    private final OkHttpClient client;

    public BaseOkHttpClientFactory() {
        this.client = httpClient();
    }

    /**
     * 留给子类实现
     *
     * @return
     */
    protected abstract OkHttpClient httpClient();

    /**
     * 获取创建好的OkHttpClient
     *
     * @return
     */
    public OkHttpClient okHttpClient() {
        return this.client;
    }
}
public class DefaultOkHttpClientFactory extends BaseOkHttpClientFactory {
    @Override
    protected OkHttpClient httpClient() {
        return new OkHttpClient();
    }
}

The above is a component of the default. Why Customize OkHttpClient, in order to achieve, for example Https or Request Broker.

public class HttpProxyOkHttpClientFactory extends BaseOkHttpClientFactory {
    @Override
    protected OkHttpClient httpClient() {
        OkHttpClient client = new OkHttpClient();
        // 实现请求代理
        return client;
    }
}
@Post(clientFactory = HttpProxyOkHttpClientFactory.class)
String add(@Url String url, @Field User user);

Finally, there WebSocket:

import okhttp3.WebSocketListener;

// 创建WebSocket,url是ws://echo.websocket.org
@Ws("ws://echo.websocket.org")
WebSocket newWebSocket(WebSocketListener listener);

// 自定义url创建WebSocket
@Ws
WebSocket newWebSocket(@Url String url, WebSocketListener listener);

Integrated spring

In fact, simple-http and mybatis as completely separate from the spring framework allows:

public class DefaultHttpServiceFactory implements HttpServiceFactory {

    /** 缓存代理对象 */
    private static final Map<Class<?>, Object> proxyCache = Maps.newConcurrentMap();

    /**
     * 获取代理对象
     *
     * @param type
     * @param <T>
     * @return
     */
    @Override
    public <T> T getSimpleHttpService(Class<T> type) {
        return cacheProxy(type);
    }

    /**
     * 缓存代理对象
     *
     * @param type
     * @param <T>
     * @return
     */
    private <T> T cacheProxy(Class<T> type) {
        T proxy = (T) proxyCache.get(type);
        if (Objects.isNull(proxy)) {
            proxy = new HttpProxyFactory<>(type).newInstance();
            proxyCache.put(type, proxy);
        }
        return proxy;
    }
}
public interface SimpleHttp {
    /**
     * 发送get请求访问http://www.baidu.com
     * @return
     */
    @Get("http://www.baidu.com")
    String baidu();
}


public class TestSimpleHttp {
     private DefaultHttpServiceFactory factory = new DefaultHttpServiceFactory();

    public static void main(String[] args) {
        SimpleHttp simpleHttp = factory.getSimpleHttpService(SimpleHttp.class)
        return simpleHttp.baidu();
    }
}

According to the above cases, to integrate and spring, we only need to DefaultHttpServiceFactory injected into the spring of IOC container, whether @Bean way or XML configuration:

import com.github.zw201913.simplehttp.core.DefaultHttpServiceFactory;

@Bean
public HttpServiceFactory httpServiceFactory(){
    return new DefaultHttpServiceFactory();
}

or

<bean id="httpServiceFactory" class="com.github.zw201913.simplehttp.core.DefaultHttpServiceFactory">
</bean>

Use:

@Service
public class TestService {
     @Autowired
     private DefaultHttpServiceFactory factory;

    public String baidu() {
        SimpleHttp simpleHttp = factory.getSimpleHttpService(SimpleHttp.class)
        return simpleHttp.baidu();
    }
}

These are the Simple-http simple to use.

Reproduced in: https: //www.jianshu.com/p/ea28e4d1f5c5

Guess you like

Origin blog.csdn.net/weixin_34183910/article/details/91064051