我的服务既来自Quartz(没有会话范围),也来自Web流(带会话范围)。
从Web Flow调用时,可能会设置一些可选标志,我想安全地检查它们,如果它们存在。
我正在使用会话范围,因为我调用的函数远远落后于调用链,并且传递选项或范围一直都会触及大量代码。
我想知道是否有类似的内容:
if(someObject.session?.myFlag)
其中"会话"如果从Web流调用,则引用会话范围;如果从Quartz调用,则引用null。
提前致谢!
答案 0 :(得分:3)
您似乎已经知道,从服务中访问会话范围不是值得鼓励的,因为HTTP会话只应在Web层(GSP,控制器,过滤器等)中使用。
现在你没有听到这个消息,但你可以从这样的地方访问当前的会话:
def session = org.codehaus.groovy.grails.web.util.WebUtils.
retrieveGrailsWebRequest().session
有权访问会话后,您可以检查属性是否存在,或使用通常的HttpSession
API检索它们。
答案 1 :(得分:1)
我会使用Filter和ThreadLocal方法。
使用静态ThreadLocal变量创建一个类,该变量包含对该类实例的引用。然后可以从执行线程的任何地方引用此实例,它将提供对变量和标志的访问。这样,您就不会直接引用服务中的HTTP会话API。
最后创建一个Filter,在执行其余链之前设置ThreadLocal值。记得在线程完成后清除值的状态。
class MyExecutionContext {
private static ThreadLocal instance = new ThreadLocal<MyExecutionContext>()
private HttpSession session
private ServletRequest request
// set the state for current thread
// you can add request here too, if you want/need
public static void setContext(ServletRequest req, HttpSession s) {
stateInstance.set(new MyExecutionContext(req, s))
}
// get the state of current thread
public static getContext() {
return instance.get()
}
// clear the current state
public static void clearContext() {
stateInstance.remove()
}
// private constructor
private MyExecutionContext(ServletRequest req, HttpSession s) {
request = req
session = s
}
// now the actual methods to query any kinds of things you need
// from session (or request if you gave it in the constructor)
public String getSomething() {
(String) session?.getAttribute("somethingInSession")
}
public String getSomethingElse() {
(String) request?.getAttribute("somethingInRequest")
}
}
class ContextFilter extends Filter {
public void doFilter(...) {
try {
MyExecutionContext.setContext(request, request.getSession(false))
chain.doFilter(req, res)
} finally {
// make sure you clear the state
MyExecutionContext.clearContext()
}
}
}
// usage in your service
class YourService {
def method() {
if (MyExecutionContext?.context?.something) {
// value exists in session
}
}
}