声明式服务调用Feign
1、feign介绍
1)什么是feign?
feign是spring cloud提供的声明式的http客户端,工作在consumer端
feign支持springmvc注解
feign集成ribbon也支持负载均衡(restTemplate+ribbon=feign)
2)feign启动器
spring-cloud-starter-openfeign
2、feign入门案例
1)创建服务提供者feign_provider
pom
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>springcloud_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
service
package com.bjpoernode.service;
import com.bjpowernode.pojo.User;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService{
@Override
public User getUserById(Integer id) {
return new User(id,"王粪堆1",18);
}
}
contrller
package com.bjpoernode.controller;
import com.bjpoernode.service.UserService;
import com.bjpowernode.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/provider")
public class ProviderController {
@Autowired
private UserService userService;
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable Integer id){
return userService.getUserById(id);
}
}
app
package com.bjpoernode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApp {
public static void main(String[] args) {
SpringApplication.run(ProviderApp.class);
}
}
server:
port: 9090
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.10.135:8848 #nacos服务的地址
application:
name: feign-provider #向注册中心注册的名字
2)创建接口feign_interface
pom
<dependencies>
<!--Spring Cloud OpenFeign Starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>springcloud_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
写一个feign接口
package com.bjpowernode.feign;
import com.bjpowernode.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
//问题1:feign的运行原理?
@FeignClient("feign-provider")
@RequestMapping("/provider")
public interface UserFeign {
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable("id") Integer id);//问题2:?必须("id")
}
3)创建服务消费者ribbon_consumer:
pom
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>springcloud_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--feign接口-->
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>feign_interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
config
package com.bjpowernode.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ConfigBean {
@Bean
/**
* 1.在RestTemplate上添加@LoadBalanced后,ribbon会给RestTemplate的请求添加拦截器
* 2.在拦截器中根据serverId获得List<Service>,然后再使用ribbon的负载均衡算法从
* List<Service>获得 一个service
* 3.最后再把serverId换成ip和端口
*/
@LoadBalanced //开启ribbon负载均衡,默认是轮询策略
public RestTemplate restTemplate(){
return new RestTemplate();
}
//随机策略
@Bean
public IRule iRule(){
return new RandomRule();
}
}
contrller
package com.bjpowernode.controller;
import com.bjpowernode.feign.UserFeign;
import com.bjpowernode.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
import java.util.Random;
@RestController
@RequestMapping(value = "/consumer")
public class ConsumerController {
@Autowired
private UserFeign userFeign;
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable Integer id){
return userFeign.getUserById(id);
}
}
app
package com.bjpowernode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients //开启feign
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class);
}
}
application.yml
server:
port: 8080
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.10.135:8848 #nacos服务的地址
application:
name: feign-consumer #向注册中心注册的名字
3.Feign参数传递
传参方式:
- restful风格:
feign接口:@PathVarible
【拼接restful形式的url】
- ?传参
feign接口:@RequestParam
【拼接?形式的url】
- pojo参数
provider: @RequestBody User user
【获取请求体中的json串】