公众号
关注公众号和我一起学习哦!
一、什么是Feign
Feign
是一个声明式的模板化的
HTTP
客户端,它使得写 Http 客户端变得更简单。使用 Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用 Feign 注解和 JAX-RS 注解。Feign 支持可插拔的编码器和解码器。Feign 默认集成了 Ribbon,并和 Eureka 结合,默认实现了
负载均衡
的效果
-
Feign 采用的是基于接口的注解
-
Feign 整合了
ribbon
-
Feign 整合了
Hystrix
二、创建公共模块
为了减少代码的冗余 提升代码精简程度
1. 创建一个新的模块 选择 Mavne项目
spring-cloud-netflix-common
2. 添加Lombok的依赖
什么是Lombok ? 传送门:
地址
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
3. 创建 User 实体类
package cn.yufire.pojo;
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private static final long serialVersionUID = -3064610191893595688L;
private String userName;
private String passWord;
private Integer age;
}
4. 创建 UserService接口
package cn.yufire.service;
import cn.yufire.pojo.User;
import java.util.List;
public interface UserService {
/**
* 创建查询用户的接口
*
* @return
*/
List<User> queryAll();
}
5. 打包 并 安装到本地
mvn install
二、创建服务提供者
1. 创建一个新的模块 选择SpringBoot项目 名称为:
spring-cloud-netflix-user-provider
本次以用户服务提供者为例子 不涉及操作数据库
操作数据库的步骤 之前怎么写现在就这么写
2. 添加用户服务提供者所需的依赖 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.yufire</groupId>
<artifactId>spring-cloud-netflix-user-provider</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>spring-cloud-netflix-user-provider</name>
<description>用户服务提供者</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--添加SpringBoot的Web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--添加 Eureka的客户端依赖 注意后边是 client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--依赖公共模块-->
<dependency>
<groupId>cn.yufire</groupId>
<artifactId>spring-cloud-netflix-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!--Spring Cloud 父级依赖-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
与创建 Eureka客户端的依赖一致 需要其他功能自行添加依赖
3. 修改配置文件
spring:
application:
name: user-provider # 配置服务名称
eureka:
instance:
lease-renewal-interval-in-seconds: 1=
lease-expiration-duration-in-seconds: 2
instance-id: ${spring.cloud.client.ip-address}:${server.port} # 配置当前服务在 注册中心中显示的 ip + 端口号
client:
service-url: # 可以在路径中配置用户名密码
defaultZone: http://root:root@127.0.0.1:9988/eureka
server:
port: 9000 # 客户端运行的端口
4. 开启Eureka客户端
package cn.yufire.spring.cloud.netflix.user.provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
public class SpringCloudNetflixUserProviderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudNetflixUserProviderApplication.class, args);
}
}
5. 编写用户Service的实现类
由于不需要连接数据库 所以不需要编写 Mapper接口
package cn.yufire.spring.cloud.netflix.user.provider.serviceimpl;
import cn.yufire.pojo.User;
import cn.yufire.service.UserService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
public class UserServiceImpl implements UserService {
@RequestMapping("/queryAll")
@Override
public List<User> queryAll() {
List<User> users = new ArrayList<>();
// 添加假数据
for (int i = 1; i < 4; i++) {
User user = new User();
user.setUserName("张" + i);
user.setPassWord(String.valueOf((Math.random() * 1000)));
user.setAge(i);
users.add(user);
}
return users;
}
}
由于Feign是使用HTTP进行远程调用的 所以需要把用户Service实现类 使用 @RestController进行标注 才可以被外界访问到
6. 查看Eureka注册中心是否有我们的 用户服务提供者
7. 由于Feign是使用Rest方式进行调用所以可以直接测试访问该接口
成功 !
三、创建服务消费者
1. 创建一个新的模块 选择SpringBoot项目 名称为:
spring-cloud-netflix-user-consumer
2. 添加所需要的依赖 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.yufire</groupId>
<artifactId>spring-cloud-netflix-user-consumer</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>spring-cloud-netflix-user-consumer</name>
<description>用户服务消费者</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--添加SpringBoot的Web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--添加 Eureka的客户端依赖 注意后边是 client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--添加 openFeign的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!--Spring Cloud 父级依赖-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
主要添加了 OpenFeign的依赖
<!--添加 openFeign的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
3. 修改配置文件
spring:
application:
name: user-consumer
eureka:
instance:
lease-renewal-interval-in-seconds: 1 # 每间隔1s,向服务端发送一次心跳,证明自己依然存活
lease-expiration-duration-in-seconds: 2 # 告诉服务端,如果我2s之内没有给你发心跳,就代表我挂掉了,将我踢出掉。
instance-id: ${spring.cloud.client.ip-address}:${server.port} # 配置当前服务在 注册中心中显示的 ip + 端口号
client:
service-url: # 可以在路径中配置用户名密码
defaultZone: http://root:root@127.0.0.1:9988/eureka
server:
port: 10000 # 运行在 10000端口
4. 配置启动类
package cn.yufire.spring.cloud.netflix.user.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
@EnableEurekaClient // 开启 Eureka客户端
@EnableFeignClients // 开启 Feign客户端
@SpringBootApplication
public class SpringCloudNetflixUserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudNetflixUserConsumerApplication.class, args);
}
}
5. 在Consumer中创建 UserService
我们需要使用 这个UserService来调用 provider中的UserService实现类
package cn.yufire.spring.cloud.netflix.user.consumer.service;
import cn.yufire.pojo.User;
import cn.yufire.spring.cloud.netflix.user.consumer.fullback.UserServiceFullBack;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
// 使用 FeignClient注解来标注这个类是Fegin客户端 name属性为 provider项目的 application.name 一定要一致 否则将调用错误
@FeignClient(name = "user-provider")
public interface UserService {
@RequestMapping("/queryAll")
List<User> queryAll();
}
6. 创建 Controller
正常调用即可
注意 UserService的导包 是Consumer中的userService 不是 公共类的UserService
package cn.yufire.spring.cloud.netflix.user.consumer.controller;
import cn.yufire.pojo.User;
import cn.yufire.spring.cloud.netflix.user.consumer.service.UserService; // 注意包
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/queryAll")
public List<User> queryAll() {
return userService.queryAll();
}
}
7. 启动项目
8. 测试访问
出现返回的数据即为成功 !
四、传递参数
在我们访问接口的时候肯定是需要传递参数的
传递参数我分为了以下两种情况 :
- 基本Java数据类型
- 引用数据类型
1. 传递Java数据类型
1. 在公共模块的 Service 中添加一个新的接口
/**
* 传递Java数据类型参数
*
* @param content
* @return
*/
String sayHi(String content, Integer age);
2. 在provider中实现该接口
需要在形参前 添加
@RequertParam
注解进行标注 才可以正常的传递参数
@Override
@RequestMapping("/sayHi")
public String sayHi(@RequestParam("content") String content, @RequestParam("age") Integer age) {
return "Hello Spring Cloud Netflix!" + content + "\t" + age;
}
3. 在 consumer 中的 UserService中添加该接口
需要在形参前 添加
@RequertParam
注解进行标注 才可以正常的传递参数
如果只有一个参数 可以忽略
@RequertParam
注解
@RequestMapping("/sayHi")
String sayHi(@String content, Integer age);
4. 在UserController中注册请求接口
正常接收参数即可
@GetMapping("/sayHi")
public String sayHi(String content, Integer age) {
return userService.sayHi(content, age);
}
5. 重启项目
6. 测试访问
出现以上内容即为成功 !
2. 传递引用数据类型
我们在传递数据的时候 可能会遇到要同时传递多个参数的情况
针对这种情况 我们可以使用 Map 或者 对象来进行数据的传递
1. 传递一个引用类型
在公共模块的UserService中添加两个接口
/**
* 传递Map类型的参数
*
* @param paramMap
* @return
*/
String paramMap(Map<String, Object> paramMap);
/**
* 传递对象参数
* @param user
* @return
*/
User getUserInfo(User user);
2. 在provider中实现该接口
由于传递的参数是引用类型 我们将接收参数的注解改为
@RequestBody
使用JSON格式传递
/**
* 使用 Map 作为参数传递
* 获取 用户名 密码
* @param paramMap
* @return
*/
@Override
@RequestMapping("/paramMap")
public String paramMap(@RequestBody Map<String, Object> paramMap) {
System.out.println(paramMap.get("username"));
System.out.println(paramMap.get("password"));
return (paramMap.get("username").toString() + paramMap.get("password").toString());
}
/**
* 使用 User 作为参数传递
* 获取用户信息
*
* @param user
* @return
*/
@Override
@RequestMapping("/getUserInfo")
public User getUserInfo(@RequestBody User user) {
System.out.println(user);
return user;
}
3. 在 Consumer中的UserService中添加这两个接口
/**
* 传递Map类型的参数
*
* @param paramMap
* @return
*/
String paramMap(Map<String, Object> paramMap);
/**
* 传递对象参数
* @param user
* @return
*/
User getUserInfo(User user);
4. 在Controller中创建请求接口
@GetMapping("/paramMap")
public String paramMap(String username, String pwd) {
Map paramMap = new HashMap<>();
paramMap.put("username", username);
paramMap.put("password", pwd);
System.out.println(paramMap);
return userService.paramMap(paramMap);
}
@RequestMapping("/getUserInfo")
public User getUserInfo(User user) {
return userService.getUserInfo(user);
}
5. 测试访问
paramMap
接口
测试结果 返回的是 用户名和密码
6. 测试访问
getUserInfo
接口
测试结果
小结
1. 传递 Java数据类型的时候 只需要添加
@RequestParam
注解即可
2. 传递引用类型的时候 只需要添加
@RequestBodu
注解即可正常传递