SpringCloud 商城系统搭建之Feign
Spring Cloud 服务调用方式
Spring Cloud有两种服务调用方式,一种是Ribbon + RestTemplate,另一种是feign。在这一篇文章首先讲解下基于Feign。
Feign简介
Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编码器和解码器。Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。
简而言之:
- Feign 采用的是基于接口的注解
- Feign 整合了ribbon,具有负载均衡的能力
- 整合了Hystrix,具有熔断的能力
前提
本文是基于SpringCloud 商城系统搭建之eureka
创建supermarker 项目的子项目(supermarker-feign-consume),并在pom.xml 添加相关依赖.
pom.xml
<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>
<parent>
<groupId>com.zzg</groupId>
<artifactId>supermarker</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>supermarker-feign-consume</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--srping-boot-actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
Feign消费者配置
1、在supermarker-feign-consume启动类上加@EnableFeignClients注解:开启Feign的功能
package com.zzg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class EurekaFeignConsumeApplication {
public static void main(String[] args) {
// TODO Auto-generated method stub
SpringApplication.run(EurekaFeignConsumeApplication.class, args);
}
}
2、打开fFeign消费者的application.properties,添加如下配置
server.port=8085
spring.application.name=fegin
#
eureka.client.register-with-eureka=false
# 和eureka服务器通讯的URL
eureka.client.service-url.defaultZone=http://localhost:8081/eureka/
eureka.instance.instance-id=consumer-fegin
#spring-boot-actuator配置
#开放所有的web Endpoints
management.endpoints.web.exposure.include=*
3、定义一个feign接口,通过@ FeignClient(“服务名”),来指定调用哪个服务。
package com.zzg.inter;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.zzg.entity.User;
@FeignClient(value = "provider")
public interface FeignServiceInter {
@RequestMapping(value = "/user",method = RequestMethod.GET)
public User findById(@RequestParam(value = "id") Integer id);
}
注意:服务名来源于生产者的spring.application.name 属性值,也可以通过eurake 注册中心找到
4、调用生产者,通过Feign 定义的接口调用
package com.zzg.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.zzg.entity.User;
import com.zzg.inter.FeignServiceInter;
@RestController
public class UserController {
@Autowired
private FeignServiceInter feignServiceInter;
@GetMapping("/user")
public User findById(@RequestParam(value = "id") Integer id) {
return feignServiceInter.findById(id);
}
}
补全实体对象User 定义:
package com.zzg.entity;
import java.util.Date;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class User {
private Integer useId;
private String useName;
private String useSex;
private Integer useAge;
private String useIdNo;
private String usePhoneNum;
private String useEmail;
private Date createTime;
private Date modifyTime;
private String useState;
}
5、启动EurekaFeignConsumeApplication,浏览器访问http://localhost:8085/user?id=3,出现如下界面证明基于Feign的消费者创建成功
备注:修改两个生产者功能接口
supermarker-provider
package com.zzg.controller;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.zzg.dao.UserRepository;
import com.zzg.entity.User;
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@Value("${server.port}")
private int port;
@GetMapping("/user")
public User findById(@RequestParam(value = "id") Integer id) {
System.out.println("---------------provider端口被调用--------------" + port);
return userRepository.findOne(new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
// TODO Auto-generated method stub
List<Predicate> predicates = new ArrayList<Predicate>();
// 用户编号
predicates.add(criteriaBuilder.equal(root.<Integer> get("useId"), id));
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}
}).orElse(null);
}
}
supermarker-provider-second
package com.zzg.controller;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.zzg.dao.UserRepository;
import com.zzg.entity.User;
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@Value("${server.port}")
private int port;
@GetMapping("/user")
public User findById(@RequestParam(value = "id") Integer id) {
System.out.println("---------------provider-second端口被调用--------------" + port);
return userRepository.findOne(new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
// TODO Auto-generated method stub
List<Predicate> predicates = new ArrayList<Predicate>();
// 用户编号
predicates.add(criteriaBuilder.equal(root.<Integer> get("useId"), id));
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}
}).orElse(null);
}
}
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。