文档章节

http-invoker

陈孝杰
 陈孝杰
发布于 2017/09/23 17:33
字数 1753
阅读 162
收藏 0

花了一点时间,包装了下httpclient,填了常见的坑。

有兴趣的戳下方链接~~

https://github.com/chenxiaojie/http-invoker

基于apache httpclient的轻量http请求

特性

  1. 封装了httpclient, 仅暴露常用的配置, 将常见的坑填上
  2. 接口设计参考jsoup http, 十分便捷的请求让人耳目一新
  3. 支持所有的请求方式, GET,POST,PUT,DELETE,PATCH,HEAD,OPTIONS,TRACE
  4. 可以像rpc请求一样发http请求, 代码更加规范稳定, 易于管理
  5. 出参入参对json极为友好, 自动解析返回对象to pojo
  6. 当返回值为HttpResult时, 调用失败也不会抛出异常. GET请求不建议使用HttpResult, 非GET如POST/PUT/DELETE请求都建议使用HttpResult
  7. 支持返回值取jsonPath, 例如:msg.user.id/msg.user[1].id 参考测试包下com.chenxiaojie.http.invoker.test.http.test.ResultJsonPathTest
  8. 支持设计重试次数, 建议get请求都有重试机制, 参考测试包下com.chenxiaojie.http.invoker.test.http.test.RetryTest
  9. 支持上传各种类型的文件, 支持File/InputStream/byte[]/base64上传, 参考测试包下com.chenxiaojie.http.invoker.test.http.test.UploadFileTest
  10. 支持@PathVariable 如 http://.com/{key}/info -> http://.com/xiaojie.chen/info, 参考测试包下com.chenxiaojie.http.invoker.test.http.test.SimpleTest
  11. 支持请求拦截器和自定义httpclient, 参考com.chenxiaojie.http.invoker.test.http.test.CustomHttpClientTest

添加依赖

<dependency>
    <groupId>com.chenxiaojie</groupId>
    <artifactId>http-invoker</artifactId>
    <version>1.0.1</version>
</dependency>

如果您的项目中有依赖以下包,请指定以下版本或高于以下版本

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.1</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.4.3</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
    <version>4.5.1</version>
</dependency>
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.9</version>
</dependency>

快速入门

http-invoker-demo-web module是专门用于测试, 运行以下代码时, 请先启动这个web项目

使用HttpInvoker, 参考测试包下com.chenxiaojie.http.invoker.test.httpinvoker.HttpInvokerTest

public class HttpInvokerTest {

    @Test
    public void testGet() {
        HttpInvoker.Response response = HttpInvoker.builder()
                .uri(Consts.URL + "/simple/1")
                .data("employeeId", "00160041")
                .data(ImmutableMap.of("employeeName", "陈孝杰1"))
                .data("ad", "xiaojie.chen", "ad", "xiaojie.chen1")
                .method(HttpMethod.GET)
                .execute();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Test
    public void testGet2() {
        HttpInvoker.Response response = HttpInvoker.builder()
                .uri(Consts.URL + "/simple/2")
                .data("employeeId", "00160042")
                .data(ImmutableMap.of("employeeName", "陈孝杰2"))
                .data("ad", "xiaojie.chen", "ad", "xiaojie.chen2")
                .get();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void testGet3() {
        thrown.expect(HttpRequestException.class);

        HttpInvoker.Response response = HttpInvoker.builder(HttpClientBuilder.builder().followRedirects(true).build())
                .uri(Consts.URL + "/redirect/loop")
                .get();

        response.log();
    }

    @Test
    public void testPost() {
        HttpInvoker.Response response = HttpInvoker.builder()
                .uri(Consts.URL + "/simple/3")
                .data("employeeId", "00160043")
                .data(ImmutableMap.of("employeeName", "陈孝杰3"))
                .data("ad", "xiaojie.chen", "ad", "xiaojie.chen3")
                .post();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Test
    public void testPost2() {
        UserLoginModel userLoginModel = new UserLoginModel();
        userLoginModel.setLoginId(5);
        userLoginModel.setEmployeeId("0016004");
        userLoginModel.setEmployeeName("陈孝杰");
        userLoginModel.setAd("xiaojie.chen");

        HttpInvoker.Response response = HttpInvoker.builder()
                .uri(Consts.URL + "/simple?employeeName=employeeName陈孝杰")
                .data("ad", "xiaojie.chen", "ad", "xiaojie.chen3")
                .json(JSON.toJSONString(userLoginModel))
                .post();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Test
    public void testPost3() {
        InputStream in = Thread.currentThread().getClass().getResourceAsStream("/logo.png");
        InputStream in2 = Thread.currentThread().getClass().getResourceAsStream("/logo.png");
        HttpInvoker.Response response = HttpInvoker.builder()
                .uri(Consts.URL + "/file")
                .data("employeeId", "00160043")
                .data(ImmutableMap.of("employeeName", "陈孝杰3"))
                .data("ad", "xiaojie.chen", "ad", "xiaojie.chen3")
                .data("fileinput", "attachment.png", in)
                .data("fileinput2", "attachment2.png", in2)
                .post();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Test
    public void testPut() {

        UserLoginModel userLoginModel = new UserLoginModel();
        userLoginModel.setEmployeeId("0016004");
        userLoginModel.setEmployeeName("陈孝杰");
        userLoginModel.setAd("xiaojie.chen");

        HttpInvoker.Response response = HttpInvoker.builder()
                .uri(Consts.URL + "/simple/1")
                .json(JSON.toJSONString(userLoginModel))
                .put();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Test
    public void testPatch() {

        UserLoginModel userLoginModel = new UserLoginModel();
        userLoginModel.setEmployeeId("0016004");
        userLoginModel.setEmployeeName("陈孝杰");
        userLoginModel.setAd("xiaojie.chen");

        HttpInvoker.Response response = HttpInvoker.builder()
                .uri(Consts.URL + "/simple/2")
                .json(JSON.toJSONString(userLoginModel))
                .patch();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Test
    public void testDelete() {
        HttpInvoker.Response response = HttpInvoker.builder()
                .uri(Consts.URL + "/simple/1")
                .data("aa", "陈孝杰")
                .delete();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Test
    public void testHead() {
        HttpInvoker.Response response = HttpInvoker.builder()
                .uri(Consts.URL + "/simple/2")
                .head();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Test
    public void testOptions() {
        HttpInvoker.Response response = HttpInvoker.builder()
                .uri(Consts.URL + "/simple/3")
                .options();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Test
    public void testTrace() {
        HttpInvoker.Response response = HttpInvoker.builder()
                .uri(Consts.URL + "/simple/4")
                .trace();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Test
    public void testTrace2() {
        HttpRequestException httpRequestException = null;
        try {
            HttpInvoker.Response response = HttpInvoker.builder(HttpClientBuilder.builder().followRedirects(true).build())
                    .uri(Consts.URL + "/redirect/loop")
                    .trace();
            response.log();
        } catch (HttpRequestException e) {
            httpRequestException = e;
        }

        Assert.assertNull(httpRequestException);
    }

    @Test
    public void testHeaders() {
        HttpInvoker.Response response = HttpInvoker.builder(HttpClientBuilder.builder()
                .header("AAA", "VVV")
                .header(HttpHeaders.USER_AGENT, "VVVVVVFSDSFSF")
                .build())
                .uri(Consts.URL + "/simple/3")
                .data("employeeId", "00160041")
                .data(ImmutableMap.of("employeeName", "陈孝杰1"))
                .data("ad", "xiaojie.chen", "ad", "xiaojie.chen1")
                .header("AAA", "BBB")
                .header("AAA", "BBB2")
                .headers(ImmutableMap.of("BBB", "CCC"))
                .headers(ImmutableMap.of(HttpHeaders.USER_AGENT, "ASSSDDSDSDD"))
                .get();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Test
    public void testCookie() {
        BasicClientCookie cookie1 = new BasicClientCookie("Auth", "AuthAuth");
        cookie1.setPath("/");
        cookie1.setDomain("localhost");

        BasicClientCookie cookie2 = new BasicClientCookie("Auth2", "Auth2Auth2");
        cookie2.setPath("/");
        cookie2.setDomain("localhost");

        BasicClientCookie cookie3 = new BasicClientCookie("Auth3", "Auth3Auth3");
        cookie3.setPath("/");
        cookie3.setDomain("localhost");

        HttpInvoker.Response response = HttpInvoker.builder(HttpClientBuilder.builder()
                .header("AAA", "VVV")
                .header(HttpHeaders.USER_AGENT, "VVVVVVFSDSFSF")
                .cookie(cookie1)
                .cookies(Lists.<Cookie>newArrayList(cookie2, cookie3))
                .build())
                .uri(Consts.URL + "/simple/3")
                .data("employeeId", "00160041")
                .data(ImmutableMap.of("employeeName", "陈孝杰1"))
                .data("ad", "xiaojie.chen", "ad", "xiaojie.chen1")
                .header("AAA", "BBB")
                .header("AAA", "BBB2")
                .headers(ImmutableMap.of("BBB", "CCC"))
                .headers(ImmutableMap.of(HttpHeaders.USER_AGENT, "ASSSDDSDSDD"))
                .cookie("Auth", "123")
                .cookies(ImmutableMap.of("Auth5", "Auth5Auth5", "Auth6", "Auth6Auth6"))
                .get();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

    @Test
    public void testInterceptor() {

        HttpInvoker.Response response = HttpInvoker.builder()
                .uri(Consts.URL + "/simple/3")
                .data("employeeId", "00160041")
                .data(ImmutableMap.of("employeeName", "陈孝杰1"))
                .data("ad", "xiaojie.chen", "ad", "xiaojie.chen1")
                .header("AAA", "BBB")
                .header("AAA", "BBB2")
                .headers(ImmutableMap.of("BBB", "CCC"))
                .headers(ImmutableMap.of(HttpHeaders.USER_AGENT, "ASSSDDSDSDD"))
                .cookie("Auth", "123")
                .cookies(ImmutableMap.of("Auth5", "Auth5Auth5", "Auth6", "Auth6Auth6"))
                .interceptor(new HttpInvoker.Interceptor() {
                    @Override
                    public boolean intercept(HttpRequestBase httpRequestBase) throws HttpRequestException {
                        System.out.println(httpRequestBase);
                        return true;
                    }
                })
                .interceptor(new BasicAuthInterceptor("AAA", "BBB", "UTF-8"))
                .get();

        response.log();
        Assert.assertTrue(response.isSuccess());
    }

}

通过api的方式请求

java api

public interface SimpleHttpApi {

    @RequestMapping("/simple/{loginId}")
    Response<UserLoginModel> queryByLoginId(@PathVariable("loginId") int loginId);

    @RequestMapping("/simple/{loginId}")
    HttpResult<Response<UserLoginModel>> queryHttpResultByLoginId(@PathVariable("loginId") int loginId);

    @RequestMapping(value = "/simple/{loginId}", method = HttpMethod.GET)
    Response<UserLoginModel> getByLoginId(@PathVariable("loginId") int loginId,
                                          @RequestParam(value = "employeeId") String employeeId,
                                          @RequestParam(value = "employeeName") String employeeName,
                                          @RequestParam(value = "ad") String ad);


    @RequestMapping(value = "/simple/{loginId}", method = HttpMethod.POST)
    Response<UserLoginModel> addByLoginId(@PathVariable("loginId") int loginId,
                                          @RequestParam(value = "employeeId") String employeeId,
                                          @RequestParam(value = "employeeName") String employeeName,
                                          @RequestParam(value = "ad") String ad);


    @RequestMapping(value = "/simple", method = HttpMethod.POST)
    Response<UserLoginModel> addUser(UserLoginModel userLoginModel);

    @RequestMapping(value = "/simple", method = HttpMethod.POST)
    HttpResult<Response<UserLoginModel>> addUser2(@RequestBody UserLoginModel userLoginModel);

    @RequestMapping(value = "/simple", method = HttpMethod.POST)
    HttpResult<Response<UserLoginModel>> addUser3(String userLoginModel);

    @RequestMapping(value = "/simple", method = HttpMethod.POST)
    HttpResult<Response<UserLoginModel>> addUser4(@RequestBody String userLoginModel);

    @RequestMapping(value = "/{path}", method = HttpMethod.POST)
    HttpResult<Response<UserLoginModel>> addUser5(@RequestBody UserLoginModel userLoginModel,
                                                  @PathVariable("path") String path,
                                                  @RequestParam(value = "employeeId") String employeeId,
                                                  @RequestParam(value = "employeeId") String employeeId2,
                                                  @RequestParam(value = "employeeId") String employeeId3,
                                                  @RequestParam(value = "employeeName") String employeeName,
                                                  @RequestParam(value = "ad") String ad);

    @RequestMapping(value = "/simple/{loginId}", method = HttpMethod.PUT)
    HttpResult<Response<UserLoginModel>> updateUser(@RequestBody UserLoginModel userLoginModel,
                                                    @PathVariable("loginId") int loginId,
                                                    @RequestParam(value = "employeeId") String employeeId,
                                                    @RequestParam(value = "employeeId") String employeeId2,
                                                    @RequestParam(value = "employeeId") String employeeId3,
                                                    @RequestParam(value = "employeeName") String employeeName,
                                                    @RequestParam(value = "ad") String ad);

    @RequestMapping(value = "/simple/{loginId}", method = HttpMethod.PATCH)
    HttpResult<Response<UserLoginModel>> patchUser(@RequestBody UserLoginModel userLoginModel,
                                                   @PathVariable("loginId") int loginId,
                                                   @RequestParam(value = "employeeId") String employeeId,
                                                   @RequestParam(value = "employeeId") String employeeId2,
                                                   @RequestParam(value = "employeeId") String employeeId3,
                                                   @RequestParam(value = "employeeName") String employeeName,
                                                   @RequestParam(value = "ad") String ad);


    @RequestMapping(value = "/simple/{loginId}", method = HttpMethod.DELETE)
    HttpResult<String> deleteUser(@RequestBody UserLoginModel userLoginModel,
                                  @PathVariable("loginId") int loginId,
                                  @RequestParam(value = "employeeId") String employeeId,
                                  @RequestParam(value = "employeeId") String employeeId2,
                                  @RequestParam(value = "employeeId") String employeeId3,
                                  @RequestParam(value = "employeeName") String employeeName,
                                  @RequestParam(value = "ad") String ad);

}

通过java 请求

HttpInvocationHandler httpInvocationHandler = new HttpInvocationHandler();
httpInvocationHandler.setRequestUrlPrefix(Consts.URL);

SimpleHttpApi simpleHttpApi = (SimpleHttpApi) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
        new Class[]{SimpleHttpApi.class},
        httpInvocationHandler);

UserLoginModel userLoginModel = new UserLoginModel();
userLoginModel.setLoginId(1);
userLoginModel.setEmployeeId("0016004");
userLoginModel.setEmployeeName("陈孝杰");
userLoginModel.setAd("xiaojie.chen");

Response<UserLoginModel> response = simpleHttpApi.addUser(userLoginModel);

System.out.println(response.getData());

通过spring xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="httpParent" class="com.chenxiaojie.http.invoker.spring.HttpProxyFactoryBean" abstract="true" init-method="init">
        <property name="invocationHandler">
            <bean class="com.chenxiaojie.http.invoker.proxy.HttpInvocationHandler">
                <property name="requestUrlPrefix" value="http://localhost:8081/httpinvoker"></property>
            </bean>
        </property>
    </bean>

    <!-- 只需配置下方代码即可 -->
    <bean id="simpleHttpApi" parent="httpParent">
        <property name="proxyInterfaces" value="com.chenxiaojie.http.invoker.test.http.api.SimpleHttpApi"/>
    </bean>
</beans>

测试类请参考com.chenxiaojie.http.invoker.test.http.test.SimpleTest

建议

如果请求量比较大, 请尽量自定义httpclient, 否则全局共享一个默认的httpclient

如果请求量比较大, 请将http请求详细日志重置到其他位置或者关闭

日志位置重置

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="info">

    <Properties>
        <Property name="log-path">/data/applogs/http-invoker-demo/logs</Property>
        <Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} %level [%t] [%c] %msg%xEx%n</Property>
    </Properties>

    <Appenders>
        <Console name="ConsoleAppender" target="SYSTEM_OUT" follow="true">
            <PatternLayout pattern="${pattern}"/>
        </Console>

        <RollingFile name="AppAppender" fileName="${log-path}/app.log" filePattern="${log-path}/app.log.%d{yyyy-MM-dd}">
            <PatternLayout pattern="${pattern}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
            </Policies>
        </RollingFile>

        <RollingFile name="HttpAppender" fileName="${log-path}/http.log"
                     filePattern="${log-path}/http.log.%d{yyyy-MM-dd}">
            <PatternLayout pattern="${pattern}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1"/>
            </Policies>
        </RollingFile>

        <Async name="AsyncAppAppender">
            <AppenderRef ref="AppAppender" level="info"/>
        </Async>

    </Appenders>

    <loggers>
        <logger name="com.chenxiaojie.http.invoker.HttpInvoker$Response" additivity="false">
            <appender-ref ref="HttpAppender"/>
            <appender-ref ref="ConsoleAppender"/>
        </logger>

        <root level="info">
            <appender-ref ref="ConsoleAppender"/>
            <appender-ref ref="AsyncAppAppender"/>
        </root>
    </loggers>

</configuration>

关闭日志 spring xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="httpParent" class="com.chenxiaojie.http.invoker.spring.HttpProxyFactoryBean" abstract="true"
          init-method="init">
        <property name="invocationHandler">
            <bean class="com.chenxiaojie.http.invoker.proxy.HttpInvocationHandler">
                <property name="requestUrlPrefix" value="http://localhost:8081/httpinvoker"></property>
                <property name="openLog" value="true"></property>
            </bean>
        </property>
    </bean>

    <!-- 只需配置下方代码即可 -->
    <bean id="simpleHttpApi" parent="httpParent">
        <property name="proxyInterfaces" value="com.chenxiaojie.http.invoker.test.http.api.SimpleHttpApi"/>
    </bean>
</beans>

打包命令

mvn clean install -DskipTests -Dmaven.javadoc.skip=true

维护

有任何问题请随时联系:陈孝杰, qq:3262515, email: 3262515@qq.com

© 著作权归作者所有

陈孝杰
粉丝 4
博文 6
码字总数 5639
作品 0
武汉
程序员
私信 提问
Spring HTTP Invoker

Spring 开发小组意识到在RMI服务和基于 HTTP的服务(如Hessian和Burlap)之间的空白。一方面,RMI使用Java标准的对象序列化,但很难穿越防火墙;另一方面, Hessian/Burlap能很好地穿过防火墙...

匿名
2010/08/15
4.1K
0
dubbo源码分析系列(2)服务的发布

1 系列目录 - dubbo源码分析系列(1)扩展机制的实现- dubbo源码分析系列(2)服务的发布- dubbo源码分析系列(3)服务的引用- dubbo源码分析系列(4)dubbo通信设计 2 dubbo与spring接入 du...

乒乓狂魔
2015/09/28
8.7K
4
使用Spring HTTP invoker进行远程调用

6.4 使用Spring HTTP invoker进行远程调用 Spring 开发小组意识到在RMI服务和基于 HTTP的服务(如Hessian和Burlap)之间的空白。一方面,RMI使用Java标准的对象序列化,但很难穿越防火墙;另...

红薯
2010/08/15
5.2K
1
dubbo源码分析系列(3)服务的引用

1 系列目录 - dubbo源码分析系列(1)扩展机制的实现- dubbo源码分析系列(2)服务的发布- dubbo源码分析系列(3)服务的引用- dubbo源码分析系列(4)dubbo通信设计 2 服务引用案例介绍 先看...

乒乓狂魔
2015/10/12
4.6K
5
Dubbo源码分析(11):服务发布

服务发布是服务提供方向注册中注册服务过程,以便服务消费者从注册中心查阅并调用服务。 服务发布方在spring的配置文件中配置如下: 上面是在spring中配置的服务的具体实现,是spring中的一个...

郑加威
2018/12/23
33
0

没有更多内容

加载失败,请刷新页面

加载更多

DDD(十)--仓储

1、引言 DDD中的Repository(仓储):协调领域和数据映射层,利用类似与集合的接口来访问领域对象。——《领域驱动设计-软件核心复杂性应对之道》 仓储是DDD中产生的概念,也就是说,如果应...

MrYuZixian
11分钟前
5
0
Jenkins的多种迁移方法

说明 Jenkins有时需要进行迁移,主目录会发生改变,本文主要讲解如何更改主目录。由于jenkins安装方式的不同,主目录也不一样。 本测试环境:Centos7.6 X64。注意:在更改主目录之前,请一定...

Elson
12分钟前
5
0
好程序员web前端教程分享前端javascript练习题三

好程序员web前端教程分享前端javascript练习题三,cookie 一周内免登录 样式代码: <form action=""> 姓名:<input type="text" id="usename"/><br /> 密码:<input type="text" i="mima"/>......

好程序员官网
31分钟前
5
0
Table 信息转成pojo属性

import com.google.common.base.CaseFormat;import java.sql.*;/** * @author: liyhu * @date: 2019/11/22 */public class TableToPojo { static String url="jdbc:mys......

暗中观察
今天
8
0
Access数据库-C#操作类

//Access数据库-C# 操作类 代码using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data.OleDb;using System.Data;namespace XXX{......

芳缘
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部