spring cloud集成feign实现微服务调用,服务注册使用consul,构建选择maven。
项目目录结构,主要包含以下3个module:
kp-core提供公共类和公共配置(如:feign)
kp-service-customer-back 服务提供者
kp-service-customer-mid 服务调用者
首先在父模块(proj-hd-parent)的pom.xml引入依赖(PS:部分没有使用到)使用到dependencyManagement,所以可以在各个子模块下不需要再指定版本标签(version>${project.version}</version)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hd</groupId>
<artifactId>proj-hd-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<modules>
<module>kp-service-customer-back</module>
<module>kp-service-customer-mid</module>
<module>kp-core</module>
</modules>
<packaging>pom</packaging>
<properties>
<!-- Compile libs -->
<fastjson.version>1.2.51</fastjson.version>
<!-- Test libs -->
<junit.version>4.12</junit.version>
<mockito.version>2.21.0</mockito.version>
<!-- Build -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.source.version>1.6</java.source.version>
<java.target.version>1.6</java.target.version>
<maven.compiler.version>3.8.0</maven.compiler.version>
<maven.surefire.version>2.22.1</maven.surefire.version>
<maven.source.version>3.0.1</maven.source.version>
<maven.javadoc.version>3.0.1</maven.javadoc.version>
<maven.deploy.version>2.8.2</maven.deploy.version>
<maven.gpg.version>1.6</maven.gpg.version>
<maven.jacoco.version>0.8.2</maven.jacoco.version>
<maven.jar.version>3.1.0</maven.jar.version>
<spring.boot.version>2.0.6.RELEASE</spring.boot.version>
<spring.cloud.feign.version>2.0.2.RELEASE</spring.cloud.feign.version>
<spring.cloud.consul.version>2.0.1.RELEASE</spring.cloud.consul.version>
<spring.mybatis.version>1.3.2</spring.mybatis.version>
<spring.redis.version>2.9.0</spring.redis.version>
<guava.version>20.0</guava.version>
</properties>
<!-- maven依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.hd</groupId>
<artifactId>kp-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.hd</groupId>
<artifactId>kp-service-customer-back</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.hd</groupId>
<artifactId>kp-service-customer-mid</artifactId>
<version>${project.version}</version>
</dependency>
<!-- spring-boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>${spring.cloud.feign.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<version>${spring.cloud.consul.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${spring.mybatis.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${spring.redis.version}</version>
</dependency>
<!-- hd -->
<dependency>
<groupId>com.hd</groupId>
<artifactId>kp-service-customer-back</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!-- jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>${spring.cloud.feign.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<version>${spring.cloud.consul.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies>
</project>
spring-cloud-starter-openfeign、spring-cloud-starter-consul-discovery重点引入这两个jar
提供方(kp-service-customer-back)
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>proj-hd-parent</artifactId>
<groupId>com.hd</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>kp-service-customer-back</artifactId>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
</dependency>
<dependency>
<groupId>com.hd</groupId>
<artifactId>kp-core</artifactId>
</dependency>
</dependencies>
<build>
<finalName>sentinel-dashboard</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<mainClass>com.hd.pk.CustomerApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>${maven.deploy.version}</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/webapp/</directory>
<excludes>
<exclude>resources/node_modules/**</exclude>
</excludes>
</resource>
</resources>
</build>
</project>
@SpringBootApplication
@EnableDiscoveryClient
public class CustomerApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerApplication.class, args);
}
}
yml文件:
server:
port: 10086
consul-server-ip-address: 192.168.x.xx #consul服务地址
spring:
application:
name: kp-service-customer-back
cloud:
consul:
host: ${consul-server-ip-address}
port: 8500
discovery:
prefer-ip-address: true
service-name: ${spring.application.name}
# hostname: ${spring.cloud.client.ip-address} #默认本机
port: ${server.port}
health-check-interval: 10s
heartbeat:
enabled: true
Controller
@RestController
@RequestMapping("/back")
public class BackController {
@RequestMapping(value = "/test", method = RequestMethod.POST)
public Response<String> getInfo(@RequestBody CustomerEntity customerEntity){
Response<String> response = new Response<>();
response.setCode(0);
response.setData("hello world");
return response;
}
}
调用方(kp-service-customer-mid)
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>proj-hd-parent</artifactId>
<groupId>com.hd</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>kp-service-customer-mid</artifactId>
<name>kp-service-customer-mid</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.hd</groupId>
<artifactId>kp-core</artifactId>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class App
{
public static void main( String[] args ){
SpringApplication.run(App.class, args);
}
}
yml:
server:
port: 10087
consul-server-ip-address: 192.168.x.xx
spring:
application:
name: kp-service-customer-mid
cloud:
consul:
host: ${consul-server-ip-address}
port: 8500
discovery:
prefer-ip-address: true
service-name: ${spring.application.name}
hostname: ${spring.cloud.client.ip-address}
port: ${server.port}
health-check-interval: 10s
heartbeat:
enabled: true
Controller
@RestController
@RequestMapping("/mid")
public class MidController {
@Resource
private CustomerServiceFeign customerServiceFeign;
@RequestMapping(value = "/test", method = RequestMethod.GET)
public Response getInfo(){
CustomerEntity customerEntity = new CustomerEntity();
customerEntity.setAccountId(123344L);
Response<String> customerEntity1 = customerServiceFeign.getCustomerEntity(customerEntity);
return customerEntity1;
}
}
kp-core 模块可以新建公共类和公共配置类可以放在此模块,以供多个模块共享。
CustomerServiceFeign 类:
@FeignClient(value = "kp-service-customer-back", configuration = FeignConfig.class)
public interface CustomerServiceFeign {
/**
* 获取客户实体
* @param customerEntity
* @return
*/
@RequestMapping(value = "/back/test", method = RequestMethod.POST)
Response<String> getCustomerEntity(@RequestBody CustomerEntity customerEntity);
}
FeignConfig 类Feign相关配置
@Configuration
public class FeignConfig {
@Bean
public Retryer feignRetryer() {
return new Retryer.Default(100, TimeUnit.SECONDS.toMillis(1), 3);
}
@Bean
public Request.Options feginOption() {
Request.Options option = new Request.Options(3000, 5000);
return option;
}
}
分别启动服务模块和调用模块后,通过浏览器请求:http://localhost:10087/mid/test
consul注册服务要先配置好并启动,启动后看到服务已经注册上去:
至此spring cloud基于feign结合consul注册中心实现微服务已经完成。
这里需要注意一点,
开始在实现过程中发现一个问题,请求URL的时候总是报:
java.lang.NoClassDefFoundError: com/google/common/reflect/TypeToken,
再请求抛异常
java.lang.NoClassDefFoundError: Could not initialize class com.netflix.client.config.CommonClientConfigKey
经排查和结合网上资料是由于没引入com.google.guava依赖,引入后就没问题了。