1. 程式人生 > >Spring Boot 2關於http介面呼叫(6)

Spring Boot 2關於http介面呼叫(6)

使用自定義HttpClientProxy

這裡其實是參考FeignClient的功能,實現自己的代理包裝類。因為FeignClient封裝的太好,功能很強大,但是有時候想實現一點特殊的功能,改造起來很麻煩。

定義自己的FeignClient註解

@Target(TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface HttpClientEx {
    @AliasFor("hostName")
    String value() default "";

    /**
     * 主機名http://www.baidu.com
     *
     * @return
     */
    @AliasFor("value")
    String hostName() default "";

    /**
     * http請求資料組裝
     *
     * @return
     */
    Class<HttpRequestBuilder> config() default HttpRequestBuilder.class;
}

定義自己的RequestMapping註解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMappingEx {
    @AliasFor("name")
    String value() default "";

    /**
     * 介面名a/b/c
     *
     * @return
     */
    @AliasFor("value")
    String name() default "";

    /**
     * 請求方法
     *
     * @return
     */
    HttpMethod method() default HttpMethod.GET;

    /**
     * contentType
     *
     * @return
     */
    String contentType() default MediaType.APPLICATION_JSON_UTF8_VALUE;

    /**
     * 請求頭a=b
     *
     * @return
     */
    String[] headers() default {};

    /**
     * 擴充套件引數a=b
     *
     * @return
     */
    String[] params() default {};
}

自定義HttpClientProxy,用於解析自定義的兩個註解

public final class HttpClientProxy<T> implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Class clz = method.getDeclaringClass();
        if (clz != null) {
            HttpClientEx typeAnno = (HttpClientEx) (clz.getAnnotation(HttpClientEx.class));
            RequestMappingEx methodAnno = method.getAnnotation(RequestMappingEx.class);
            //......
        }
        return null;
    }
}	

自定義HttpClientFactory,通過Proxy構造一個例項

@SuppressWarnings("unchecked")
public static <T> T getBean(Class<T> clz) throws IllegalArgumentException {
    return (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[]{clz}, new HttpClientProxy<T>());
}

定義介面

@HttpClientEx(hostName = "http://localhost:9999")
public interface IHelloService {
    @RequestMappingEx(name = "demo/hello", method = HttpMethod.GET, headers = {"xxx=123"})
    HttpRspDTO<String> demoHello(@RequestParam(value = "msg") String msg);

    @RequestMappingEx(name = "demo/hello", method = HttpMethod.POST, headers = {"xxx=123"})
    HttpRspDTO<String> demoHello(@RequestBody Map<String, Object> reqMap);
}

單元測試

    @Test
    public void test1() {
        long begin = System.currentTimeMillis();

        IHelloService testService = HttpClientFactory.getBean(IHelloService.class);

        long end = System.currentTimeMillis();
        System.out.println("*****構造物件消耗時間(秒):" + (end - begin) / 1000.0);
        begin = System.currentTimeMillis();

        HttpRspDTO<String> rspDTO = testService.demoHello("張三");

        end = System.currentTimeMillis();
        System.out.println("*****查詢資料消耗時間(秒):" + (end - begin) / 1000.0);
        System.out.println(rspDTO);

        begin = System.currentTimeMillis();
        Map<String, Object> paraMap = new HashMap<String, Object>();
        paraMap.put("msg", "這是一條測試資料");

        rspDTO = testService.demoHello(paraMap);
        end = System.currentTimeMillis();
        System.out.println("*****查詢資料消耗時間(秒):" + (end - begin) / 1000.0);
        System.out.println(rspDTO);
    }