【问题标题】:How do I gain access to the data source in Spring?如何在 Spring 中访问数据源?
【发布时间】:2009-06-05 23:43:32
【问题描述】:

我阅读了this post,但我不明白如何使用ThreadLocalDataSourceLookupAbstractRoutingDataSource 访问请求。我阅读了每篇文章,但仍然无法正常工作。

如何访问我的请求的 dataSource 参数并动态创建与它们的连接?

【问题讨论】:

    标签: java spring


    【解决方案1】:

    我认为这类似于您链接到的答案:

    警告:这些都没有被编译。这些都没有经过测试。

    CurrentRequestFilter 每个请求运行一次。它负责将当前请求存储在ThreadLocal 中,供以后使用。

    public class CurrentRequestFilter extends OncePerRequestFilter {
    
        private ThreadLocal<HttpServletRequest> currentRequest;
    
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
            currentRequest.set(request);
            filterChain.doFilter(request, response);
        }
    
        public ThreadLocal<HttpServletRequest> getCurrentRequest() {
            return currentRequest;
        }
    
        public void setCurrentRequest(ThreadLocal<HttpServletRequest> currentRequest) {
            this.currentRequest = currentRequest;
        }
    
    }
    

    CurrentRequestDataSource 可以访问与CurrentRequestFilter 相同的ThreadLocal

    public class CurrentRequestDataSource extends AbstractRoutingDataSource {
    
        private ThreadLocal<HttpServletRequest> currentRequest;
    
        @Override
        protected DataSource determineTargetDataSource() {
            HttpServletRequest request = currentRequest.get();
    
            String url = ...;
            String username = ...;
            String password = ...;
            DataSource dataSource = ...;
    
            return dataSource;
        }
    
        @Override
        protected Object determineCurrentLookupKey() {
            return null;
        }
    
        public ThreadLocal<HttpServletRequest> getCurrentRequest() {
            return currentRequest;
        }
    
        public void setCurrentRequest(ThreadLocal<HttpServletRequest> currentRequest) {
            this.currentRequest = currentRequest;
        }
    }
    

    然后你会像这样配置你的 bean 定义:

    <bean id="currentRequest" class="java.lang.ThreadLocal"/>
    
    <bean id="currentRequestFilter" class="CurrentRequestFilter">
        <property name="currentRequest" ref="currentRequest"/>
    </bean>
    
    <bean id="dataSource" class="CurrentRequestDataSource">
        <property name="currentRequest" ref="currentRequest"/>
    </bean>
    
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    

    然后,您必须确保 CurrentRequestFilter 已在您的 web.xml 文件中注册:

    <filter>
        <filter-name>Current Request Filter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetBeanName</param-name>
            <param-value>currentRequestFilter</param-value>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>Current Request Filter</filter-name>
        <servlet-name>Name_Of_Your_Servlet</servlet-name>
    </filter-mapping>
    

    同样,这些都没有经过测试,但希望它可以提供一些指导。

    【讨论】:

    • 对我来说,所有的东西都有些古怪——根据请求参数更改数据源(记住这些参数来自用户框)——但这看起来应该可以解决问题。
    • 作为记录,我同意这似乎有点时髦。我永远不会自己做。我只是想看看其他人在推荐什么。说实话,其他人的答案不是从头开始创建新的数据源。相反,他是在几个预先构建的数据源之间进行选择。
    【解决方案2】:

    我不确定您的意思是什么参数,或者请求是什么。您是否正在尝试编写 Web 应用程序?这是一个 HttpRequest 吗?您是否根据请求确定需要什么样的数据源?

    根据这些问题的答案,您可能不需要动态访问数据源。

    如果您有多个数据源,每个数据源都服务于不同类型的请求,我建议将数据源注入到服务对象中,这些服务对象被注入到为特定 URL 选择的 Web 控制器中。您将能够以这种方式改变数据源,没有什么比 Web 层中的 URL 映射更有趣的了。

    在不了解您的用例的情况下,我猜您可能过于复杂了,因为您是 Spring 新手,还不知道如何正确使用它。无意侮辱,只是猜测。

    更新:

    “我不能改变它”——你至少应该在假设之前与客户讨论一下。这是一个坏主意。加密参数不会拯救你。

    您最好创建一个工厂,控制器可以使用该工厂来实例化注入了您需要的所有数据源的工厂。将数据源存储在地图中,然后简单地来回传递一个键来获取数据源。控制器已经可以访问请求;您使用户不必知道有关数据库的所有这些详细信息;您使查找成为一个简单的键(我仍然不喜欢)。

    如果它看起来太难了,你可能不应该这样做。有更简单的方法。重新考虑一下。

    【讨论】:

    • 嗨,我想用 spring 创建多个数据源 bean,但是连接参数(url、驱动程序、用户、...)由另一个 Web 应用程序传递给我的应用程序,我正在使用 hibernate而且我不知道如何在请求中传递参数以动态创建连接,我认为解决方案在这篇文章的末尾:stackoverflow.com/questions/517353/… 但我不明白如何使用 ThreadLocal 或 DataSourceLookup 或 AbstractRoutingDataSource 访问请求,谢谢你的帮助...
    • 抱歉,我不太喜欢这种设计。另一个传递连接参数的网络应用程序?不,这是最糟糕的封装。您是在强迫客户了解您需要的所有数据源吗?错了,错了,错了。重新考虑一下。这可能是你的第一个想法,但不要让它成为你的最后一个想法。
    • 传入这些参数意味着您也无法利用连接池。这个规模如何?
    • 是的,我知道,但我不能改变它,至少参数是加密的......你知道我如何无法使用 DataSourceLookup 实现中的威胁访问请求吗?对不起,我是拉丁美洲人的语法......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-16
    • 2016-05-03
    • 1970-01-01
    • 2017-07-30
    • 2020-07-11
    相关资源
    最近更新 更多