SpringCloud(四)学习笔记之Feign

Feign是一个声明式的Web服务客户端,可帮助我们更加便捷、优雅地调用HTTP API

Feign可以与Eureka和Ribbon组合使用以支持负载均衡

一、构建Eureka Server

【基于第二章节创建的Eureka Server】

二、构建Eureka Client提供者集群项目

【基于第三章节构建的Eureka Client提供者集群项目】

1:提供者集群项目中创建controller

mhb-cloud-producer mhb-cloud-producer-extend
【创建UserVo对象】com\applesnt\vo\UserVo.java

package com.applesnt.vo;
import lombok.Data;

@Data
public class UserVo {

    private String user_id;

    private String user_name;

    private String code;

    public UserVo(String user_id, String user_name, String code) {
        this.user_id = user_id;
        this.user_name = user_name;
        this.code = code;
    }

    public UserVo() {
    }
}

mhb-cloud-producer :9904
mhb-cloud-producer-extend:9905

【创建Controller】com\applesnt\controller\FeignProducerController.java

package com.applesnt.controller;

import com.applesnt.vo.UserVo;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/producer")
public class FeignProducerController {

    /*返回传递过来的id
    * 请求路径:http://localhost:9904/producer/get/123
    * */
    @GetMapping("/get/{id}")
    public String getId(@PathVariable("id") String id){
        System.out.println("-----"+id);
        return "我是提供者 端口是9904 传递的参数= "+id;
    }

    /*参数为id  返回user对象
    * 请求路径:http://localhost:9904/producer/getuserbyid/123
    * */
    @GetMapping("/getuserbyid/{id}")
    public UserVo getUserById(@PathVariable("id") String id){
        UserVo userVo = new UserVo();
        userVo.setUser_id(id);
        userVo.setUser_name("applesnt");
        userVo.setCode("9904");
        return userVo;
    }

    /*
    * 返回user对象
    * 访问路径:http://localhost:9904/producer/getuser2?id=123&name=lisi
    * */
    @GetMapping("/getuser2")
    public UserVo getUser2(@RequestParam("id") String id,
                           @RequestParam("name") String name){
        UserVo userVo = new UserVo();
        userVo.setUser_id(id);
        userVo.setUser_name(name);
        userVo.setCode("9904");
        return userVo;
    }

    /*
    * 返回user对象
    * 访问路径:http://localhost:9904/producer/getuser3?user_id=123&user_name=lisi
    * */
    @GetMapping("/getuser3")
    public UserVo getUser3(UserVo userVo){
        userVo.setUser_id(userVo.getUser_id());
        userVo.setUser_name(userVo.getUser_name());
        userVo.setCode("9904");
        return userVo;
    }

    /*参数uservo  返回UserVo
    * postman body--raw(选择json格式)
    * 数据格式:{"user_id":"123","user_name":"zhangsan"}
    * */
    @PostMapping("/getuser")
    public UserVo getUser(@RequestBody UserVo userVo){
        return userVo;
    }

    /*返回UserVo集合
    *  请求路径:http://localhost:9904/producer/getlist/
    * */
    @GetMapping("/getlist")
    public List<UserVo> getUserList(){

        List<UserVo> voList = new ArrayList<>();
        UserVo userVo1 = new UserVo("1","zhangsan","9904");
        UserVo userVo2 = new UserVo("2","lisi","9904");
        UserVo userVo3 = new UserVo("3","wangwu","9904");
        voList.add(userVo1);voList.add(userVo2);voList.add(userVo3);

        return voList;
    }
}

三、创建Eureka消费者项目(基于Feign)

mhb-cloud-consumer-Feign:【端口 8801】

1:pom文件

<!--eureka客户端环境支持-->
<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>

2:application.yml文件

debug: false

spring:
  application:
    name: mhb-cloud-consumer-feign #每一个微服务必须有这个应用名称

server:
  port: 8801 #端口

eureka:
  instance:
    appname: consumer-feign #eureka application的名称
    prefer-ip-address: true #开启ip显示eureka的主机服务
    #eureka仪表盘的Instances格式
    instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}
  client:
    service-url:
     defaultZone: http://admin:123456@eureka1.com:8762/eureka/,http://admin:123456@eureka2.com:8762/eureka/,http://admin:123456@eureka3.com:8763/eureka/
    #从eureka服务器注册表中获取注册表信息的时间间隔,默认30s
    registry-fetch-interval-seconds: 30
    #客户端发送变化同步到eureka服务器的时间间隔 默认30s
    instance-info-replication-interval-seconds: 30
    #询问eureka服务url信息的变化的间隔时间 默认300s
    eureka-service-url-poll-interval-seconds: 300
    #最初同步到eureka服务器的时间 默认40s
    initial-instance-info-replication-interval-seconds: 40
    #注册表是否压缩
    g-zip-content: true
    #eureka等待超时时间 默认是5s
    eureka-server-connect-timeout-seconds: 5
    #eureka等待读取时间 默认是8s
    eureka-server-read-timeout-seconds: 8
    #eureka客户端允许的所有eureka服务器连接的总数 默认200
    eureka-server-total-connections: 200

3:启动类中开启Feign支持

@@EnableEurekaClient
@EnableFeignClients

package com.applesnt;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients //开启feign支持
public class MhbCloudConsumerFeignApplication {

	public static void main(String[] args) {
		SpringApplication.run(MhbCloudConsumerFeignApplication.class, args);
	}
}

4:构建Feign远程调用接口

@FeignClient(name = "mhb-cloud-producer",configuration = FeignClientsConfiguration.class)

com\applesnt\service\FeignClientService.java

package com.applesnt.service;

import com.applesnt.vo.UserVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/*
name:提供者的服务名称
configuration:使用默认配置类 FeignClientsConfiguration
默认配置支持springmvc注解
*/
@FeignClient(name = "mhb-cloud-producer",configuration = FeignClientsConfiguration.class)
public interface FeignClientService {

    /*value要写全路径
    * PathVariable一定要指定value值
    * */
    @GetMapping("/producer/get/{id}")
    public String getId(@PathVariable("id") String id);

    @GetMapping("/producer/getuserbyid/{id}")
    public UserVo getUserById(@PathVariable("id") String id);

    @GetMapping("/producer/getuser2")
    public UserVo getUser2(@RequestParam("id") String id,
                           @RequestParam("name") String name);

    /*
    * 如果传入复杂(vo类型)参数时 不支持get请求 远程调用对象必须要用post请求
    * 所以getUser3是调用失败的
    * */
    @GetMapping("/producer/getuser3")
    public UserVo getUser3(UserVo userVo);

    /*POST请求 如果是复杂对象 可以使用@RequestBody  也可以不使用*/
    @PostMapping("/producer/getuser")
    public UserVo getUser(@RequestBody UserVo userVo);

    @GetMapping("/producer/getlist")
    public List<UserVo> getUserList();
}

5:构建远程调用controller

【构建UserVo对象】com\applesnt\vo\UserVo.java

package com.applesnt.vo;
import lombok.Data;

@Data
public class UserVo {

    private String user_id;

    private String user_name;

    private String code;

    public UserVo(String user_id, String user_name, String code) {
        this.user_id = user_id;
        this.user_name = user_name;
        this.code = code;
    }

    public UserVo() {
    }
}

【构建远程调用Controller】com\applesnt\controller\FeignConsumerController.java

package com.applesnt.controller;

import com.applesnt.service.FeignClientService;
import com.applesnt.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController
@RequestMapping("/feign")
@Slf4j
public class FeignConsumerController {

    @Autowired/*feign远程服务接口注入*/
    private FeignClientService feignClientservice;

    @GetMapping("/get/{id}")
    //http://127.0.0.1:8801/feign/get/123
    public String getId(@PathVariable("id") String id){

        String reutrnStr = feignClientservice.getId(id);
        log.info("feign调用 = {}",reutrnStr);

        return reutrnStr;
    }

    @GetMapping("/getuserbyid/{id}")
    //http://127.0.0.1:8801/feign/getuserbyid/123
    public UserVo getUserById(@PathVariable("id") String id){

        UserVo userVo = feignClientservice.getUserById("123");
        log.info("feign调用 = {}",userVo);

        return userVo;
    }

    @GetMapping("/getuser2")
    //http://127.0.0.1:8801/feign/getuser2?id=123&name=zhangsan
    public UserVo getUser2(@RequestParam(name = "id",required = false) String id,
                           @RequestParam("name") String name){

        UserVo userVo = feignClientservice.getUser2(id,name);
        log.info("feign调用 = {}",userVo);

        return userVo;
    }

    @GetMapping("/getuser3")
    //http://127.0.0.1:8801/feign/getuser3?user_id=123&user_name=zhangsan
    public UserVo getUser3(UserVo userVo){

        /*feign调用-会报错,不支持get远程调用*/
        UserVo  uVo = feignClientservice.getUser3(userVo);
        log.info("feign调用 = {}",uVo);

        return uVo;
    }

    @PostMapping("/getuser")
    //http://127.0.0.1:8801/feign/getuser【要用postman模拟post请求】
    public UserVo getUser(@RequestBody UserVo userVo){

        UserVo  uVo = feignClientservice.getUser(userVo);
        log.info("feign调用 = {}",uVo);

        return uVo;
    }


    @GetMapping("/getlist")
    //http://127.0.0.1:8801/feign/getlist
    public List<UserVo> getUserList(){

        List<UserVo> list = feignClientservice.getUserList();
        log.info("feign调用 = {}",list);

        return list;
    }
}

6:Feign远程调用测试

分别启动Eureka服务集群、mhb-cloud-consumer-feign、mhb-cloud-producer、mhb-cloud-producer-extend六个服务

http://127.0.0.1:8801/feign/getuser2?id=123&name=zhangsan
第一次访问:

第二次访问:

四、Feign调用非微服务

创建远程调用service接口
@FeignClient(name = "xxxx",url = "http://localhost:8761")

com\applesnt\service\FeignClientService2.java

package com.applesnt.service;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.*;

/*不写configuration属性 默认使用FeignClientsConfiguration
* 默认配置支持springmvc注解
* */
@FeignClient(name = "xxxx",url = "http://localhost:8761")
public interface FeignClientService2 {

    @GetMapping(value = "/eureka/apps")
    public String getapp();

}

在FeignConsumerController中追加远程调用方法:


@Autowired/*feign远程服务接口注入(非微服务)*/
private FeignClientService2 feignClientService2;

/*访问非微服务*/
//http://127.0.0.1:8801/feign/getapp
@GetMapping("/getapp")
public String getapp(){
    String reutrnStr = feignClientService2.getapp();
    return reutrnStr;
}

五、Feign日志配置

由于Feign默认不开启日志,所有我们要创建一个配置类用于覆盖默认配置

com\applesnt\config\FeignLogConfiguration.java

package com.applesnt.config;

import feign.Logger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignLogConfiguration {

    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

2:在feign的远程调用service接口中,配置上FeignLogConfiguration类

@FeignClient(name = "mhb-cloud-producer",configuration = FeignLogConfiguration.class)

3:在application.yml中开启service接口的日志输出

logging:
  level:
    com.applesnt.service.FeignClientService: debug

4:日志输出

posted @ 2020-04-01 16:03  努力的校长  阅读(505)  评论(0编辑  收藏  举报