作者 crossoverJie

:sparkles: Introducing new features新增路由

  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>netty-action</artifactId>
  7 + <groupId>com.crossoverjie.netty</groupId>
  8 + <version>1.0.0-SNAPSHOT</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>cim-forward-route</artifactId>
  13 + <packaging>jar</packaging>
  14 +
  15 + <properties>
  16 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  17 + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  18 + <java.version>1.8</java.version>
  19 + <swagger.version>2.5.0</swagger.version>
  20 + <logback.version>1.2.3</logback.version>
  21 + </properties>
  22 +
  23 +
  24 +
  25 + <dependencies>
  26 +
  27 + <dependency>
  28 + <groupId>com.crossoverjie.netty</groupId>
  29 + <artifactId>netty-action-common</artifactId>
  30 + </dependency>
  31 +
  32 +
  33 + <dependency>
  34 + <groupId>io.springfox</groupId>
  35 + <artifactId>springfox-swagger2</artifactId>
  36 + <scope>compile</scope>
  37 + </dependency>
  38 + <dependency>
  39 + <groupId>io.springfox</groupId>
  40 + <artifactId>springfox-swagger-ui</artifactId>
  41 + </dependency>
  42 +
  43 + <dependency>
  44 + <groupId>org.springframework.boot</groupId>
  45 + <artifactId>spring-boot-starter-web</artifactId>
  46 + </dependency>
  47 + <dependency>
  48 + <groupId>org.springframework.boot</groupId>
  49 + <artifactId>spring-boot-starter-test</artifactId>
  50 + <scope>test</scope>
  51 + </dependency>
  52 +
  53 + <dependency>
  54 + <groupId>org.springframework.boot</groupId>
  55 + <artifactId>spring-boot-configuration-processor</artifactId>
  56 + <optional>true</optional>
  57 + </dependency>
  58 +
  59 +
  60 + <dependency>
  61 + <groupId>org.springframework.boot</groupId>
  62 + <artifactId>spring-boot-starter-actuator</artifactId>
  63 + </dependency>
  64 +
  65 + <dependency>
  66 + <groupId>de.codecentric</groupId>
  67 + <artifactId>spring-boot-admin-starter-client</artifactId>
  68 + </dependency>
  69 +
  70 + <dependency>
  71 + <groupId>ch.qos.logback</groupId>
  72 + <artifactId>logback-classic</artifactId>
  73 + </dependency>
  74 +
  75 + <dependency>
  76 + <groupId>io.netty</groupId>
  77 + <artifactId>netty-all</artifactId>
  78 + <version>${netty.version}</version>
  79 + </dependency>
  80 +
  81 + <dependency>
  82 + <groupId>junit</groupId>
  83 + <artifactId>junit</artifactId>
  84 + </dependency>
  85 +
  86 + <dependency>
  87 + <groupId>com.alibaba</groupId>
  88 + <artifactId>fastjson</artifactId>
  89 + </dependency>
  90 +
  91 + <dependency>
  92 + <groupId>com.google.guava</groupId>
  93 + <artifactId>guava</artifactId>
  94 + </dependency>
  95 +
  96 + </dependencies>
  97 +
  98 + <build>
  99 + <plugins>
  100 + <!-- spring-boot-maven-plugin (提供了直接运行项目的插件:如果是通过parent方式继承spring-boot-starter-parent则不用此插件) -->
  101 + <plugin>
  102 + <groupId>org.springframework.boot</groupId>
  103 + <artifactId>spring-boot-maven-plugin</artifactId>
  104 + <executions>
  105 + <execution>
  106 + <goals>
  107 + <goal>repackage</goal>
  108 + </goals>
  109 + </execution>
  110 + </executions>
  111 + </plugin>
  112 + </plugins>
  113 + </build>
  114 +
  115 +</project>
  1 +package com.crossoverjie.cim.route;
  2 +
  3 +import org.slf4j.Logger;
  4 +import org.slf4j.LoggerFactory;
  5 +import org.springframework.boot.SpringApplication;
  6 +import org.springframework.boot.autoconfigure.SpringBootApplication;
  7 +
  8 +/**
  9 + * @author crossoverJie
  10 + */
  11 +@SpringBootApplication
  12 +public class RouteApplication {
  13 +
  14 + private final static Logger LOGGER = LoggerFactory.getLogger(RouteApplication.class);
  15 +
  16 + public static void main(String[] args) {
  17 + SpringApplication.run(RouteApplication.class, args);
  18 + LOGGER.info("启动 route 成功");
  19 + }
  20 +
  21 +}
  1 +package com.crossoverjie.cim.route.config;
  2 +
  3 +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
  4 +import org.springframework.context.annotation.Bean;
  5 +import org.springframework.context.annotation.Configuration;
  6 +import springfox.documentation.builders.ApiInfoBuilder;
  7 +import springfox.documentation.builders.PathSelectors;
  8 +import springfox.documentation.builders.RequestHandlerSelectors;
  9 +import springfox.documentation.service.ApiInfo;
  10 +import springfox.documentation.spi.DocumentationType;
  11 +import springfox.documentation.spring.web.plugins.Docket;
  12 +import springfox.documentation.swagger2.annotations.EnableSwagger2;
  13 +
  14 +
  15 +@Configuration
  16 +@EnableSwagger2
  17 +/** 是否打开swagger **/
  18 +@ConditionalOnExpression("'${swagger.enable}' == 'true'")
  19 +public class SwaggerConfig {
  20 +
  21 +
  22 + @Bean
  23 + public Docket createRestApi() {
  24 + return new Docket(DocumentationType.SWAGGER_2)
  25 + .apiInfo(apiInfo())
  26 + .select()
  27 + .apis(RequestHandlerSelectors.basePackage("com.crossoverjie.cim.route.controller"))
  28 + .paths(PathSelectors.any())
  29 + .build();
  30 + }
  31 +
  32 + private ApiInfo apiInfo() {
  33 + return new ApiInfoBuilder()
  34 + .title("cim-forward-route")
  35 + .description("cim-forward-route api")
  36 + .termsOfServiceUrl("http://crossoverJie.top")
  37 + .contact("crossoverJie")
  38 + .version("1.0.0")
  39 + .build();
  40 + }
  41 +
  42 +}
  1 +package com.crossoverjie.cim.route.controller;
  2 +
  3 +import com.crossoverjie.cim.route.vo.req.P2PRequest;
  4 +import com.crossoverjie.cim.route.vo.req.GroupRequest;
  5 +import com.crossoverjie.netty.action.common.enums.StatusEnum;
  6 +import com.crossoverjie.netty.action.common.res.BaseResponse;
  7 +import io.swagger.annotations.ApiOperation;
  8 +import org.slf4j.Logger;
  9 +import org.slf4j.LoggerFactory;
  10 +import org.springframework.stereotype.Controller;
  11 +import org.springframework.web.bind.annotation.RequestBody;
  12 +import org.springframework.web.bind.annotation.RequestMapping;
  13 +import org.springframework.web.bind.annotation.RequestMethod;
  14 +import org.springframework.web.bind.annotation.ResponseBody;
  15 +
  16 +/**
  17 + * Function:
  18 + *
  19 + * @author crossoverJie
  20 + * Date: 22/05/2018 14:46
  21 + * @since JDK 1.8
  22 + */
  23 +@Controller
  24 +@RequestMapping("/")
  25 +public class RouteController {
  26 + private final static Logger LOGGER = LoggerFactory.getLogger(RouteController.class);
  27 +
  28 + @ApiOperation("群聊 API")
  29 + @RequestMapping(value = "groupRoute",method = RequestMethod.POST)
  30 + @ResponseBody()
  31 + public BaseResponse groupRoute(@RequestBody GroupRequest groupRequest){
  32 + BaseResponse res = new BaseResponse();
  33 +
  34 + LOGGER.info("msg=[{}]",groupRequest.toString());
  35 +
  36 + res.setCode(StatusEnum.SUCCESS.getCode()) ;
  37 + res.setMessage(StatusEnum.SUCCESS.getMessage()) ;
  38 + return res ;
  39 + }
  40 +
  41 +
  42 + /**
  43 + * 私聊路由
  44 + * @param p2pRequest
  45 + * @return
  46 + */
  47 + @ApiOperation("私聊 API")
  48 + @RequestMapping(value = "p2pRoute",method = RequestMethod.POST)
  49 + @ResponseBody()
  50 + public BaseResponse p2pRoute(@RequestBody P2PRequest p2pRequest){
  51 + BaseResponse res = new BaseResponse();
  52 +
  53 + res.setCode(StatusEnum.SUCCESS.getCode()) ;
  54 + res.setMessage(StatusEnum.SUCCESS.getMessage()) ;
  55 + return res ;
  56 + }
  57 +
  58 +
  59 +}
  1 +package com.crossoverjie.cim.route.vo.req;
  2 +
  3 +import com.crossoverjie.netty.action.common.req.BaseRequest;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +
  6 +import javax.validation.constraints.NotNull;
  7 +
  8 +/**
  9 + * Function: Google Protocol 编解码发送
  10 + *
  11 + * @author crossoverJie
  12 + * Date: 2018/05/21 15:56
  13 + * @since JDK 1.8
  14 + */
  15 +public class GroupRequest extends BaseRequest {
  16 +
  17 + @NotNull(message = "msg 不能为空")
  18 + @ApiModelProperty(required = true, value = "msg", example = "hello")
  19 + private String msg ;
  20 +
  21 + public String getMsg() {
  22 + return msg;
  23 + }
  24 +
  25 + public void setMsg(String msg) {
  26 + this.msg = msg;
  27 + }
  28 +
  29 + @Override
  30 + public String toString() {
  31 + return "GroupRequest{" +
  32 + "msg='" + msg + '\'' +
  33 + "} " + super.toString();
  34 + }
  35 +}
  1 +package com.crossoverjie.cim.route.vo.req;
  2 +
  3 +import com.crossoverjie.netty.action.common.req.BaseRequest;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +
  6 +import javax.validation.constraints.NotNull;
  7 +
  8 +/**
  9 + * Function:
  10 + *
  11 + * @author crossoverJie
  12 + * Date: 2018/05/21 15:56
  13 + * @since JDK 1.8
  14 + */
  15 +public class P2PRequest extends BaseRequest {
  16 +
  17 + @NotNull(message = "msg 不能为空")
  18 + @ApiModelProperty(required = true, value = "msg", example = "hello")
  19 + private String msg ;
  20 +
  21 + public String getMsg() {
  22 + return msg;
  23 + }
  24 +
  25 + public void setMsg(String msg) {
  26 + this.msg = msg;
  27 + }
  28 +}
  1 +package com.crossoverjie.cim.route.vo.req;
  2 +
  3 +import com.crossoverjie.netty.action.common.req.BaseRequest;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +
  6 +import javax.validation.constraints.NotNull;
  7 +
  8 +/**
  9 + * Function:
  10 + *
  11 + * @author crossoverJie
  12 + * Date: 2018/05/21 15:56
  13 + * @since JDK 1.8
  14 + */
  15 +public class SendMsgReqVO extends BaseRequest {
  16 +
  17 + @NotNull(message = "msg 不能为空")
  18 + @ApiModelProperty(required = true, value = "msg", example = "hello")
  19 + private String msg ;
  20 +
  21 + @NotNull(message = "id 不能为空")
  22 + @ApiModelProperty(required = true, value = "id", example = "11")
  23 + private long id ;
  24 +
  25 + public String getMsg() {
  26 + return msg;
  27 + }
  28 +
  29 + public void setMsg(String msg) {
  30 + this.msg = msg;
  31 + }
  32 +
  33 + public long getId() {
  34 + return id;
  35 + }
  36 +
  37 + public void setId(long id) {
  38 + this.id = id;
  39 + }
  40 +}
  1 +package com.crossoverjie.cim.route.vo.res;
  2 +
  3 +/**
  4 + * Function:
  5 + *
  6 + * @author crossoverJie
  7 + * Date: 2017/6/26 15:43
  8 + * @since JDK 1.8
  9 + */
  10 +public class SendMsgResVO {
  11 + private String msg ;
  12 +
  13 + public String getMsg() {
  14 + return msg;
  15 + }
  16 +
  17 + public void setMsg(String msg) {
  18 + this.msg = msg;
  19 + }
  20 +}
  1 +spring.application.name=cim-forward-route
  2 +
  3 +# web port
  4 +server.port=8083
  5 +
  6 +# 是否打开swagger
  7 +swagger.enable = true
  8 +
  9 +logging.level.root=info
  10 +
  11 +
  12 +# 关闭健康检查权限
  13 +management.security.enabled=false
  14 +
@@ -19,6 +19,11 @@ @@ -19,6 +19,11 @@
19 </dependency> 19 </dependency>
20 20
21 <dependency> 21 <dependency>
  22 + <groupId>com.squareup.okhttp3</groupId>
  23 + <artifactId>okhttp</artifactId>
  24 + </dependency>
  25 +
  26 + <dependency>
22 <groupId>io.springfox</groupId> 27 <groupId>io.springfox</groupId>
23 <artifactId>springfox-swagger2</artifactId> 28 <artifactId>springfox-swagger2</artifactId>
24 <scope>compile</scope> 29 <scope>compile</scope>
1 package com.crossoverjie.netty.action.client.config; 1 package com.crossoverjie.netty.action.client.config;
2 2
3 -import com.crossoverjie.netty.action.common.pojo.CustomProtocol;  
4 -import org.springframework.beans.factory.annotation.Configurable; 3 +import com.crossoverjie.netty.action.common.protocol.BaseRequestProto;
5 import org.springframework.beans.factory.annotation.Value; 4 import org.springframework.beans.factory.annotation.Value;
6 import org.springframework.context.annotation.Bean; 5 import org.springframework.context.annotation.Bean;
7 import org.springframework.context.annotation.Configuration; 6 import org.springframework.context.annotation.Configuration;
@@ -16,12 +15,18 @@ import org.springframework.context.annotation.Configuration; @@ -16,12 +15,18 @@ import org.springframework.context.annotation.Configuration;
16 @Configuration 15 @Configuration
17 public class HeartBeatConfig { 16 public class HeartBeatConfig {
18 17
19 - @Value("${channel.id}")  
20 - private long id ; 18 + @Value("${client.request.id}")
  19 + private int requestId;
21 20
22 21
23 @Bean(value = "heartBeat") 22 @Bean(value = "heartBeat")
24 - public CustomProtocol heartBeat(){  
25 - return new CustomProtocol(id,"ping") ; 23 + public BaseRequestProto.RequestProtocol heartBeat() {
  24 +
  25 + BaseRequestProto.RequestProtocol heart = BaseRequestProto.RequestProtocol.newBuilder()
  26 + .setRequestId(requestId)
  27 + .setReqMsg("ping")
  28 + .build();
  29 +
  30 + return heart;
26 } 31 }
27 } 32 }
@@ -11,6 +11,10 @@ import com.crossoverjie.netty.action.common.pojo.CustomProtocol; @@ -11,6 +11,10 @@ import com.crossoverjie.netty.action.common.pojo.CustomProtocol;
11 import com.crossoverjie.netty.action.common.res.BaseResponse; 11 import com.crossoverjie.netty.action.common.res.BaseResponse;
12 import com.crossoverjie.netty.action.common.res.NULLBody; 12 import com.crossoverjie.netty.action.common.res.NULLBody;
13 import io.swagger.annotations.ApiOperation; 13 import io.swagger.annotations.ApiOperation;
  14 +import okhttp3.MediaType;
  15 +import okhttp3.OkHttpClient;
  16 +import okhttp3.Request;
  17 +import okhttp3.Response;
14 import org.springframework.beans.factory.annotation.Autowired; 18 import org.springframework.beans.factory.annotation.Autowired;
15 import org.springframework.boot.actuate.metrics.CounterService; 19 import org.springframework.boot.actuate.metrics.CounterService;
16 import org.springframework.stereotype.Controller; 20 import org.springframework.stereotype.Controller;
@@ -19,6 +23,8 @@ import org.springframework.web.bind.annotation.RequestMapping; @@ -19,6 +23,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
19 import org.springframework.web.bind.annotation.RequestMethod; 23 import org.springframework.web.bind.annotation.RequestMethod;
20 import org.springframework.web.bind.annotation.ResponseBody; 24 import org.springframework.web.bind.annotation.ResponseBody;
21 25
  26 +import java.io.IOException;
  27 +
22 /** 28 /**
23 * Function: 29 * Function:
24 * 30 *
@@ -111,4 +117,50 @@ public class IndexController { @@ -111,4 +117,50 @@ public class IndexController {
111 res.setMessage(StatusEnum.SUCCESS.getMessage()) ; 117 res.setMessage(StatusEnum.SUCCESS.getMessage()) ;
112 return res ; 118 return res ;
113 } 119 }
  120 +
  121 +
  122 +
  123 + /**
  124 + * 群发消息
  125 + * @param sendMsgReqVO
  126 + * @return
  127 + */
  128 + @ApiOperation("群发消息")
  129 + @RequestMapping(value = "sendGroupMsg",method = RequestMethod.POST)
  130 + @ResponseBody
  131 + public BaseResponse<SendMsgResVO> sendGroupMsg(@RequestBody SendMsgReqVO sendMsgReqVO) throws IOException {
  132 + BaseResponse<SendMsgResVO> res = new BaseResponse();
  133 + OkHttpClient client = new OkHttpClient();
  134 + MediaType MEDIA_TYPE_MARKDOWN
  135 + = MediaType.parse("text/x-markdown; charset=utf-8");
  136 +
  137 + String postBody = ""
  138 + + "Releases\n"
  139 + + "--------\n"
  140 + + "\n"
  141 + + " * _1.0_ May 6, 2013\n"
  142 + + " * _1.1_ June 15, 2013\n"
  143 + + " * _1.2_ August 11, 2013\n";
  144 +
  145 + Request request = new Request.Builder()
  146 + .url("https://api.github.com/markdown/raw")
  147 + .post(okhttp3.RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody))
  148 + .build();
  149 +
  150 + Response response = client.newCall(request).execute();
  151 + if (!response.isSuccessful()){
  152 + throw new IOException("Unexpected code " + response);
  153 + }
  154 +
  155 + System.out.println(response.body().string());
  156 +
  157 + counterService.increment(Constants.COUNTER_SERVER_PUSH_COUNT);
  158 +
  159 + SendMsgResVO sendMsgResVO = new SendMsgResVO() ;
  160 + sendMsgResVO.setMsg("OK") ;
  161 + res.setCode(StatusEnum.SUCCESS.getCode()) ;
  162 + res.setMessage(StatusEnum.SUCCESS.getMessage()) ;
  163 + res.setDataBody(sendMsgResVO) ;
  164 + return res ;
  165 + }
