6.使用Feign實現聲明式REST調用

                    使用Feign實現聲明式REST調用

6.1. Feign簡介

Feign是一個聲明式的REST客戶端,它的目的就是讓REST調用更加簡單。

Feign提供了HTTP請求的模板,經過編寫簡單的接口和插入註解,就能夠定義好HTTP請求的參數、格式、地址等信息。

而Feign則會徹底代理HTTP請求,咱們只須要像調用方法同樣調用它就能夠完成服務請求及相關處理。

SpringCloud對Feign進行了封裝,使其支持SpringMVC標準註解和HttpMessageConverters。

Feign能夠與Eureka和Ribbon組合使用以支持負載均衡。

6.2. 爲服務消費者整合Feign

pom.xmljava

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <artifactId>microservice-consumer-movie-feign</artifactId>
    <packaging>jar</packaging>

    <parent>
        <groupId>com.itmuch.cloud</groupId>
        <artifactId>microservice-spring-cloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
    </dependencies>
</project>

Feign類git

package com.itmuch.cloud.feign;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.itmuch.cloud.entity.User;

@FeignClient("microservice-provider-user")
public interface UserFeignClient {
  @RequestMapping(value = "/simple/{id}", method = RequestMethod.GET)
    //@GetMapping("/simple/{id}")
  public User findById(@PathVariable("id") Long id); // 兩個坑:1. @GetMapping不支持   2. @PathVariable得設置value

}

 圖文:github

 

6.3. 自定義Feign配置

Spring Cloud容許經過註解@FeignClient的configuration屬性自定義Feign的配置,自定義配置的優先級比FeignClientsConfiguration要高。

pom.xmlweb

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <artifactId>microservice-consumer-movie-feign-customizing</artifactId>
    <packaging>jar</packaging>

    <parent>
        <groupId>com.itmuch.cloud</groupId>
        <artifactId>microservice-spring-cloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
    </dependencies>
</project>

配置文件spring

spring:
  application:
    name: microservice-consumer-movie-feign-customizing
server:
  port: 7901
eureka:
  client:
    healthcheck:
      enabled: true
    serviceUrl:
      defaultZone: http://user:password123@localhost:8761/eureka
  instance:
    prefer-ip-address: true
logging:
  level:
    com.itmuch.cloud.feign.UserFeignClient: DEBUG

# 解決第一次請求報超時異常的方案:
# hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
# 或者:
# hystrix.command.default.execution.timeout.enabled: false
# 或者:
feign.hystrix.enabled: false ## 索性禁用feign的hystrix支持

# 超時的issue:https://github.com/spring-cloud/spring-cloud-netflix/issues/768
# 超時的解決方案: http://stackoverflow.com/questions/27375557/hystrix-command-fails-with-timed-out-and-no-fallback-available
# hystrix配置: https://github.com/Netflix/Hystrix/wiki/Configuration#execution.isolation.thread.timeoutInMilliseconds

configsql

package com.itmuch.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import feign.Contract;
 

@Configuration
public class FooConfiguration {
  @Bean
  public Contract feignContract() {
    return new feign.Contract.Default();
     
  }

}

實體apache

package com.itmuch.cloud.entity;

import java.math.BigDecimal;

public class User {
  private Long id;

  private String username;

  private String name;

  private Short age;

  private BigDecimal balance;

  public Long getId() {
    return this.id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getUsername() {
    return this.username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Short getAge() {
    return this.age;
  }

  public void setAge(Short age) {
    this.age = age;
  }

  public BigDecimal getBalance() {
    return this.balance;
  }

  public void setBalance(BigDecimal balance) {
    this.balance = balance;
  }

}

Feignjson

package com.itmuch.cloud.feign;

import org.springframework.cloud.netflix.feign.FeignClient;

import com.itmuch.cloud.entity.User;
 
import com.itmuch.config.FooConfiguration;

import feign.Param;
import feign.RequestLine;

@FeignClient(name = "microservice-provider-user", configuration = FooConfiguration.class)
public interface UserFeignClient {
  @RequestLine("GET /simple/{id}")
  public User findById(@Param("id") Long id);
}

Controllerapp

package com.itmuch.cloud.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.itmuch.cloud.entity.User;
 
import com.itmuch.cloud.feign.UserFeignClient;

@RestController
public class MovieController {

  @Autowired
  private UserFeignClient userFeignClient;
 

  @GetMapping("/movie/{id}")
  public User findById(@PathVariable Long id) {
    return this.userFeignClient.findById(id);
  }

  
}

啓動類負載均衡

package com.itmuch.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class ConsumerMovieFeignApplication {
  public static void main(String[] args) {
    SpringApplication.run(ConsumerMovieFeignApplication.class, args);
  }
}

 

注意,咱們在此類中修改了Feign的Contract ,那麼Contract 是什麼呢。它叫作契約。由於Feign一開始使用的契約是SpringMVC,因此剛纔咱們SpringMVC的註解的時候直接成功了,可是你若是如今啓動項目你就會發現已經啓動不了了。由於Contract.Default()使用的契約是Feign本身的,也就是說咱們要把SpringMVC的註解修改成Feign的註解

SpringMVC版本

@GetMapping (value = "/user/getUser/{id}") public User getUser(@PathVariable("id")Long id);

Feign版本

@RequestLine("GET /user/getUser/{id}")  public User getUser(@Param("id") Long id);

6.4. 手動建立Feign

服務端:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <artifactId>microservice-provider-user-with-auth</artifactId>
    <packaging>jar</packaging>

    <name>microservice-provider-user-with-auth</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>com.itmuch.cloud</groupId>
        <artifactId>microservice-spring-cloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    </dependencies>

</project>

配置文件:

server:
  port: 7900
spring:
  jpa:
    generate-ddl: false
    show-sql: true
    hibernate:
      ddl-auto: none
  datasource:
    platform: h2
    schema: classpath:schema.sql
    data: classpath:data.sql
  application:
    name: microservice-provider-user-with-auth
logging:
  level:
    root: INFO
    org.hibernate: INFO
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
    com.itmuch: DEBUG
eureka:
  client:
    healthcheck:
      enabled: true
    serviceUrl:
      defaultZone: http://user:password123@localhost:8761/eureka
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
    metadata-map:
      zone: ABC      # eureka能夠理解的元數據
      lilizhou: BBC  # 不會影響客戶端行爲
    lease-renewal-interval-in-seconds: 5

Spring Security的配置類

package com.itmuch.cloud.entity;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;

public class SecurityUser implements UserDetails {

    private static final long serialVersoinUID = 1L;

    private Long id;
    private String username;
    private String password;
    private String role;

    public SecurityUser() {
    }

    public SecurityUser(String username, String password, String role) {
        this.username = username;
        this.password = password;
        this.role = role;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        SimpleGrantedAuthority authority = new SimpleGrantedAuthority(this.role);
        authorities.add(authority);
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}
package com.itmuch.cloud.microserviceprovideruserwithauth.security;

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

@Component
public class CustomUserDetailsService implements UserDetailsService {

    /**
     * 模擬兩個帳戶
     * ① 帳號是user,密碼是password1,角色是user-role
     * ② 帳號時候admin,密碼是password1,角色是admin-role
     * @param username
     *                  用戶名
     * @return
     *
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if ("user".equals(username)) {
            return new SecurityUser("user", "password1", "user-role");
        } else if ("admin".equals(username)) {
            return new SecurityUser("admin", "password2", "admin-role");
        } else {
            return null;
        }
    }
}
package com.itmuch.cloud.microserviceprovideruserwithauth.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 全部的請求,都須要通過HTTP basic認證
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .httpBasic();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        // 明文編碼器。這個一個不作任何操做的密碼編碼器,是Spring提供給咱們作明文測試的
        return NoOpPasswordEncoder.getInstance();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(this.userDetailsService).passwordEncoder(this.passwordEncoder());
    }
}

修改Controller,在其中打印當前登陸的用戶信息

package com.itmuch.cloud.controller;

import com.itmuch.cloud.repository.UserRepository;
import com.itmuch.cloud.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;

@RestController
public class UserController {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/{id}")
    public User findById(@PathVariable Long id) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (principal instanceof UserDetails) {
            UserDetails user = (UserDetails) principal;
            Collection<? extends GrantedAuthority> collections = user.getAuthorities();
            for (GrantedAuthority ga: collections) {
                // 打印當前登陸用戶的信息
                UserController.LOGGER.info("當前用戶是{}, 角色是{}", user.getUsername(), ga.getAuthority());
            }
        } else {
            UserController.LOGGER.warn("ε=(´ο`*)))唉,出現問題了");
        }
        User findOne = userRepository.findOne(id);
        return findOne;
    }

}

客服端:

 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <artifactId>microservice-consumer-movie-feign-manual</artifactId>
    <packaging>jar</packaging>

    <parent>
        <groupId>com.itmuch.cloud</groupId>
        <artifactId>microservice-spring-cloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
    </dependencies>
</project>

配置文件

spring:
  application:
    name: microservice-consumer-movie-feign-manual
server:
  port: 7901
eureka:
  client:
    healthcheck:
      enabled: true
    serviceUrl:
      defaultZone: http://user:password123@localhost:8761/eureka
  instance:
    prefer-ip-address: true
ribbon:
  eureka:
    enabled: true

實體類

package com.itmuch.cloud.entity;

import java.math.BigDecimal;

public class User {
  private Long id;

  private String username;

  private String name;

  private Short age;

  private BigDecimal balance;

  public Long getId() {
    return this.id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getUsername() {
    return this.username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Short getAge() {
    return this.age;
  }

  public void setAge(Short age) {
    this.age = age;
  }

  public BigDecimal getBalance() {
    return this.balance;
  }

  public void setBalance(BigDecimal balance) {
    this.balance = balance;
  }

}

Feign類

package com.itmuch.cloud.feign;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.itmuch.cloud.entity.User;

public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);  
 

}
package com.itmuch.cloud.controller;



import com.itmuch.cloud.feign.UserFeignClient;
import com.itmuch.cloud.entity.User;
import feign.Client;
import feign.Contract;
import feign.Feign;
import feign.auth.BasicAuthRequestInterceptor;
import feign.codec.Decoder;
import feign.codec.Encoder;
import org.springframework.cloud.netflix.feign.FeignClientsConfiguration;
import org.springframework.context.annotation.Import;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@Import(FeignClientsConfiguration.class) // Spring Cloud爲Feign默認提供的配置類
@RestController
public class MovieController {

    private UserFeignClient userUserFeignClient;
    private UserFeignClient adminUserFeignClient;

    public MovieController(Decoder decoder, Encoder encoder, Client client, Contract contract) {
        this.userUserFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
                .requestInterceptor(new BasicAuthRequestInterceptor("user", "password1"))
                .target(UserFeignClient.class, "http://microservice-provider-user-with-auth/");
        this.adminUserFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
                .requestInterceptor(new BasicAuthRequestInterceptor("admin", "password2"))
                .target(UserFeignClient.class, "http://microservice-provider-user-with-auth/");
    }

    @GetMapping("/user-user/{id}")
    public User findByIdUser(@PathVariable Long id) {
        return this.userUserFeignClient.findById(id);
    }

    @GetMapping("/user-admin/{id}")
    public User findByIdAdmin(@PathVariable Long id) {
        return this.adminUserFeignClient.findById(id);
    }

}

圖文:

 

6.5. Feign對繼承的支持

Feign還支持繼承,將一些公共操做弄到父接口,從而簡化開發

好比,先寫一個基礎接口:UserService.java

public interface UserService {
     @RequestMapping(method=RequestMethod.GET,value="/user/{id}")
      User getUser(@PathVariable("id") long id);
}

服務提供者Controller:UserResource.java

@RestController
 public class UserResource implements UserService {
 
 //...
 }

服務消費者:UserClient.java

 @FeignClient("users")
       public interface UserClient extends UserService {
}

 

6.6. Feign對壓縮的支持

feign:
  compression:
      mime-types: text/xml,application/xml,application/json
  request:
       enable: true
       min-request-size: 2048
  response:
        enable: true

6.7. Feign的日誌

Feign配置類

package com.itmuch.cloud.conf;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
  
  /**
   * Created by 2YSP on 2018/7/18.
   */
 @Configuration
 public class FeignLogConfiguration {
 
     /**
      * NONE:不記錄任何日誌(默認)
      * BASIC:僅記錄請求方法、URL、響應狀態代碼以及執行時間
      * HEADERS:記錄BASIC級別的基礎上,記錄請求和響應的header
      * FULL:記錄請求和響應的header,body和元數據
      * @return
      */
     @Bean
     Logger.Level feignLoggerLevel(){
         return Logger.Level.FULL;    
    }
 }

修改Feign,使用指定配置類

package com.itmuch.cloud.feign;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.itmuch.cloud.conf.FeignLogConfiguration;
import com.itmuch.cloud.entity.User;

@FeignClient( name = "microservice-provider-user",configuration = FeignLogConfiguration.class)
public interface UserFeignClient {
  @RequestMapping(value = "/simple/{id}", method = RequestMethod.GET)
    //@GetMapping("/simple/{id}")
  public User findById(@PathVariable("id") Long id); // 兩個坑:1. @GetMapping不支持   2. @PathVariable得設置value
 
 
  @RequestMapping(value = "/user", method = RequestMethod.POST)
  public User postUser(@RequestBody User user);

  // 該請求不會成功,只要參數是複雜對象,即便指定了是GET方法,feign依然會以POST方法進行發送請求。多是我沒找到相應的註解或使用方法錯誤。
  // 如勘誤,請@lilizhou2008  eacdy0000@126.com
  @RequestMapping(value = "/get-user", method = RequestMethod.GET)
  public User getUser(User user);
}

application.yml中添加以下內容,設置日誌級別,注意:Feign的日誌打印只會對DEBUG級別作出響應

spring:
  application:
    name: microservice-consumer-movie-feign
server:
  port: 7901
eureka:
  client:
    healthcheck:
      enabled: true
    serviceUrl:
      defaultZone: http://user:password123@localhost:8761/eureka
  instance:
    prefer-ip-address: true
logging:
  level:
    com.itmuch.cloud.feign.UserFeignClient: DEBUG

6.8. 使用Feign構造多參數請求

當咱們用Get請求多參數的URL的時候,好比:http://microservice-provider-user/get?id=1&username=zhangsan,可能會採起以下的方式

@FeignClient(name = "microservice-provider-user")
 public interface UserFeignClient {
 
     @RequestMapping(value = "/get",method = RequestMethod.GET)
     User get0(User user);
 
 }

正確處理方式一:使用@RequestParam註解

 @RequestMapping(value = "/get",method = RequestMethod.GET)
  User get1(@RequestParam("id") Long id,@RequestParam("username") String username);

可是這種方法也有個缺點,若是參數比較多就要寫很長的參數列表。

正確處理方式二:使用map接收

 @RequestMapping(value = "/get",method = RequestMethod.GET)
 User get2(Map<String,Object> map);

處理方式三:若是請求方式沒有限制的話,換成POST方式

 @RequestMapping(value = "/get",method = RequestMethod.POST)
 User get3(User user);
相關文章
相關標籤/搜索