Tabla de contenido
2. Escenarios y condiciones de error:
3. Análisis de motivos de error:
1. Fenómeno de error:
En mi proyecto de microservicio, cuando se inicia un microservicio ogarnaizado, ocurre el siguiente error:
Un componente requería un bean de tipo 'org.springframework.security.authentication.AuthenticationManager' que no se pudo encontrar.
2. Escenarios y condiciones de error:
La estructura del módulo de mi microservicio es la siguiente:
Dos tipos comerciales de microservicios, los microservicios de los submódulos de autenticación y organización, están equipados con AuthenticationManager, como se muestra en el siguiente ejemplo:
@RestController
@RequestMapping("/sysmgr/position")
public class PositionController extends BaseController<Position, IPositionService> {
。。。
@Resource
private AuthenticationManager authenticationManager;
。。。
}
En este caso, inicie el microservicio de autenticación y todo será normal. Pero al iniciar los microservicios de la organización, aparecerá el mensaje de error " Un componente requería un bean de tipo 'org.springframework.security.authentication.AuthenticationManager' que no se pudo encontrar ".
Además, la prueba también encontró que los dos microservicios tienen las mismas condiciones de dependencia, y si el controlador usa la anotación @PreAuthorize de seguridad de Spring, de la siguiente manera. También puede suceder que la autenticación en una autenticación sea válida pero la autenticación en la organización no sea válida.
@PreAuthorize("hasAuthority('org:position:user:count')")
@GetMapping("/getUserCount")
public FdApiResult getUserCountById(Long id){
return userFeignService.getUserCountByPositionId(id);
}
3. Análisis de motivos de error:
Después del análisis, se encontró que existen algunas diferencias en los paquetes donde se encuentran las principales clases de inicio de los dos módulos:
- La clase de inicio principal del módulo de autenticación está en [ paquete com.dev.web ]
- La clase de inicio principal del módulo de organización está en [ paquete com.dev.web.organization ]
- El paquete donde se encuentra el módulo commons [ paquete com.dev.web.commons ]
1) ¿Por qué el microservicio de autenticación se inicia normalmente? Porque [ paquete com.dev.web ] está un nivel por encima de [ paquete com.dev.web.commons ]. Su clase de inicio principal, cuando se inicia, puede cargar componentes en [ com.dev.web.commons ] en el contenedor al que puede acceder. Entonces, ¡todo está bien con este microservicio!
2) Sin embargo, el paquete del microservicio de la organización [ paquete com.dev.web.organization ] y [ paquete com.dev.web.commons ] están al mismo nivel. Su clase de inicio principal no puede ser [ paquete com.dev.web .commons】El componente se carga debajo del contenedor al que puede acceder. Por lo tanto, este microservicio no puede cargar ni llamar clases en el módulo commons normalmente.
Debido a que @SpringBootApplication en la clase de inicio contiene una anotación @ComponentScan de forma predeterminada, esta anotación escanea todas las clases en el paquete al que pertenece la clase de forma predeterminada, incluidas las clases en subdirectorios.
4. Soluciones de errores:
Dos métodos:
1) Modifique la ubicación del paquete donde se encuentra la clase de inicio principal de la organización y cámbielo a [ paquete com.dev.web ]
package com.dev.web;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.stereotype.Component;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800 * 2 )
@MapperScan(basePackages = {"com.freedo.dev.web.organization.**.mapper"})
public class OrgarnizationApplication {
public static void main(String[] args) {
SpringApplication.run(OrgarnizationApplication.class,args);
}
}
2) La clase de inicio principal de la organización modifica el alcance del escaneo de paquetes para garantizar que los paquetes del módulo común también puedan ser escaneados y cargados por la clase de inicio principal. Modifique la anotación @SpringBootApplication, agregue un parámetro scanBasePackages y especifique el nombre del paquete com.dev.web.
@SpringBootApplication (scanBasePackages = {"com.dev.web"})
El código completo de la clase de inicio principal es el siguiente:
@SpringBootApplication(scanBasePackages = {"com.dev.web"})
@EnableDiscoveryClient
@EnableFeignClients
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800 * 2 )
@MapperScan(basePackages = {"com.dev.web.organization.**.mapper"})
public class OrgarnizationApplication {
public static void main(String[] args) {
SpringApplication.run(OrgarnizationApplication.class,args);
}
}
Después de realizar la prueba nuevamente, ¡algunos son normales!