SpringCloud学习第六篇:Feign学习(Greenwich-SR1版本)

一、Feign是什么?

  Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单,它的使用方法就是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可插拔式的编码器和解码器。SpringCloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。在Spring Cloud feign的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。

二、工程的搭建

2.1、eureka搭建(spring-cloud-eureka-server)

  • Maven
<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.yk</groupId>
		<artifactId>cloud-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>springcloud-eureka-server</artifactId>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		</dependency>
	</dependencies>
  • application.yml
spring:
  application:
    name: spring-cloud-eureka-server
server:
  #使用启动命令覆盖默认的801
  port: 1234

eureka:
  client:
    ##让自己不需要注册在上面禁止客户端注册,表明自己是一个eureka server
    register-with-eureka: false
    fetch-registry: false
    service-url:
      #服务注册
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
  instance:
    hostname: localhost
  • 入口类
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaServer
public class EurekaServerApplication {
	public static void main(String[] args) {
		SpringApplication.run(EurekaServerApplication.class, args);
	}
}

2.2、公共接口搭建(springcloud-api)

  • Maven
 <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yk</groupId>
        <artifactId>cloud-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>springcloud-api</artifactId>
    <dependencies>
        <!-- 服务调用 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
  • entity
@Data
public class User {

    /**
     * ID
     */
    private Long id;

    /**
     * 用户名称
     */
    private String name;

}
  • service
//声明Feign客户端,使用占位符方式防止硬编码,如果没有使用eureka需要指定url=ip地址+端口,fallback回调地址
@FeignClient(name="${user.service.name}",fallback = UserFallback.class)
public interface UserService {
    /**
     * 保存用户
     * @param user
     */
    @PostMapping("/user/save")
    boolean saveUser( User user);
    /**
     * 查询所有的用户列表
     */
    @GetMapping("/user/find/all")
    List<User> findAll();
}
  • fallback
/**
* @description:   熔断的回调
* @create: 2019年06月19日 21时16分
**/
public class UserFallback implements UserService {

    @Override
    public boolean saveUser(User user) {
        return false;
    }

    @Override
    public List<User> findAll() {
        return Collections.emptyList();
    }
}

2.3、服务提供者工程(spring-cloud-api-provider)

  • Maven
 <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yk</groupId>
        <artifactId>cloud-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>springcloud-api-provider</artifactId>
    <dependencies>
        <!-- 依赖 API -->
        <dependency>
            <groupId>com.yk</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!-- 依赖 Spring Cloud Netflix Hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!-- 依赖 Spring Cloud eureka client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
  • application.properties
## 用户服务提供方应用信息
spring.application.name = spring-cloud-api-provider

## 服务端口
server.port = 801
        
#配置eureka
eureka.client.serviceUrl.defaultZone = http://localhost:1234/eureka/
eureka.instance.hostname = localhost
eureka.instance.prefer-ip-address = true
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}

  • 启动入口类
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableHystrix  //熔断器 
@EnableDiscoveryClient //eureka
public class ApiProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiProviderApplication.class, args);
    }

}

  • ServiceImpl
@Service
public class  UserServiceImpl implements UserService {

    private Map<Long, User> repository = new ConcurrentHashMap<>();
    @Override
    public boolean saveUser(User user) {
        return repository.put(user.getId(), user) == null;
    }

    @Override
    public List<User> findAll() {
        return new ArrayList(repository.values());
    }
}

  • Controller
@RestController
public class UserController {
    @Autowired
    private UserService userService;
    
    @PostMapping("/user/save")
    public boolean saveUser(@RequestBody  User user) {
        return userService.saveUser(user);
    }

    
    @HystrixCommand(
            // Command 配置,设置操作时间为 100 毫秒
            commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "100")},
            // 设置 fallback 方法
            fallbackMethod = "fallbackForGetUsers"
    )
    @GetMapping("/user/find/all")
    public List<User> findAll() {
        return userService.findAll();
    }

    
    /**
     * 超过100毫秒就返回空集合
     * @return
     */
    public List<User> fallbackForGetUsers() {
        return Collections.emptyList();
    }
}

2.4、服务调用者工程(spring-cloud-api-client)

  • Maven
 <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yk</groupId>
        <artifactId>cloud-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>springcloud-api-client</artifactId>
    <dependencies>
        <!-- 依赖API -->
        <dependency>
            <groupId>com.yk</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!-- 依赖 Spring Cloud Netflix Hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

  • application.properties
spring.application.name = spring-cloud-api-client
## 服务端口
server.port = 802

## 提供方服务名称
provider.service.name = spring-cloud-api-provider

#配置@FeignClient(name="${user.service.name}")中的占位符
#user.service.name实际需要指定UserService接口的提供方,也就是spring-cloud-api-provider
user.service.name = ${provider.service.name}

#配置eureka
eureka.client.serviceUrl.defaultZone = http://localhost:1234/eureka/
eureka.instance.hostname = localhost
eureka.instance.prefer-ip-address = true
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}

  • 启动入口类
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
// 使用客户端短路
@EnableCircuitBreaker
//声明 UserService接口作为Feign Client 调用
@EnableFeignClients(clients = UserService.class)
@EnableDiscoveryClient
public class ClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }
}

  • Controller
@RestController
public class FeignUserController implements UserService {
    //UserService@FeignClient注解默认primary是true,相当于代理
    @Autowired
    private UserService userService;
  //这里使用Feign的继承特性,会将UserService里面的@RequestMapping继承过来但是@RequestBoday是不会继承过来的

    @Override
    public boolean saveUser(@RequestBody User user) {
        return userService.saveUser(user);
    }
 
    @Override
    public List<User> findAll() {
        return userService.findAll();
    }
}

猜你喜欢

转载自www.cnblogs.com/yangk1996/p/12663514.html