到目前为止,各微服务模块的入口类上自定义的注解已经有点多了,比如elsa-server-demo模块的入口类:
@EnableDiscoveryClient
@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true) //表示开启Spring Cloud Security权限注解
@EnableElsaAuthExceptionHandler
@EnableFeignClients //开启Feign Client功能
@EnableElsaOauth2FeignClient
@EnableElsaServerProtect
public class ElsaServerDemoApp{
public static void main(String[] args) {
SpringApplication.run(ElsaServerDemoApp.class, args);
}
}
三个自定义入口注解,作用分别为:
这三个功能都是微服务提供者必备的功能,所以我们可以定义一个注解将这三个功能整合在一起。
因为这三个注解都是通过@Enable类型注解来将配置类注册到IOC容器中,所以我们现在要做的就是将这三个配置类一次性都注册到IOC容器中。在Spring中,要将多个类进行注册,可以使用selector的方式。
在elsa-common模块的com.elsa.common下新建selector包,然后在该包下创建ElsaCloudApplicationSelector:
public class ElsaCloudApplicationSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{
ElsaAuthExceptionConfigure.class.getName(),
ElsaOAuth2FeignConfigure.class.getName(),
ElsaServerProtectConfigure.class.getName()
};
}
}
通过selectImports方法,我们一次性导入了ElsaAuthExceptionConfigure、ElsaOAuth2FeignConfigure和ElsaServerProtectConfigure这三个配置类。
要让上面的代码生效,我们还需将ElsaCloudApplicationSelector注册到IOC容器中。同之前的做法,我们可以通过注解的方式来实现。
在elsa-common模块的com.elsa.common.annotation路径下新建ElsaCloudApplication注解:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ElsaCloudApplicationSelector.class)
public @interface ElsaCloudApplication {
}
在elsa-auth、elsa-server-system、elsa-server-demo入口类上的三个注解就可以使用@ElsaCloudApplication代替了:
@EnableDiscoveryClient
@SpringBootApplication
//@EnableElsaAuthExceptionHandler
//@EnableElsaServerProtect
@ElsaCloudApplication
public class ElsaAuthApp
{
public static void main(String[] args) {
SpringApplication.run(ElsaAuthApp.class, args);
}
}
@EnableDiscoveryClient
@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true) //表示开启Spring Cloud Security权限注解
//@EnableElsaAuthExceptionHandler
//@EnableElsaServerProtect
@ElsaCloudApplication
public class ElsaServerSystemApp {
public static void main(String[] args) {
SpringApplication.run(ElsaServerSystemApp.class, args);
}
}
@EnableDiscoveryClient
@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true) //表示开启Spring Cloud Security权限注解
//@EnableElsaAuthExceptionHandler
@EnableFeignClients //开启Feign Client功能
//@EnableElsaOauth2FeignClient
//@EnableElsaServerProtect
@ElsaCloudApplication
public class ElsaServerDemoApp{
public static void main(String[] args) {
SpringApplication.run(ElsaServerDemoApp.class, args);
}
}
在搭建认证服务器时,elsa-auth模块的Web安全配置类ElsaSecurityConfigure里注册了一个BCryptPasswordEncoder类型的PasswordEncoderBean。但实际上这个密码加密器不仅在elsa-auth里需要用到,在elsa-server-system也要用到,比如新增用户,修改密码等业务,所以这个Bean适合定义在elsa-common通用模块里。
修改elsa-common模块的ElsaServerProtectConfigure,添加代码如下
public class ElsaServerProtectConfigure implements
WebMvcConfigurer {
......
@Bean
@ConditionalOnMissingBean(value = PasswordEncoder.class)
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
......
}
@ConditionalOnMissingBean(value = PasswordEncoder.class)注解标注,表示当IOC容器里没有PasswordEncoder类型的Bean的时候,则将BCryptPasswordEncoder注册到IOC容器中。
修改elsa-auth模块的ElsaSecurityConfigure代码:
@Order(2) // 增加过滤链的优先级,因为ElsaResourceServerConfigure的优先级为3
@EnableWebSecurity // 开启和Web相关的安全配置
public class ElsaSecurityConfigure extends WebSecurityConfigurerAdapter {
......
@Autowired
private PasswordEncoder passwordEncoder;
......
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder);
}
}
源码地址:注解功能整合及密码加密器调整