【发布时间】:2009-06-05 23:43:32
【问题描述】:
我阅读了this post,但我不明白如何使用ThreadLocal 或DataSourceLookup 或AbstractRoutingDataSource 访问请求。我阅读了每篇文章,但仍然无法正常工作。
如何访问我的请求的 dataSource 参数并动态创建与它们的连接?
【问题讨论】:
我阅读了this post,但我不明白如何使用ThreadLocal 或DataSourceLookup 或AbstractRoutingDataSource 访问请求。我阅读了每篇文章,但仍然无法正常工作。
如何访问我的请求的 dataSource 参数并动态创建与它们的连接?
【问题讨论】:
我认为这类似于您链接到的答案:
警告:这些都没有被编译。这些都没有经过测试。
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>
同样,这些都没有经过测试,但希望它可以提供一些指导。
【讨论】:
我不确定您的意思是什么参数,或者请求是什么。您是否正在尝试编写 Web 应用程序?这是一个 HttpRequest 吗?您是否根据请求确定需要什么样的数据源?
根据这些问题的答案,您可能不需要动态访问数据源。
如果您有多个数据源,每个数据源都服务于不同类型的请求,我建议将数据源注入到服务对象中,这些服务对象被注入到为特定 URL 选择的 Web 控制器中。您将能够以这种方式改变数据源,没有什么比 Web 层中的 URL 映射更有趣的了。
在不了解您的用例的情况下,我猜您可能过于复杂了,因为您是 Spring 新手,还不知道如何正确使用它。无意侮辱,只是猜测。
更新:
“我不能改变它”——你至少应该在假设之前与客户讨论一下。这是一个坏主意。加密参数不会拯救你。
您最好创建一个工厂,控制器可以使用该工厂来实例化注入了您需要的所有数据源的工厂。将数据源存储在地图中,然后简单地来回传递一个键来获取数据源。控制器已经可以访问请求;您使用户不必知道有关数据库的所有这些详细信息;您使查找成为一个简单的键(我仍然不喜欢)。
如果它看起来太难了,你可能不应该这样做。有更简单的方法。重新考虑一下。
【讨论】: