咱们在进行微服务项目的开发的时候,常常会遇到一个问题,好比A服务是一个针对用户的服务,里面有用户的增删改查的接口和方法,而如今我有一个针对产品的服务B服务中有一个查找用户的需求,这个时候咱们能够在B服务里再写一个查找用户的接口,但是就为了一个接口就得从控制层到持久层都写一遍怎么看都不值当,最关键的是这个接口在别的服务里面还有,这就更不该该作了,因此springCloud提供了服务调用的方法——feign。java
因为以前写的都是springboot的例子,因此一直都只有一个服务,此次既然是服务调用,必然有一个服务提供者和消费者,若是要让这两个服务联系起来,就得用到springCloud的那一套东西,因此意味着咱们还得要一个服务注册中心eureka,先把eureka注册中心的代码贴一下。web
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
相比以前的springboot启动类,这里多了一个@EnableEurekaServer注解,此注解的做用就是启用一个服务注册中心以提供给其余服务进行对话。spring
配置文件application.propertiesapache
#服务注册中心实例的主机名
eureka.instance.hostname=localhost
#是否向服务注册中心注册本身
eureka.client.register-with-eureka=false
#是否检索服务
eureka.client.fetch-registry=false
#服务注册中心的配置内容,指定服务注册中心的位置
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
#服务注册中心端口号
server.port=8763
每一个配置项上面注释都解释了,其中第二个注解若是选择true的话,在注册中心启动后便会存在一个服务即自己,但大部分状况都是写的faslejson
<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.fh.msDemo</groupId> <artifactId>service-eureka</artifactId> <version>0.0.1-SNAPSHOT</version> <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.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
把以上三个文件在相应位置建好以后,把服务一块儿输入“主机名”+“端口”便可访问注册中心,按照我上面的配置输入的是localhost:8763或者127.0.0.1:8763浏览器
效果以下:springboot
由于我默认了不注册本身,因此目前没有实例。app
好了,再来看一下两个业务服务,首先是服务提供者用户服务service-user,这里为了简单起见,只在controller中模拟查询的业务场景负载均衡
package com.fc.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class UserApplication{ public static void main(String[] args) { SpringApplication.run(UserApplication.class, args); } }
能够看到和springboot项目不一样的是这个服务多了一个注解@EnableEurekaClient,该注解的做用就是以eureka做为服务注册中心将服务注册上去。框架
package com.fc.demo.controller; import java.util.ArrayList; import java.util.List; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.fc.demo.pojo.User; @RestController public class UserController { @RequestMapping("/user/list") public List<User> getUser() { List<User> users = new ArrayList<>(); users.add(new User(1, "小明", 13)); users.add(new User(2, "小华", 15)); return users; } }
#服务注册中心的地址
eureka.client.service-url.defaultZone=http://localhost:8763/eureka/
#服务端口号
server.port=8768
#服务名称
spring.application.name=user
最后是服务消费者产品服务service-product
package com.fc.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.feign.FeignClient;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class ProductApplication{
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
}
与上一个服务相比,此服务又多了一个注解@EnableFeignClients,该注解的做用是:告诉框架扫描全部经过注解@Feignclient定义的feign客户端,也就是说若是不加这个注解,框架将找不到全部的feign客户端。
package com.fc.demo.feign; import java.util.List; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.cloud.netflix.feign.FeignClientsConfiguration; import org.springframework.web.bind.annotation.RequestMapping; import com.fc.demo.pojo.User; @FeignClient(value="user",configuration = {FeignClientsConfiguration.class}) public interface UserFeign { @RequestMapping("/user/list") public List<User> getAllUser(); }
只要@FeignClient注解中的value值和服务提供者的服务名保持一致便可。
package com.fc.demo.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.fc.demo.feign.UserFeign; import com.fc.demo.pojo.User; @RestController public class ProductController { @Autowired private UserFeign userFeign; @RequestMapping("user/list") public List<User> showUser() { return userFeign.getAllUser(); } }
前面也提到了@EnableFeignClients注解将全部的feign客户端注入了容器中,直接使用自动装配的注解的即可使用feign客户端
#服务注册中心的地址
eureka.client.service-url.defaultZone=http://localhost:8763/eureka/
#服务端口号
server.port=8767
#服务名称
spring.application.name=product
把三个服务同时跑起来,注册中心截图以下
显示两个服务已经注册成功了。接下来在浏览器中输入http://localhost:8767/user/list,成功返回json串
此外,feign还具备负载均衡的功能,修改user服务的controller,新增一个返回端口号的方法
package com.fc.demo.controller; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.fc.demo.pojo.User; @RestController public class UserController { @Value("${server.port}") private String port; //获取配置文件中的端口号 /**获取用户列表*/ @RequestMapping("/user/list") public List<User> getUser() { List<User> users = new ArrayList<>(); users.add(new User(1, "小明", 13)); users.add(new User(2, "小华", 15)); return users; } /**获取服务端口号*/ @RequestMapping("/user/port") public String getPort() { return port; } }
在product服务里面的UserFeign接口和controller中增长相应的方法
package com.fc.demo.feign; import java.util.List; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.cloud.netflix.feign.FeignClientsConfiguration; import org.springframework.web.bind.annotation.RequestMapping; import com.fc.demo.pojo.User; @FeignClient(value="user",configuration = {FeignClientsConfiguration.class}) public interface UserFeign { /**获取用户列表*/ @RequestMapping("user/list") public List<User> getAllUser(); /**获取服务端口号*/ @RequestMapping("user/port") public String getPort() ; }
package com.fc.demo.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.fc.demo.feign.UserFeign; import com.fc.demo.pojo.User; @RestController public class ProductController { @Autowired private UserFeign userFeign; /**获取用户列表*/ @RequestMapping("user/list") public List<User> showUser() { return userFeign.getAllUser(); } /**获取服务端口号*/ @RequestMapping("/user/port") public String getPort() { return "调用的服务端口号为"+userFeign.getPort(); } }
把服务跑起来之后,修改user服务配置文件中的端口号改成8769,再次跑一遍,这时eureka上显示user服务有两个实例,端口号分别为8767和8769,屡次刷新浏览器
效果基本就是这样,采用轮询机制调用两个user实例。
feign的基本用法就是这样,目前本人对于springcloud和feign的了解也仅限于此,只知道基本的用法,对于其原理机制一律不知,因此还得继续深究下去,如有收获则会完善该系列后续的博客。