2021SC@SDUSC
这次我们来分析最后的板块,manager
config
config包下有关于跨域资源共享的配置,数据源配置,以及错误配置
CorsConfig
corsConfig继承自WebMvcConfigurer,重写了一个方法 addCorsMappings
,该方法配置 "全局 "跨源请求处理。配置的 CORS 映射适用于注释控制器、功能端点和静态资源。被注释的控制器可以通过 @CrossOrigin 进一步声明更精细的配置。在这种情况下,这里声明的 "全局 "CORS配置与控制器方法上定义的本地CORS配置相结合。
在CorsConfig中,重写的逻辑为:
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600);
}
大致就是允许了根目录下的全部资源的访问,并且允许GET、POST、PUT、DELETE和OPTIONS的请求方法,设置权限最大年龄为一小时
在下面配置了一个CorsFilter,这个Filter并没有找到他在哪进行引用
@Bean
public CorsFilter corsFilter() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOriginPattern("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
DataSourceConfig
DataSourceConfig中声明了使用到的主数据源的配置信息,以及备用的数据源配置信息
@Primary
@Bean(name = "ds1DataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.ds1")
public DataSourceProperties ds1DataSourceProperties() {
return new DataSourceProperties();
}
//主数据源 ds1数据源
@Primary
@Bean(name = "ds1DataSource")
public DataSource ds1DataSource(@Qualifier("ds1DataSourceProperties") DataSourceProperties dataSourceProperties) {
return dataSourceProperties.initializeDataSourceBuilder().build();
}
// ds2数据源
@Bean(name = "ds2DataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.ds2")
public DataSourceProperties ds2DataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "ds2DataSource")
public DataSource ds2DataSource(@Qualifier("ds2DataSourceProperties") DataSourceProperties dataSourceProperties) {
return dataSourceProperties.initializeDataSourceBuilder().build();
}
其中prefix的作用是标识在.properties文件中哪个数据声明的是对应的配置,可以查看.properties得到:
spring.datasource.ds1.url=jdbc:mysql://****?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false
spring.datasource.ds1.username=****
spring.datasource.ds1.password=****
spring.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.ds2.url=jdbc:mysql://****?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false
spring.datasource.ds2.username=****
spring.datasource.ds2.password=****
spring.datasource.ds2.driver-class-name=com.mysql.cj.jdbc.Driver
DsConfig
DsConfig中声明了数据源对于JPA的相关配置,包括
- 配置一个实体管理工厂
- 配置实体管理器
- 配置JPA事务管理器
并且声明了对应数据源的实体的包名,实体管理器的标识和事务管理器的标识
@Configuration
//1、实体扫描
//2、实体管理ref
//3、事务管理
@EntityScan(basePackages = "cn.edu.sdu.entity.ds1")
@EnableJpaRepositories(
basePackages = "cn.edu.sdu.repository.ds1",
entityManagerFactoryRef = "ds1EntityManagerFactoryBean",
transactionManagerRef = "ds1TransactionManager")
@EnableTransactionManagement
public class DsConfig{
...
}
@Primary
@Bean(name = "ds1EntityManagerFactoryBean")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
return factoryBuilder.dataSource(dataSource)
//这一行的目的是加入jpa的其他配置参数比如(ddl-auto: update等)
//当然这个参数配置可以在事务配置的时候也可以
.properties(hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings()))
.packages("cn.edu.sdu.entity.ds1")
.persistenceUnit("ds1PersistenceUnit")
.build();
}
/**
* EntityManager
*/
@Primary
@Bean(name = "ds1EntityManager")
public EntityManager entityManager() {
return Objects.requireNonNull(entityManagerFactoryBean().getObject()).createEntityManager();
}
/**
* jpa事务管理
*/
@Primary
@Bean(name = "ds1TransactionManager")
public JpaTransactionManager transactionManager() {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
return jpaTransactionManager;
}
ErrorConfig
ErrorConfig中配置了当出现错误时该显示的页面,这里配置了404错误信息
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/index.html");
registry.addErrorPages(error404Page);
}
分析完配置包后,我们来看一下服务层的特点
manager模块主要时服务于管理人员,其对外接口和之前分析过的模块有很大的重复。
笔者决定找到特别的地方进行分析
DsAuthorityManagementService
DsAuthorityManagementService 负责查找权限,其功能有:
- 查询父角色的所有子角色
- 查询父权限的所有子权限
- 查询角色的所有权限
- 查询用户的所有角色
- 插入角色并指定权限
- 插入用户并指定角色
- 给用户授予角色
- 给角色授予权限
具体实现部分是通过分布式的调用不同节点的数据库来实现数据操作。
DsManagerUserDetailsService
DsManagerUserDetailsService 实现了User的认证过程
系统通过用户名查找到用户,再用用户ID查找用户所有的角色信息
再将每一个用户的权限信息取出,放入一个列表
最终将列表传递给DsManagerUserDetails构造器,构造出用户认证对象
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("Username="+username);
UmsUser umsUser = umsUserRepository.findByUsername(username).get(0);
List<GrantedAuthority> authorityList = new ArrayList<>();
List<JpaRoleForUserVo> jpaRoleForUserVos = ds1AuthorityManagementService.selectRoleForUser(umsUser.getUid());
jpaRoleForUserVos.forEach( role -> {
authorityList.add(new SimpleGrantedAuthority(role.getRole_name()));
});
return new Ds1ManagerUserDetails(umsUser, authorityList);
}