SpringCloud的服务间通信主要有两种办法,一种是使用Spring自带的RestTemplate,另一种是使用Feign,这里主要介绍后者的通信方式。
整个实例一共用到了四个项目,一个Eureka注册中心,一个服务调用组件、一个服务提供组件、独立的api接口项目。
eureka注册中心这里就不多说了,具体的配方式没有什么变化。
Feign的接口申明方式有很多种,这里使用了Feign的“继承特性”,将对外接口从控制器中剥离了出来,配合maven仓库实现接口共享。
被剥离的api接口
创建一个独立的maven项目,这个项目里面装的都是各个服务的对外接口。
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"> <modelVersion>4.0.0</modelVersion> <groupId>pers.cly</groupId> <artifactId>demo-api</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <name>demo-api</name> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
注意此处的<groupid>、<artifactid>、<version>三个标签,这三个标签共同构成了每个项目的唯一标识,后面需要通过这三个标签将该项目引入其他maven项目中。
下面这个是我这次创建的实例接口,对外提供的是一个login方法,相当于是user控制器。
IUserService.java:
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @RequestMapping("/user") public interface IUserService { @RequestMapping(value="/login",method=RequestMethod.POST) String login( @RequestParam("user_name")String user_name, @RequestParam("user_psw")String user_psw); }
服务提供方
pom.xml中需要引入以下三个依赖,需要注意的是下面第三个依赖是刚刚我们创建的接口项目的依赖标识。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>pers.cly</groupId> <artifactId>demo-api</artifactId> <version>1.0.0</version> </dependency> </dependencies>
项目的启动入口ProducerServerApplication.java
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @EnableDiscoveryClient @SpringBootApplication public class ProducerServerApplication { public static void main(String[] args) { SpringApplication.run(ProducerServerApplication.class, args); } }
控制器。控制器需要实现自己对应的api接口,我们之所以引入api接口项目依赖也是为了这个。
import org.springframework.web.bind.annotation.RestController; import com.api.service.IUserService; @RestController public class ProducerController implements IUserService{ @Override public String login(String user_name, String user_psw) { return "用户名:"+user_name+",密码:"+user_psw; } }
服务调用方
pom.xml,与服务提供方一样,调用方也得引入自建的api依赖。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> <dependency> <groupId>pers.cly</groupId> <artifactId>demo-api</artifactId> <version>1.0.0</version> </dependency> </dependencies>
服务启动入口ConsumerServerApplication.java,要加@EnableFeignClients注解
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.feign.EnableFeignClients; @EnableFeignClients @EnableDiscoveryClient @SpringBootApplication public class ConsumerServerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerServerApplication.class, args); } }
在本地创建一个接口继承被剥离的api接口,之后我们操作的都是这个自建接口。此处这个自建接口里不需再创建什么新方法了。
IRefactorUserService.java
import org.springframework.cloud.netflix.feign.FeignClient; import com.api.service.IUserService; //定义FeignClient的名称,如果项目使用了Ribbon,value值会作为微服务的名称,用于服务发现 @FeignClient(value = "hello-service") public interface IRefactorUserService extends IUserService{ }
控制器中可以通过之前的自建接口使用相应的其他组件提供的服务
ConsumerController.java
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.consumer.feign.inf.IRefactorUserService; @Controller @RequestMapping(value = "/consumer") public class ConsumerController { @Autowired IRefactorUserService iRefactorUserService; @RequestMapping(value="/feign-consumer",method=RequestMethod.GET) @ResponseBody public String hello() { return iRefactorUserService.login("xiaoming", "12345"); } }