2013-03-01 63 views
3

這是關於grails 1.3.7應用程序的具體內容,但希望這些答案也適用於新版本。下面的代碼是需要的簡化版本。 accountService正在被注入。下面的代碼片段完成了它應該做的事情,但顯然是重複的代碼。這是位於在grails-app一個UserFilter類/ conf目錄如何從Grails過濾器中刪除公共邏輯?

我如何提取常見的邏輯我的過濾器,保持重定向和檢查會話的能力?我已經嘗試將一種方法提取到過濾器類中,傳入會話和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 
    } 
    } 
}  

回答

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

您也可以使用|字符在controlleraction參數做普通工作跨控制器。它會因爲你使用*的管理控制器和僅適用於在用戶控制器的list動作不直接在這裏工作,但你可以做到爲明確的控制器/動作名稱檢查:

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

你可以也將邏輯移動到服務和依賴注入中。通常不是一個好主意,可以像這樣混合使用層,並在服務中使用HTTP邏輯,但這會將邏輯保留在一個地方。你可以使用與委託相同的技巧,或者只傳入會話/請求/響應/等。如所須。

0

您可以在代碼(控制器?)中聲明一個Closure,該代碼可以在後面調用。

示例:創建一個輔助方法

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