1. Introducción de Fingir
Fingir es un marco de cliente HTTP declarativo para simplificar la comunicación entre servicios en una arquitectura de microservicios. Es parte del marco Spring Cloud y tiene como objetivo proporcionar una forma elegante y fácil de usar para definir e invocar solicitudes HTTP.
El objetivo del diseño de Feign es hacer que la comunicación entre servicios sea más fácil e intuitiva. Por lo general, en una arquitectura de microservicios, un servicio necesita llamar a la API de otro servicio para obtener datos o realizar una operación. De la manera tradicional, necesitamos escribir manualmente solicitudes HTTP, procesar solicitudes y respuestas, y la aparición de Fingir simplifica este proceso.
Usando Fingir, solo necesita definir una interfaz para describir la API del servicio que se llamará y luego configurar el método de procesamiento de solicitudes y respuestas a través de anotaciones. Fingir generará automáticamente solicitudes HTTP disponibles de acuerdo con la definición de la interfaz, enviará la solicitud al servicio de destino y convertirá la respuesta en un tipo de objeto apropiado para devolver.
Fingir tiene las siguientes características y ventajas:
- Definición de API declarativa: simplemente definiendo la interfaz, la comunicación entre servicios se puede describir claramente sin tener que prestar atención a los detalles HTTP subyacentes.
- Compatibilidad con equilibrio de carga integrado: Feign está integrado con el mecanismo de descubrimiento y registro de servicios de Spring Cloud, que puede implementar automáticamente el equilibrio de carga y gestionar fácilmente las llamadas de servicio de varias instancias.
- Serialización y deserialización automática de solicitudes y respuestas: Feign puede manejar automáticamente la serialización y deserialización de solicitudes y respuestas, lo que le permite manipular datos de una manera orientada a objetos.
- Integración de fusión de servicios y limitación de corriente: Feign se integra con los fusibles de Spring Cloud (como Hystrix) y los limitadores de corriente (como Sentinel), que pueden proporcionar funciones de fusión de servicios y limitación de corriente, lo que aumenta la estabilidad y la confiabilidad del sistema.
- Fácil de extender: Feign proporciona un mecanismo conectable que le permite extender y personalizar su comportamiento a través de configuraciones e interceptores personalizados.
En segundo lugar, el uso de Fingir
Aquí tomo el proyecto del cerdo como ejemplo ilustrativo. Dirección del proyecto: https://gitee.com/log4j/pig
1. Descripción de los módulos del proyecto
pig ├── pig-auth -- provisión de servicios de autorización [3000] └── pig-common -- módulo común del sistema ├── pig-common-bom -- control de gestión de dependencia global ├── pig-common-core -- Paquete básico de herramientas comunes ├── pig-common-datasource -- paquete de origen de datos dinámicos ├── pig-common-job -- paquete xxl-job ├── pig-common-log -- servicio de registro ├── pig- common -mybatis -- paquete de extensión mybatis ├── pig-common-seata -- transacciones distribuidas ├── pig-common-security -- herramientas de seguridad ├── pig-common-swagger -- documentación de interfaz ├── pig -common- fingir -- fingir paquete de extensión └── pig-common-xss -- paquete de seguridad xss ├── pig-register -- Nacos Server[8848] ├── pig-gateway -- Spring Cloud Gateway[9999] └── pig -upms -- módulo de gestión de derechos de usuario general └── pig-upms-api -- módulo api público del sistema de gestión de derechos de usuario general └── pig-upms-biz -- módulo de procesamiento comercial del sistema de administración de derechos de usuario general[4000] └── pig-visual └── pig-monitor -- monitoreo de servicio[5001] ├── pig-codegen -- código gráfico generation[5002] ├── pig-sentinel-dashboard -- tráfico de alta disponibilidad[5003] └── pig-xxl-job-admin -- consola de administración de tareas de temporización distribuida[5004]
2. Fingir definición de cliente
(1) Introducir la dependencia de Fingir
Tanto el módulo pig-upms-api como el módulo pig-upms-biz necesitan introducir dependencias fingidas:
<!--feign 注解依赖-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-feign</artifactId>
<optional>true</optional>
</dependency>
(2) Definir la ubicación
Como puede ver en el código, el cliente de Feign se define en el módulo pig-upms-api. Es un patrón de diseño común para definir el cliente de Feign bajo el módulo pig-upms-api. El propósito de este modo es definir la interfaz de cliente de Feign como parte del módulo API, para que otros módulos puedan usar la API introduciendo dependencias pig-upms-api y realizar la conexión con el módulo pig-upms-biz (general). usuario La comunicación entre el módulo de procesamiento comercial del sistema de gestión de derechos).
(3) Fingir definición de cliente
Tome RemoteUserService como ejemplo:
//标识这是一个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);
}
En realidad, este cliente de Fingir enviará una solicitud a SysUserController :
(4) Prueba en otros módulos
Por ejemplo, si quiero usar Feign para realizar llamadas de interfaz en el módulo pig-codegen, primero debo introducir la dependencia pig-upms-api en el módulo codegen, porque definimos el cliente de Feign en pig-upms-api.
<!--upms api、model 模块-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-upms-api</artifactId>
</dependency>
Escriba un controlador de prueba:
@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 la prueba del servicio y podrá ver que la información del usuario administrador se ha obtenido con éxito:
Suplemento: En cuanto a la comprensión de los dos métodos de inyección:
Al inyectar
remoteUserService
propiedades, puede usar@RequiredArgsConstructor
anotaciones o@Autowired
anotaciones de dos maneras. Los dos métodos tienen las siguientes diferencias:
@RequiredArgsConstructor
: Al usar la anotación en una clase@RequiredArgsConstructor
, generará automáticamente un constructor para usted, que seremoteUserService
pasará como parámetro y se inyectará. Este enfoque consiste en inyectar dependencias a través de constructores . El uso@RequiredArgsConstructor
de anotaciones puede simplificar el código y reducir el trabajo de escribir constructores manualmente.
@Autowired
: cuando la anotación se usa en una propiedad@Autowired
, automáticamente inyecta una instancia del tipo correspondiente en la propiedad. Esta forma es inyectar dependencias a través de campos. Spring Framework escaneará automáticamente y encontraráRemoteUserService
una instancia que coincida con el tipo y la inyectará enremoteUserService
la propiedad.@Autowired
La inyección de dependencia se puede realizar fácilmente mediante anotaciones, pero debe asegurarse de que las instancias requeridas existan y sean únicas.En general, los efectos de estos dos métodos de inyección son los mismos y ambos se inyectarán
RemoteUserService
enremoteUserService
la propiedad. La elección de cuál usar depende de las preferencias y convenciones de su proyecto. El uso@RequiredArgsConstructor
puede proporcionar un código más conciso, mientras que el uso@Autowired
es más flexible y puede adaptarse a escenarios más diferentes.