Feign介绍
Feign客户端是一个web声明式http远程调用工具,提供了接口和注解方式进行调用。它的目的就是让Web Service调用更加简单。
下面就用一个简单的微服务项目说明
项目结构:聚合项目,子父工程
项目获取地址:https://github.com/XiaoFengSophia/springcloud2.0-lancoo-parents
该案例中的member服务和order服务都是注册在Eureka注册中心集群中,关于Eureka注册中心集群的使用请点击springboot+springcloud+eureka实现高可用注册中心了解详情!
父工程pom.xml
<!-- SpringCloud 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot整合eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- SpringBoot整合feign客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
springcloud2.0-lancoo-api-member-service 接口
pom.xml(MemberService接口)
<dependencies>
<!-- 引入公共项目 -->
<dependency>
<groupId>lancoo</groupId>
<artifactId>springccloud2.0-lancoo-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
IMemberService
public interface IMemberService {
@RequestMapping("/getMember")
public UserEntity getMember(@RequestParam("name") String name);//这里必须加@RequestParam("name"),否则远程调用时参数为null
@RequestMapping("/getUserInfo")
public ResponseBase getUserInfo();
}
UserEntity
public class UserEntity {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public UserEntity(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public UserEntity() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "UserEntity [name=" + name + ", age=" + age + "]";
}
springcloud2.0-lancoo-api-member-service-impl 实现类
pom.xml
<!-- 引入member接口项目 -->
<dependency>
<groupId>lancoo</groupId>
<artifactId>springcloud2.0-lancoo-api-member-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
application.yml
#启动服务端口
server:
port: 8001
#服务名称(服务注册到Eureka注册中心)
spring:
application:
name: zxf-lancoo-member
#服务注册到Eureka地址
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8100/eureka,http://127.0.0.1:8200/eureka
#因为是注册中心,不会自己注册
register-with-eureka: true
#是否需要从eureka上获取注册信息
fetch-registry: true
MemberServiceImpl
@RestController
public class MemberServiceImpl extends BaseApiService implements IMemberService {
@Autowired
private LoadBalancerClient loadBalancerClient;
@RequestMapping("/getMember")
public UserEntity getMember(@RequestParam("name")String name) {//这里必须加@RequestParam("name"),否则远程调用时参数为null
// TODO Auto-generated method stub
UserEntity userEntity = new UserEntity();
userEntity.setName(name);
userEntity.setAge(20);
return userEntity;
}
}
AppMember 启动类
@SpringBootApplication
@EnableEurekaClient //开启Eureka客户端
@EnableFeignClients //开启Feign客户端
public class AppMember {
public static void main(String[] args) {
SpringApplication.run(AppMember.class, args);
}
}
springcloud2.0-lancoo-api-order-service 接口
pom.xml(OrderService)
<!-- 引入公共项目 -->
<dependency>
<groupId>lancoo</groupId>
<artifactId>springccloud2.0-lancoo-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
IOrderService
public interface IOrderService {
//订单服务调用会员服务接口信息 feign
@RequestMapping("/orderToMember")
public String orderToMember(String name);
//订单服务调用会员服务接口
@RequestMapping("/orderToMemberUserInfo")
public ResponseBase orderToMemberUserInfo();
//订单服务调用会员服务接口
@RequestMapping("/orderInfo")
public ResponseBase orderInfo();
}
springcloud2.0-lancoo-api-order-service-impl OrderService实现类
pom.xml
<!-- order接口项目 -->
<dependency>
<groupId>lancoo</groupId>
<artifactId>springcloud2.0-lancoo-api-order-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 引入member接口项目 -->
<dependency>
<groupId>lancoo</groupId>
<artifactId>springcloud2.0-lancoo-api-member-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
application.yml
#启动服务端口
server:
port: 8021
#服务名称(服务注册到Eureka注册中心)
spring:
application:
name: zxf-lancoo-order
#服务注册到Eureka地址
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka
#因为是注册中心,不会自己注册
register-with-eureka: true
#是否需要从eureka上获取注册信息
fetch-registry: true
###设置feign客户端超时时间
#springcloud feign默认开启支持ribbon
ribbon:
###指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间。
ReadTimeout: 5000
###指的是建立连接后从服务器读取到可用资源所用的时间。
ConnectTimeout: 5000
OrderServiceImpl
@RestController
public class OrderServiceImpl extends BaseApiService implements IOrderService {
//订单服务继承会员服务接口,用来实现feign客户端的调用,减少重复代码接口
@Autowired
private IMemberServiceFeign iMemberServiceFeign;
@RequestMapping("/orderToMember")
public String orderToMember(String name) {
// TODO Auto-generated method stub
UserEntity userEntity = iMemberServiceFeign.getMember(name);
return userEntity==null?"未找到任何信息":userEntity.toString();
}
}
IMemberServiceFeign
/**
* 继承的作用解决代码重复
* 订单服务继承会员服务接口,实现feign客户端的调用
* @author lancoo
*
*/
@FeignClient("zxf-lancoo-member")
public interface IMemberServiceFeign extends IMemberService {
}
AppOrder
@SpringBootApplication
@EnableEurekaClient //Eureka客户端
@EnableFeignClients //Feign客户端
public class AppOrder {
public static void main(String[] args) {
SpringApplication.run(AppOrder.class, args);
}
}
公共子模块
BaseApiService
@Component
public class BaseApiService {
public ResponseBase setResultError(Integer code,String msg) {
return setResult(code, msg,null);
}
//返回错误,可以传msg
public ResponseBase setResultError(String msg) {
return setResult(500,msg,null);
}
//返回成功,可以传data值
public ResponseBase setResultSuccess(Object data) {
return setResult(200,"处理成功",data);
}
//返回成功,没有data值
public ResponseBase setResultSuccess() {
return setResult(200,"处理成功",null);
}
//返回成功,没有data值
public ResponseBase setResultSuccess(String msg) {
return setResult(200,msg,null);
}
//通用封装
public ResponseBase setResult(Integer code,String msg,Object data) {
return new ResponseBase(code,msg,data);
}
}
ResponseBase
@Slf4j
public class ResponseBase {
private Integer rtnCode;
private String msg;
private Object data;
public ResponseBase() {
super();
// TODO Auto-generated constructor stub
}
public ResponseBase(Integer rtnCode, String msg, Object data) {
super();
this.rtnCode = rtnCode;
this.msg = msg;
this.data = data;
}
public Integer getRtnCode() {
return rtnCode;
}
public void setRtnCode(Integer rtnCode) {
this.rtnCode = rtnCode;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
@Override
public String toString() {
return "ResponseBase [rtnCode=" + rtnCode + ", msg=" + msg + ", data=" + data + "]";
}
}
访问member服务:http://127.0.0.1:8001/getMember?name=张三
order服务通过Feign客户端调用member http://127.0.0.1:8021/orderToMember?name=张三
解决方案在member服务的接口和接口的实现类相应方法的参数头加 @RequestParam("name")