如何从grails过滤器中去除常见逻辑?

如何从grails过滤器中去除常见逻辑?,grails,grails-filters,Grails,Grails Filters,这是专门针对Grails1.3.7应用程序的,但希望答案也适用于较新版本。下面的代码是所需代码的简化版本。正在注入accountService。下面的代码片段做了它应该做的事情,但显然是重复的代码。这在grails app/conf中的UserFilter类中 如何从过滤器中提取公共逻辑,并保持重定向和检查会话的功能?我尝试将一个方法提取到filter类中,传入会话和flash,但重定向仍然给我带来问题 def filters = { // ... other filters ... a

这是专门针对Grails1.3.7应用程序的,但希望答案也适用于较新版本。下面的代码是所需代码的简化版本。正在注入accountService。下面的代码片段做了它应该做的事情,但显然是重复的代码。这在grails app/conf中的UserFilter类中

如何从过滤器中提取公共逻辑,并保持重定向和检查会话的功能?我尝试将一个方法提取到filter类中,传入会话和flash,但重定向仍然给我带来问题

def filters = {
  // ... other filters ...
  adminAllCheck(controller: 'administration', action: '*') {
    before = {
      if(!session.isAdmin) {
        if(accountService.isAdmin()) {
          session.isAdmin = true
        } else {
          flash.message = 'Non admin'
          redirect(controller: 'home', action: 'index')
          return false
        }
      }
      true
    }
  }
  userListCheck(controller: 'user', action: 'list') {
    before = {
      if(!session.isAdmin) {
        if(accountService.isAdmin()) {
          session.isAdmin = true
        } else {
          flash.message = 'Non admin'
          redirect(controller: 'home', action: 'index')
          return false
        }
      }
      true
    }
  }
}    

您可以在您的代码(控制器?)中声明一个
闭包
,该闭包可以在之后调用

样本:

private def ensureSessionAdmin = {
  if(!session.isAdmin) {
    if(accountService.isAdmin()) {
      session.isAdmin = true
    } else {
      flash.message = 'Non admin'
      redirect(controller: 'home', action: 'index')
      return false
    }
  }
  true
}
def filters = {
  // ... other filters ...
  adminAllCheck(controller: 'administration', action: '*') {
    before = ensureSessionAdmin
  }
  userListCheck(controller: 'user', action: 'list') {
    before = ensureSessionAdmin
  }
}    

创建助手方法的一种方法是在
过滤器
闭包之外创建它,并传入实例。传入
this
不起作用,因为这不是闭包,而是
UserFilters
实例。而是传入闭包的
委托
,该委托添加了
呈现
重定向
方法,其中
参数
控制器名
等属性为:

class UserFilters {
   def filters = {
      // ... other filters ...
      adminAllCheck(controller: 'administration', action: '*') {
         before = {
            doAdminCheck(delegate)
         }
      }
      userListCheck(controller: 'user', action: 'list') {
         before = {
            doAdminCheck(delegate)
         }
      }
   }

   private boolean doAdminCheck(filters) {
      if (!filters.session.isAdmin) {
         if (accountService.isAdmin()) {
            filters.session.isAdmin = true
         }
         else {
            filters.flash.message = 'Non admin'
            filters.redirect(controller: 'home', action: 'index')
            return false
         }
      }
      true
   }
}
您还可以使用
控制器
操作
参数中的
|
字符跨控制器执行常见工作。它不能直接在这里工作,因为您对管理控制器使用
*
,并且只应用于用户控制器中的
列表
操作,但您可以对其执行显式控制器/操作名称检查:

adminCheck(controller: 'administration|user', action: '*') {
   if (controllerName == 'user' && actionName != 'list') {
      return true
   }
   // common logic here
}
您还可以将逻辑移到服务中,并将依赖项注入其中。在服务中混合这样的层和HTTP逻辑通常不是一个好主意,但这样可以将逻辑保持在一个位置。您可以对委托使用相同的技巧,或者根据需要传入会话/请求/响应等