首页 > 解决方案 > 相同的方法,看似相同的String字符串输入,不同的结果

问题描述

我正在开发一个具有多租户的应用程序(java/spring 的新手),试图用不同的用户连接到不同的数据库。对 java.lang.String 类有一些奇怪的经历

将字符串字符串用作@PathVariable 时,它​​正在工作 - 方法(路径变量)。如果我以硬编码的方式定义参数,而不使用 PathVariables,它正在工作 - 方法(“字符串”)。

但是当我尝试用我的代码定义一个字符串字符串,而不使用 PathVariables 时,它不起作用 - 根据用户数据从 db 获取一个字符串,并使用方法(字符串)的结果来更改 db 连接。

我也添加了一些日志信息,但仍然,这一切似乎都是一样的,但仍然无法完成这项工作。它是否与代码执行顺序、控制器生命周期、变量类型有关?

tenantContext

public class TenantContext {

    private static ThreadLocal<String> currentTenant = new ThreadLocal<>();

    public static void setCurrentTenant(String tenant) {

        currentTenant.set(tenant);

    }

    public static String getCurrentTenant() {
        return currentTenant.get();
    }

    public static void clear() {
        currentTenant.set(null);
    }
}


* PROBLEMATIC SOLUTION **********************************************

@GetMapping("/koms-list/name-containing")
public List<Kom> komsListByNameContaining(
               Principal principal,
               User user,
               @RequestParam("targetKomName") String targetKomName
           )                
    {

    user = userRepository.findByUsername(principal.getName());
    String dbContext = new String();
    dbContext = user.getClient_db();

        TenantContext.setCurrentTenant(dbContext);//NOT WORKING
        TenantContext.setCurrentTenant("whatever");// THIS WORKS

        Logger logger = LoggerFactory.getLogger(Logger.class.getName());
        logger.info("Client db name based on Principal > " + user.getClient_db());
        logger.info("Client db name variable-data type > " + user.getClient_db().getClass().getName());

        logger.info("Active users name based on Principal > " + principal.getName());
        logger.info("TenantContext variable data type > " + dbContext.getClass().getName());

        logger.info("TenantContext variable value > " + dbContext);
        logger.info("Target kom to find > " + targetKomName);

        List<Kom> result = komRepository.findByNevContaining(targetKomName);

        return result;

    * WORKING SOLUTION **************************************************

        @GetMapping("/koms-list/selected-client/{client}/selected-partner/{sif}")
                public List<Kom> komListBySif(
                        @PathVariable (value = "sif") Long sif,
                        @PathVariable (value = "client") String client
                        )
        {
        TenantContext.setCurrentTenant(client);// THIS WORKS AS WELL        
        List<Kom> kom = (List<Kom>) komRepository.findBySif(sif);
        return kom;
        }

我希望 String dbContext = user.getClient_db() 字符串可以用作 Pathvariable String 客户端。但他们没有得出相同的结果。我在这里错过了一些基本的java东西吗?

* 更多代码 *

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class MultitenantDataSource extends AbstractRoutingDataSource {
    @Override
    public Object determineCurrentLookupKey() {
        return TenantContext.getCurrentTenant();
    }
}

这是通过根据用户数据从不同的文件/文件夹加载 application.properties 来更改数据库连接的正确方法吗?

* 更新 *

/**
         * SECOND CONTROLLER
         * get selected KOM by sif
         * 
         *  */
        @CrossOrigin(origins = "http://localhost:3000/partners")
        @GetMapping("/koms-list/selected-client/{client}/selected-partner/{sif}")
        public List<Kom> komListBySif(
                @PathVariable (value = "sif") Long sif,
                @PathVariable (value = "client") String client
                )
        {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

            String currentPrincipalName = authentication.getName();

            User user = userRepository.findByUsername(currentPrincipalName);

            String context = user.getClient_db();

            context = Normalizer.normalize(context, Form.NFD);

            Logger logger = LoggerFactory.getLogger(Logger.class.getName());
            logger.info("Client db name based on pathVariable > " + client);
            logger.info("TenantContext variable data type based on context > " + context.getClass().getName());
            //TenantContext tenantContext = new TenantContext();
            //TenantContext.setCurrentTenant(client);
            TenantContext.setCurrentTenant(client);

            List<Kom> kom = (List<Kom>) komRepository.findBySif(sif);

            return kom;
        }

// 也成功断开,无法切换到另一个数据库连接

标签: javaspring

解决方案


看看有什么user.getClient_db();回报。我怀疑这是一个空字符串 ( "")

顺便说一句,您正在创建一个冗余String对象,String dbContext = new String();您可以简单地做String dbContext = user.getClient_db();

也许问题出在您的 REST 方法上,我不确定您是否可以拥有多个有效负载(例如Principal principalUser user。尝试删除一个,看看是否有帮助


推荐阅读