114 } 166 }
1 package com.crossoverjie.netty.action.client.handle; 1 package com.crossoverjie.netty.action.client.handle;
2 2
  3 +import com.crossoverjie.netty.action.client.util.SpringBeanFactory;
  4 +import com.crossoverjie.netty.action.common.pojo.CustomProtocol;
3 import com.crossoverjie.netty.action.common.protocol.BaseRequestProto; 5 import com.crossoverjie.netty.action.common.protocol.BaseRequestProto;
4 import com.crossoverjie.netty.action.common.protocol.BaseResponseProto; 6 import com.crossoverjie.netty.action.common.protocol.BaseResponseProto;
5 import io.netty.channel.ChannelFutureListener; 7 import io.netty.channel.ChannelFutureListener;
@@ -21,10 +23,7 @@ public class EchoClientHandle extends SimpleChannelInboundHandler<BaseResponsePr @@ -21,10 +23,7 @@ public class EchoClientHandle extends SimpleChannelInboundHandler<BaseResponsePr
21 23
22 private final static Logger LOGGER = LoggerFactory.getLogger(EchoClientHandle.class); 24 private final static Logger LOGGER = LoggerFactory.getLogger(EchoClientHandle.class);
23 25
24 - private final BaseRequestProto.RequestProtocol heart = BaseRequestProto.RequestProtocol.newBuilder()  
25 - .setRequestId(99999999)  
26 - .setReqMsg("ping")  
27 - .build(); 26 +
28 27
29 28
30 @Override 29 @Override
@@ -36,7 +35,8 @@ public class EchoClientHandle extends SimpleChannelInboundHandler<BaseResponsePr @@ -36,7 +35,8 @@ public class EchoClientHandle extends SimpleChannelInboundHandler<BaseResponsePr
36 if (idleStateEvent.state() == IdleState.WRITER_IDLE){ 35 if (idleStateEvent.state() == IdleState.WRITER_IDLE){
37 LOGGER.info("已经 10 秒没有发送信息!"); 36 LOGGER.info("已经 10 秒没有发送信息!");
38 //向服务端发送消息 37 //向服务端发送消息
39 - ctx.writeAndFlush(heart).addListener(ChannelFutureListener.CLOSE_ON_FAILURE) ; 38 + BaseRequestProto.RequestProtocol heartBeat = SpringBeanFactory.getBean("heartBeat", BaseRequestProto.RequestProtocol.class);
  39 + ctx.writeAndFlush(heartBeat).addListener(ChannelFutureListener.CLOSE_ON_FAILURE) ;
40 } 40 }
41 41
42 42
@@ -11,8 +11,8 @@ netty.server.port=11211 @@ -11,8 +11,8 @@ netty.server.port=11211
11 11
12 logging.level.root=info 12 logging.level.root=info
13 13
14 -# 通道 ID  
15 -channel.id=100 14 +# 客户端唯一ID
  15 +client.request.id=100
