Grails-服务是否可以访问会话?

Grails-服务是否可以访问会话?,grails,Grails,GrailsServices默认情况下是否可以访问会话对象?因为能够做到: session.putSomeValueNeededLater 我之所以这样问,是因为我需要存储一个变量作为一个服务方法的结果,而另一个服务方法(在同一个服务中)以后可能需要这个变量,我试图通过服务中的全局变量来避免这样做,因为我觉得这被认为是糟糕的设计。所以我认为这次会议可能是另一种方法。谢谢 编辑:在我的服务中,我遇到以下情况: masterMethod() { call method1() cal

Grails
Service
s默认情况下是否可以访问会话对象?因为能够做到:

session.putSomeValueNeededLater
我之所以这样问,是因为我需要存储一个变量作为一个服务方法的结果,而另一个服务方法(在同一个服务中)以后可能需要这个变量,我试图通过服务中的全局变量来避免这样做,因为我觉得这被认为是糟糕的设计。所以我认为这次会议可能是另一种方法。谢谢

编辑:在我的服务中,我遇到以下情况:

masterMethod() {
    call method1()
    call method2()
    //Check if either method 1 or 2 set some variable that indicates whether method 3 needs to be called.
    if (condition == true) { call method3 } // Is it a good idea to store the condition in the session?

}

method 1() { //if some condition, masterMethod() needs to call method 3. Where to store this? In session? }
method 2() { //if some condition, masterMethod() needs to call method 3. Where to store this? In session? }
method 3() {...}

如果你想编写一个伟大的、可扩展的功能,你必须使用一个设计模式。 当像您的情况一样,您有一个操作列表,它依赖于一些有条件的事情或由一个流程管理时,正确的方法是使用责任链模式。 我还在grails应用程序中使用了它。我会给你看我的解决方案

第一步是创建一个接口,它不是一个服务,是一个标准groovy类,可以存储在Source/groovy中:

public interface MyMasterHandler {

    public void setNext(MyMasterHandler handler)

    public void handleRequest(Operation operation)

}
正如您所见,我们只有两种方法:用于创建链的setNext和用于放置单个责任链逻辑的HandlerRequest

因此,在创建一些处理程序之后,一个用于职责范围,另一个用于共享信息的对象:

对象:

public class Operation {
Boolean callmethod3 = false
}
Mthod1处理器:

    class Method1 implements MyMasterHandler {
        private MyMasterHandler next

        @Override
        void setNext(MyMasterHandler handler) {
            next = handler
        }

        @Override
        void handleRequest(Operation operation) throws SomeExceptionIfYouWant {
            if (some.condition || operation.some.condition )
    {
operation.callmethod3 = true

    }
    next.handleRequest(operation)
        }
    }
Mthod2处理器:

    class Method2 implements MyMasterHandler {
        private MyMasterHandler next

        @Override
        void setNext(MyMasterHandler handler) {
            next = handler
        }

        @Override
        void handleRequest(Operation operation) throws SomeExceptionIfYouWant {
            if (operation.callmethod3 == true )
    {
         next.handleRequest(operation)

    }

        }
    }
Mthod3处理器:

    class Method1 implements MyMasterHandler {
        private MyMasterHandler next

        @Override
        void setNext(MyMasterHandler handler) {
            next = handler
        }

        @Override
        void handleRequest(Operation operation) throws SomeExceptionIfYouWant {
            do stuff of method3
        }
    }
之后,在you服务/控制器中,您只需从会话或所需的会话初始化一个项目类(在本例中为操作),然后创建链:

class MyController(){
def test(){
Operation op = new Operation(params) //or session, here we use grails marshalling, if you have params.callmethod3 the object will auto initialized
MyMasterHandler one = new Method1()
MyMasterHandler two = new Method2()
MyMasterHandler three = new Method3()
one.setNext(two)
two.setNext(three)
one.handleRequest(op)
}
}
因此,一件好事是,业务登录在处理程序中被拆分,将来如果您想添加一个新的链,您必须只创建一个新的处理程序。 如果需要,可以将对象操作存储在控制器的会话中,然后将其传递给服务或创建并启动链的服务。
在链中,如果您愿意,您可以抛出特定的异常,因此在服务/控制器中,您可以处理抛出的异常,并根据需要执行任何操作。

如果您想编写一个出色且可扩展的功能,您必须使用设计模式。 当像您的情况一样,您有一个操作列表,它依赖于一些有条件的事情或由一个流程管理时,正确的方法是使用责任链模式。 我还在grails应用程序中使用了它。我会给你看我的解决方案

第一步是创建一个接口,它不是一个服务,是一个标准groovy类,可以存储在Source/groovy中:

public interface MyMasterHandler {

    public void setNext(MyMasterHandler handler)

    public void handleRequest(Operation operation)

}
正如您所见,我们只有两种方法:用于创建链的setNext和用于放置单个责任链逻辑的HandlerRequest

因此,在创建一些处理程序之后,一个用于职责范围,另一个用于共享信息的对象:

对象:

public class Operation {
Boolean callmethod3 = false
}
Mthod1处理器:

    class Method1 implements MyMasterHandler {
        private MyMasterHandler next

        @Override
        void setNext(MyMasterHandler handler) {
            next = handler
        }

        @Override
        void handleRequest(Operation operation) throws SomeExceptionIfYouWant {
            if (some.condition || operation.some.condition )
    {
operation.callmethod3 = true

    }
    next.handleRequest(operation)
        }
    }
Mthod2处理器:

    class Method2 implements MyMasterHandler {
        private MyMasterHandler next

        @Override
        void setNext(MyMasterHandler handler) {
            next = handler
        }

        @Override
        void handleRequest(Operation operation) throws SomeExceptionIfYouWant {
            if (operation.callmethod3 == true )
    {
         next.handleRequest(operation)

    }

        }
    }
Mthod3处理器:

    class Method1 implements MyMasterHandler {
        private MyMasterHandler next

        @Override
        void setNext(MyMasterHandler handler) {
            next = handler
        }

        @Override
        void handleRequest(Operation operation) throws SomeExceptionIfYouWant {
            do stuff of method3
        }
    }
之后,在you服务/控制器中,您只需从会话或所需的会话初始化一个项目类(在本例中为操作),然后创建链:

class MyController(){
def test(){
Operation op = new Operation(params) //or session, here we use grails marshalling, if you have params.callmethod3 the object will auto initialized
MyMasterHandler one = new Method1()
MyMasterHandler two = new Method2()
MyMasterHandler three = new Method3()
one.setNext(two)
two.setNext(three)
one.handleRequest(op)
}
}
因此,一件好事是,业务登录在处理程序中被拆分,将来如果您想添加一个新的链,您必须只创建一个新的处理程序。 如果需要,可以将对象操作存储在控制器的会话中,然后将其传递给服务或创建并启动链的服务。
如果需要,可以在链中抛出特定的异常,以便在服务/控制器中处理抛出的异常,并执行所需的操作。

您可以使用

def session = WebUtils.retrieveGrailsWebRequest().session
即使这将在服务中工作,您也应该只从web层(控制器、GSP、标记库等)访问会话。但是,对于您上面描述的特定场景,我不明白您为什么需要使用会话,您可以改为这样做吗

def masterMethod() {
    def method1Result = method1()
    def method2Result = method2()

    method3(method1Result, method2Result)        
}

def method3(method1Result, method2Result) {
    // decide what to do based on the results of methods 1 and 2
}       

您可以从Grails应用程序中的任何位置使用

def session = WebUtils.retrieveGrailsWebRequest().session
即使这将在服务中工作,您也应该只从web层(控制器、GSP、标记库等)访问会话。但是,对于您上面描述的特定场景,我不明白您为什么需要使用会话,您可以改为这样做吗

def masterMethod() {
    def method1Result = method1()
    def method2Result = method2()

    method3(method1Result, method2Result)        
}

def method3(method1Result, method2Result) {
    // decide what to do based on the results of methods 1 and 2
}       

您可以始终通过各种方法从控制器传递会话(被认为是糟糕的设计),也可以将服务会话限定为作用域(检查Grails文档),这将为每个会话生成一个服务实例。实际上,听起来好像您正在尝试组合数据/输出,您应该传递一个由各种方法作用的容器(有时只是一个简单的映射就可以做到这一点)。就我的两分钱;)@Joshuamore我在一个服务中有3个方法,其中两个可能会将变量(布尔值)设置为true,如果其中一个设置为true,则需要调用第三个方法。我想知道在哪里干净地存储这个变量,这样第三个方法就可以检查它是否需要执行。如果条件为true,可以设置此变量的两个方法当然可以调用第三个方法,但我不希望它们都调用第三个方法,因为这样它可能会被调用两次(因此不必要地调用一次).@Joshuamore编辑了这个问题,以便更清楚地解释我的场景。我将从保存条件状态的masterMethod内部向method1和method2传递一个变量。最简单的解决方案。在masterMethod中定义它,使其作用域限于执行,而不是整个服务。非常程序化,但它会起作用。@Joshuamore好的,谢谢,我会试试这个。非常感谢。您总是可以通过各种方法从控制器传递会话(被认为是糟糕的设计),或者您可以将服务会话限定为作用域(检查Grails文档),这将为每个会话生成一个服务实例。实际上,听起来您正试图组合数据/输出,您应该传递一个由各种方法作用的容器(因此