如何安全地检测服务中是否存在会话范围?

时间:2014-05-26 21:25:02

标签: session grails scope

我的服务既来自Quartz(没有会话范围),也来自Web流(带会话范围)。

从Web Flow调用时,可能会设置一些可选标志,我想安全地检查它们,如果它们存在。

我正在使用会话范围,因为我调用的函数远远落后于调用链,并且传递选项或范围一直都会触及大量代码。

我想知道是否有类似的内容:

if(someObject.session?.myFlag)

其中"会话"如果从Web流调用,则引用会话范围;如果从Quartz调用,则引用null。

提前致谢!

2 个答案:

答案 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
        }
    }
}