2013-03-01 3 views
3

이것은 특히 grails 1.3.7 응용 프로그램에 관한 것이지만 잘하면 대답은 최신 버전에서도 잘 작동합니다. 아래 코드는 필요한 것을 단순화 한 것입니다. accountService가 주입 중입니다. 아래 스 니펫은 수행해야 할 작업을 수행하지만 명확하게 반복 코드입니다. 이것은 grails-app/conf에있는 UserFilter 클래스에 있습니다.grails 필터에서 일반적인 로직을 어떻게 제거합니까?

내 필터에서 일반적인 로직을 추출하고 리디렉션 및 세션 확인 기능을 유지하려면 어떻게해야합니까? 세션과 플래시를 전달하는 필터 클래스에 메서드를 추출해 보았습니다.하지만 리디렉션을 통해 여전히 문제가 발생했습니다.

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 인스턴스. 대신 전달 paramscontrollerName 같은 속성이있는 renderredirect 방법이 추가되는 곳이다 폐쇄의 delegate :

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