Skip to content

chenxiaojie/http-invoker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

基于apache httpclient的轻量http请求

特性

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

添加依赖

<dependency>
    <groupId>com.chenxiaojie</groupId>
    <artifactId>http-invoker</artifactId>
    <version>1.0.2</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 是专门用于测试, 运行以下代码时, 请先启动这个web项目

使用HttpInvoker, 参考测试包下 HttpInvokerTest
@Test
public void testGet() {
     HttpInvoker.Response response = HttpInvoker.builder()
                     .uri("https://www.dianping.com")
                     .get();
}


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


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

    HttpInvoker.Response response = HttpInvoker.builder()
            .uri(Consts.URL + "/postJson")
            .json(userLoginModel)
            .post();
}


@Test
public void testPostFile() {
    InputStream in = Thread.currentThread().getClass().getResourceAsStream("/logo.png");
    
    HttpInvoker.Response response = HttpInvoker.builder()
            .uri(Consts.URL + "/file")
            .data("fileinput", "attachment.png", in)
            .post();
}
通过api的方式请求

java api

public interface SimpleHttpApi {

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

    //post
    @RequestMapping(value = "/{path}", method = HttpMethod.POST)
    HttpResult<Response<UserLoginModel>> post(@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);
    
    //postJson
    @RequestMapping(value = "/simple", method = HttpMethod.POST)
        HttpResult<Response<UserLoginModel>> postJosn(@RequestBody UserLoginModel userLoginModel);
    
    //upload
    @RequestMapping(value = "/{path}", method = HttpMethod.POST)
    HttpResult<Response<String>> upload(@RequestFile("a1.png") InputStream in,
                                        @RequestFile("a2.png") File file,
                                        @RequestFile("a3.png") byte[] fileBytes,
                                        @RequestFile("a4.png") String base64,
                                        @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);
    
    //retry
    @RequestMapping(value = "/simple/{loginId}", method = HttpMethod.GET, retryTimes = 1)
    HttpResult<Response<UserLoginModel>> retry(@PathVariable("loginId") String loginId,
                                                          @RequestParam(value = "employeeId") String employeeId,
                                                          @RequestParam(value = "employeeName") String employeeName,
                                                          @RequestParam(value = "ad") String ad);
    
    //jsonPath
    @RequestMapping(value = "/simple/list", method = HttpMethod.GET, retryTimes = 1, resultJsonPath = "data[1].employeeName")
    String jsonPath();

}

通过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>

建议

如果请求量比较大, 请尽量自定义httpclient, 否则全局共享一个默认的httpclient
如果请求量比较大, 请将http请求详细日志重置到其他位置或者关闭

日志位置重置,如果您的项目中没有依赖slf4j,请添加以下配置

<!-- slf4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.2</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>1.7.2</version>
</dependency>
<!-- log4j2 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-1.2-api</artifactId>
    <version>2.7</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.7</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.7</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.7</version>
</dependency>

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" 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

维护

有任何问题请随时联系:陈孝杰, qq:3262515, email: [email protected]