在 Spring 中使用 MultiTenancy 进行数据库路由

问题描述 投票:0回答:1

我正在尝试在春季实现多租户。我使用 JWT,并且我将tenant_id 存储在JWT 中,我已配置我的类MultiTenantDataSourceRouter 扩展AbstractRoutingDataSource 以使查找键为tenant_id。

@Override
protected Object determineCurrentLookupKey() {
    var authentication = SecurityContextHolder.getContext().getAuthentication();
    if(authentication!= null && authentication.getPrincipal() instanceof User user) {
        return user.getTenant_id();
    }
    return null;
}

我还有一个以用户身份登录的控制器方法。登录后,我想创建一个用户对象并将其存储在该租户特有的数据库中

public ResponseEntity<AuthenticationResponse> loginUser(AuthenticateRequest authenticateRequest) {
            //authenticate the User
            authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(authenticateRequest.getEmail(),authenticateRequest.getPassword()));

            //this line of code runs oly if authentication is successful
            User user = userRepository.findByEmail(authenticateRequest.getEmail()).orElseThrow();
            String jwt = jwtService.generateToken(user);

            //set the security context to allow routing of db and to know the tenantID and also set the datasource
            SecurityContextHolder.getContext()
                    .setAuthentication(new UsernamePasswordAuthenticationToken(user.getUsername(),null,user.getAuthorities()));

            var mds = new MultiTenantDataSourceRouter();
            mds.setTargetDataSources(dataSourceConfig.loadAllDataSources());
            mds.afterPropertiesSet();

            //create an Employee Object for the user once
            Employee employee = employeeRepository.findByEmail(user.getEmail());
            if(employee!= null){
                Employee newEmployee = Employee.builder()
                        .email(user.getEmail())
                        .name(user.getName())
                        .build();
            }
            return ResponseEntity.ok().body(new AuthenticationResponse(jwt));
    }

应用程序启动时,我已加载数据源(dataSourceConfig.loadAllDataSources())这是一个返回tenant_id的Map和相应数据源的bean。但是当我调用此方法时,默认数据源通过app加载到应用程序中.properties 是查找 findbyEmail() 方法的员工对象的位置。我希望它在与该用户关联的租户内查找它,但它没有

这会导致错误,因为我的默认数据库没有员工表。

java spring spring-boot multi-tenant
1个回答
0
投票

看看这个例子。

我相信您错过了一个步骤,告诉您的应用程序需要为您的员工使用哪个租户。您使用 dataSourceConfig.loadAllDataSources() 为多租户数据源提供一些数据源,但您没有告诉它使用哪一个,因此它使用默认的数据源。

© www.soinside.com 2019 - 2024. All rights reserved.