SpringCloud 商城系统搭建之Feign

java哥 阅读:623 2021-03-31 13:18:51 评论:0

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.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号