16 16
17 17
18 # 关闭健康检查权限 18 # 关闭健康检查权限
@@ -12,6 +12,7 @@ import org.springframework.boot.actuate.metrics.CounterService; @@ -12,6 +12,7 @@ import org.springframework.boot.actuate.metrics.CounterService;
12 import org.springframework.stereotype.Controller; 12 import org.springframework.stereotype.Controller;
13 import org.springframework.web.bind.annotation.RequestBody; 13 import org.springframework.web.bind.annotation.RequestBody;
14 import org.springframework.web.bind.annotation.RequestMapping; 14 import org.springframework.web.bind.annotation.RequestMapping;
  15 +import org.springframework.web.bind.annotation.RequestMethod;
15 import org.springframework.web.bind.annotation.ResponseBody; 16 import org.springframework.web.bind.annotation.ResponseBody;
16 17
17 /** 18 /**
@@ -41,7 +42,7 @@ public class IndexController { @@ -41,7 +42,7 @@ public class IndexController {
41 * @return 42 * @return
42 */ 43 */
43 @ApiOperation("服务端发送消息") 44 @ApiOperation("服务端发送消息")
44 - @RequestMapping("sendMsg") 45 + @RequestMapping(value = "sendMsg",method = RequestMethod.POST)
45 @ResponseBody 46 @ResponseBody
46 public BaseResponse<SendMsgResVO> sendMsg(@RequestBody SendMsgReqVO sendMsgReqVO){ 47 public BaseResponse<SendMsgResVO> sendMsg(@RequestBody SendMsgReqVO sendMsgReqVO){
47 BaseResponse<SendMsgResVO> res = new BaseResponse(); 48 BaseResponse<SendMsgResVO> res = new BaseResponse();
@@ -56,4 +57,5 @@ public class IndexController { @@ -56,4 +57,5 @@ public class IndexController {
56 res.setDataBody(sendMsgResVO) ; 57 res.setDataBody(sendMsgResVO) ;
57 return res ; 58 return res ;
58 } 59 }
  60 +
59 } 61 }
@@ -32,13 +32,18 @@ @@ -32,13 +32,18 @@
32 <module>netty-action-common</module> 32 <module>netty-action-common</module>
33 <module>springboot-admin</module> 33 <module>springboot-admin</module>
34 <module>netty-action-zk</module> 34 <module>netty-action-zk</module>
  35 + <module>cim-forward-route</module>
35 </modules> 36 </modules>
36 37
37 38
38 <dependencyManagement> 39 <dependencyManagement>
39 <dependencies> 40 <dependencies>
40 41
41 - 42 + <dependency>
  43 + <groupId>com.squareup.okhttp3</groupId>
  44 + <artifactId>okhttp</artifactId>
  45 + <version>3.3.1</version>
  46 + </dependency>
42 <dependency> 47 <dependency>
43 <groupId>com.github.sgroschupf</groupId> 48 <groupId>com.github.sgroschupf</groupId>
44 <artifactId>zkclient</artifactId> 49 <artifactId>zkclient</artifactId>