1、错误现象:
我的微服务项目中,一个ogarnaization的微服务启动时,出现以下错误:
A component required a bean of type 'org.springframework.security.authentication.AuthenticationManager' that could not be found.
2、错误场景和条件:
我的微服务的mudule结构如下图:
两个业务类型的微服务,auth和organization子模块的微服务都有装配AuthenticationManager,如下示例:
@RestController
@RequestMapping("/sysmgr/position")
public class PositionController extends BaseController<Position, IPositionService> {
。。。
@Resource
private AuthenticationManager authenticationManager;
。。。
}
这种情况下,启动auth的微服务,一切正常。但是启动organization的微服务,就会出现【A component required a bean of type 'org.springframework.security.authentication.AuthenticationManager' that could not be found.】错误信息。
另外,测试也发现,两个微服务依赖条件相同,而且如果controller里,都使用了spring security的@PreAuthorize注解,如下。也会出现,一个auth里的鉴权有效,organization里的鉴权无效的情况
@PreAuthorize("hasAuthority('org:position:user:count')")
@GetMapping("/getUserCount")
public FdApiResult getUserCountById(Long id){
return userFeignService.getUserCountByPositionId(id);
}
3、错误原因分析:
经过分析发现,两个module的主启动类所在的包,有些差别:
- auth module的主启动类,在【package com.dev.web】
- organization module的主启动类,在【package com.dev.web.organization】
- commons module所在的包【package com.dev.web.commons】
1)为什么auth微服务启动正常?因为【package com.dev.web】在【package com.dev.web.commons】上一级。它的主启动类,启动时,可以将【com.dev.web.commons】下的组件加载到它可访问的容器下。所以,这个微服务一切正常!
2)而,organization微服务的包【package com.dev.web.organization】和【package com.dev.web.commons】同级,它的主启动类,启动时,无法将【package com.dev.web.commons】组件加载到它可访问的容器下。所以,这个微服务无法正常加载和调用commons module下的类!
因为启动类上面的@SpringBootApplication里面默认包含了一个@ComponentScan注解,这个注解默认情况下是扫描该类所属包下面的所有类,包含子目录中的类。
4、错误解决办法:
两种方法:
1)修改organization主启动类所在包的位置,改为【package 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)organization主启动类修改扫描包的范围,确保commons module的包也能被主启动类扫描并加载。修改@SpringBootApplication注解,添加一个参数scanBasePackages ,指定包名为com.dev.web。
@SpringBootApplication(scanBasePackages = {"com.dev.web"})
主启动类的完整代码如下:
@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);
}
}
再次测试后,一些正常!
版权归原作者 依然是那个墨镜 所有, 如有侵权,请联系我们删除。