如何从grails过滤器中删除常用逻辑?

Rob*_*ner 3 grails grails-filters

这特别是关于grails 1.3.7应用程序,但希望答案也适用于较新版本.下面的代码是所需内容的简化版本.正在注入accountService.下面的片段做了它应该做的事情,但显然是重复的代码.这是位于grails-app/conf中的UserFilter类

如何从过滤器中提取常用逻辑并保持重定向和检查会话的功能?我已经尝试将一个方法提取到过滤器类中,传递会话和闪存,但重定向仍然给我带来问题.

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
    }
  }
}    
Run Code Online (Sandbox Code Playgroud)

Bur*_*ith 6

创建辅助方法的一种方法是在filters闭包之外创建它,然后传入实例.它不能传入,this因为它不是闭包而是UserFilters实例.而是传递闭包delegate,这是添加renderredirect方法的地方,其中属性paramscontrollerName:

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
   }
}
Run Code Online (Sandbox Code Playgroud)

您还可以使用和参数中的|字符来跨控制器执行常见工作.它不能直接在这里工作,因为您使用管理控制器并且仅应用于用户控制器中的操作,但您可以执行明确的控制器/操作名称检查:controlleraction*list

adminCheck(controller: 'administration|user', action: '*') {
   if (controllerName == 'user' && actionName != 'list') {
      return true
   }
   // common logic here
}
Run Code Online (Sandbox Code Playgroud)

您还可以将逻辑移动到服务并依赖注入 - 重新注入.通常不是这样混合层并在服务中使用HTTP逻辑的好主意,但这会将逻辑保留在一个位置.您可以对委托使用相同的技巧,或者只是传入会话/请求/响应/等.如所须.