我有这个课:
package ds;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import play.mvc.Http;
public class MyRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected String determineCurrentLookupKey() {
return Http.Context.current().session().get("currentDB");
}
}
但是,当我想进入Play会话时,会出现以下错误:
Caused by: java.lang.RuntimeException: There is no HTTP Context available from here.
at play.mvc.Http$Context.current(Http.java:34) ~[play_2.10-2.3.10.jar:2.3.10]
at play.mvc.Controller.session(Controller.java:72) ~[play_2.10-2.3.10.jar:2.3.10]
我还尝试了HttpExecution.defaultContext()和他的HttpExecutionContext,但是无法将其强制转换为我需要的Http.Context。
我正在考虑获取请求标头,但我当然不知道如何从我的课程中处理它,并根据请求确定会话
由于该层超出范围,因此您无法访问“播放上下文”。在AbstractRoutingDatasource的文档中:
该类的主要描述是:
基于查询键将getConnection()调用路由到各种目标DataSource之一的抽象DataSource实现。后者通常(但不是必须)通过某些线程绑定的事务上下文来确定。
因此,该类建议一种获取当前上下文信息的方法应该使用线程绑定事务上下文。
现在,PlayFramework线程上下文安全吗?阅读Play文档:
https://www.playframework.com/documentation/2.3.x/ThreadPools#Java-thread-locals
Play中的Java代码使用本地线程来查找有关上下文的信息,例如当前的HTTP请求。Scala代码不需要使用线程局部变量,因为它可以使用隐式参数来传递上下文。线程局部变量在Java中使用,因此Java代码可以访问上下文信息,而无需在任何地方传递上下文参数。
因此,如果使用Java实现,则可以将ThreadLocals用作组件之间的上下文通道。如果创建自己的线程池,请小心,因为在同一文档中有一个警告:
默认对象包装了默认用户线程池。如果要执行自己的线程处理,则应使用HttpExecution类的帮助程序方法自己获取ExecutionContextExecutor对象。
但是,如果您没有在应用程序中使用自定义线程池,那将不是问题。
话虽如此,您要做的是:
为要用作路由器的对象定义ThreadLocalContext。
放在上下文中。(如果您使用的是Deadbolt之类的授权框架,或者甚至实现了新的请求过滤器,则可以在控制器中,在安全控制器中进行操作。)
在AbstractRoutingDataSource中读取ThreadLocal上下文。
重要的!不要忘了清理本地线程,否则您可能会遇到内存泄漏。
步骤1:
public class RequestContext {
private static final ThreadLocal<String> contextHolder =
new ThreadLocal<String>();
public static void setRoutingKey(String key) {
contextHolder.set(key);
}
public static String getRoutingKey() {
return (String) contextHolder.get();
}
public static void clearRoutingKey() {
contextHolder.remove();
}
}
第2步:
//Demostrative code, not tested, not even compiled
public static void myController() {
RoutingContext.setRoutingKey(Play.Context.request());
return bla;
}
第三步:
@Override
protected Object determineCurrentLookupKey() {
String datasource = RoutingContext.getRoutingKey();
RoutingContext.clearRoutingKey();
return datasource;
}
问候!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句