1. Introdução de fingimento
Feign é uma estrutura de cliente HTTP declarativa para simplificar a comunicação entre serviços em uma arquitetura de microsserviços. Faz parte da estrutura Spring Cloud e visa fornecer uma maneira elegante e fácil de usar para definir e invocar solicitações HTTP.
O objetivo do projeto da Feign é tornar a comunicação entre os serviços mais fácil e intuitiva. Normalmente, em uma arquitetura de microsserviços, um serviço precisa chamar a API de outro serviço para buscar dados ou executar uma operação. Na maneira tradicional, precisamos escrever manualmente as solicitações HTTP, processar solicitações e respostas, e o surgimento do Feign simplifica esse processo.
Usando o Feign, você só precisa definir uma interface para descrever a API do serviço a ser chamado e, em seguida, configurar o método de processamento de solicitações e respostas por meio de anotações. Feign gerará automaticamente solicitações HTTP disponíveis de acordo com a definição da interface, enviará a solicitação ao serviço de destino e converterá a resposta em um tipo de objeto apropriado para retornar.
Feign tem as seguintes características e vantagens:
- Definição de API declarativa: simplesmente definindo a interface, a comunicação entre serviços pode ser claramente descrita sem ter que prestar atenção aos detalhes HTTP subjacentes.
- Suporte de balanceamento de carga integrado: o Feign é integrado ao mecanismo de descoberta e registro de serviço do Spring Cloud, que pode implementar automaticamente o balanceamento de carga e lidar facilmente com chamadas de serviço de várias instâncias.
- Serialização e desserialização automáticas de solicitações e respostas: Feign pode manipular automaticamente a serialização e desserialização de solicitações e respostas, permitindo que você manipule dados de maneira orientada a objetos.
- Integração de fusão de serviço e limitação de corrente: Feign se integra aos fusíveis do Spring Cloud (como Hystrix) e limitadores de corrente (como Sentinel), que podem fornecer recursos de fusão de serviço e limitação de corrente, aumentando a estabilidade e a confiabilidade do sistema.
- Fácil de estender: Feign fornece um mecanismo conectável que permite estender e personalizar seu comportamento por meio de configurações e interceptores personalizados.
Em segundo lugar, o uso de Feign
Aqui tomo o projeto do porco como exemplo para ilustração. Endereço do projeto: https://gitee.com/log4j/pig
1. Descrição dos módulos do projeto
pig ├── pig-auth -- provisão de serviço de autorização [3000] └── pig-common -- módulo comum do sistema ├── pig-common-bom -- controle de gerenciamento de dependência global ├── pig-common-core -- Pacote principal de ferramentas comuns ├── pig-common-datasource -- pacote de fonte de dados dinâmica ├── pig-common-job -- pacote xxl-job ├── pig-common-log -- serviço de log ├── pig- common -mybatis -- pacote de extensão mybatis ├── pig-common-seata -- transações distribuídas ├── pig-common-security -- ferramentas de segurança ├── pig-common-swagger -- documentação da interface ├── pig -common- feign -- pacote de extensão feign └── pig-common-xss -- pacote de segurança xss ├── pig-register -- Nacos Server[8848] ├── pig-gateway -- Spring Cloud Gateway[9999] └── pig -upms -- módulo geral de gerenciamento de direitos do usuário └── pig-upms-api -- sistema geral de gerenciamento de direitos do usuário módulo api público └── pig-upms-biz -- módulo geral de processamento de negócios do sistema de gerenciamento de direitos do usuário[4000] └── pig-visual └── pig-monitor -- monitoramento de serviço[5001] ├── pig-codegen -- código gráfico geração[5002] ├── pig-sentinel-dashboard -- tráfego de alta disponibilidade[5003] └── pig-xxl-job-admin -- console de gerenciamento de tarefas de temporização distribuído[5004]
2. Fingir definição do cliente
(1) Introduza a dependência Feign
Tanto o módulo pig-upms-api quanto o módulo pig-upms-biz precisam introduzir dependências simuladas:
<!--feign 注解依赖-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-feign</artifactId>
<optional>true</optional>
</dependency>
(2) Defina o local
Como você pode ver no código, o cliente de Feign é definido no módulo pig-upms-api. É um padrão de design comum definir o cliente de Feign no módulo pig-upms-api. O objetivo deste modo é definir a interface do cliente Feign como parte do módulo API, para que outros módulos possam usar a API introduzindo dependências pig-upms-api e realizar a conexão com o módulo pig-upms-biz (geral usuário A comunicação entre o módulo de processamento de negócios do sistema de gerenciamento de direitos).
(3) Fingir definição do cliente
Tome RemoteUserService como exemplo:
//标识这是一个Feign客户端接口,contextId指定客户端的id,用于和其他客户端区分
//value="pig-upms-biz" 指定了要调用的服务名称
@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.UMPS_SERVICE)
public interface RemoteUserService {
//通过用户名查询用户、角色信息
//@GetMapping注解指定了要调用的HTTP GET请求的路径。这里是 /user/info/{username}
//headers指定了请求的头部信息,这里HEADER_FROM_IN的值是"from=Y"
@GetMapping(value = "/user/info/{username}", headers = SecurityConstants.HEADER_FROM_IN)
R<UserInfo> info(@PathVariable("username") String username);
//通过手机号码查询用户、角色信息
@GetMapping(value = "/app/info/{phone}", headers = SecurityConstants.HEADER_FROM_IN)
R<UserInfo> infoByMobile(@PathVariable("phone") String phone);
//根据部门id,查询对应的用户 id 集合
@GetMapping(value = "/user/ids", headers = SecurityConstants.HEADER_FROM_IN)
R<List<Long>> listUserIdByDeptIds(@RequestParam("deptIds") Set<Long> deptIds);
}
Na verdade, este cliente Feign enviará solicitação para SysUserController :
(4) Teste em outros módulos
Por exemplo, se eu quiser usar o Feign para fazer chamadas de interface no módulo pig-codegen, primeiro preciso introduzir a dependência pig-upms-api no módulo codegen, porque definimos o cliente Feign no pig-upms-api.
<!--upms api、model 模块-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-upms-api</artifactId>
</dependency>
Escreva um controlador de teste:
@RestController
@RequiredArgsConstructor //自动生成构造方法,在生成FeignDemoController会将remoteUserService传入
@RequestMapping("/feignDemo")
public class FeignDemoController {
//注入Feign客户端接口 RemoteUserService
//定义为final 确保在实例化后变量不会发生意外改变
private final RemoteUserService remoteUserService;
@Inner(value = false)
@GetMapping("/test")
public R<UserInfo> test() {
//假设传入的用户名是 admin
String username = "admin";
//调用feign中的info方法
return remoteUserService.info(username);
}
}
Inicie o teste do serviço e você verá que as informações do usuário admin foram obtidas com sucesso:
Suplemento: Sobre a compreensão dos dois métodos de injeção:
Ao injetar
remoteUserService
propriedades, você pode usar@RequiredArgsConstructor
anotações ou@Autowired
anotações de duas maneiras. Os dois métodos têm as seguintes diferenças:
@RequiredArgsConstructor
: Ao usar a anotação em uma classe@RequiredArgsConstructor
, ela irá gerar automaticamente um construtor para você, que seráremoteUserService
passado como parâmetro e injetado. Essa abordagem é injetar dependências por meio de construtores . O uso@RequiredArgsConstructor
de anotações pode simplificar o código e reduzir o trabalho de escrever construtores manualmente.
@Autowired
: quando a anotação é usada em uma propriedade@Autowired
, ela injeta automaticamente uma instância do tipo correspondente na propriedade. Esta forma é injetar dependências através de campos. A estrutura do Spring verificará automaticamente e encontraráRemoteUserService
uma instância que corresponda ao tipo e a injetará naremoteUserService
propriedade.@Autowired
A injeção de dependência pode ser feita facilmente usando anotações, mas você precisa garantir que as instâncias necessárias existam e sejam exclusivas.Em geral, os efeitos desses dois métodos de injeção são os mesmos e ambos serão
RemoteUserService
injetadosremoteUserService
na propriedade. A escolha de qual usar depende da preferência e das convenções do seu projeto. Using@RequiredArgsConstructor
pode fornecer um código mais conciso, enquanto using@Autowired
é mais flexível e pode se adaptar a mais cenários diferentes.