2011-08-25 3 views
29

web.xml과 다른 방식으로 필터를 수정/구성 할 수 있습니다. 다음은 2 개의 필터로 구성된 정적 구성입니다. 하나의 필터를 정적으로 구성하고 추가 필터를로드 할 수있는 기능을 원합니다. 나는 이미 이걸 가지고있는 lib를 아는 사람이 있는지 알고 싶었다. 나는이 필터가 런타임에 구성되어 GuiceFilter과 Guice에서 수행 본 적이 서블릿 API 2.5web.xml을 수정하지 않고 서블릿에 필터를 추가하는 방법

<web-app> 
    ... 
    <filter> 
    <filter-name>MyFilter1</filter-name> 
    <filter-class>com.me.MyFilter1</filter-class> 
    </filter> 
    <filter-mapping> 
    <filter-name>MyFilter1</filter-name> 
    <url-pattern>/*</url-pattern> 
    </filter-mapping> 
    ... 
    <filter> 
    <filter-name>MyFilter2</filter-name> 
    <filter-class>com.me.MyFilter2</filter-class> 
    </filter> 
    <filter-mapping> 
    <filter-name>MyFilter2</filter-name> 
    <url-pattern>/*</url-pattern> 
    </filter-mapping> 
    ... 
</web-app> 

를 사용

.

+0

그것은 서블릿 컨테이너의 의존하는 것, 그래서 당신이 의존해야 – SJuan76

+0

를 사용하고있는 한 당신이 우리를 말해야한다? GuiceFilter가 컨테이너에 종속되어 있습니까? – TJR

+0

Guice는 'web.xml'매핑과 같이 동작하는 자체 매핑 메커니즘을 롤백합니다. 웹 컨테이너의 경우 모든 요청이 'GuiceFilter'에서 끝납니다. Guice를 원한다면 그냥 사용하십시오 :) –

답변

35

컨테이너와 동일한 작업을 이미 수행합니다. 나는. 서블릿 필터에서 사용 된 커버 아래에있는 디자인 패턴 chain of responsibility의 휠을 재발 명하십시오. 또한 먹이를

public class Pattern { 

    private int position; 
    private String url; 

    public Pattern(String url) { 
     this.position = url.startsWith("*") ? 1 
         : url.endsWith("*") ? -1 
         : 0; 
     this.url = url.replaceAll("/?\\*", ""); 
    } 

    public boolean matches(String path) { 
     return (position == -1) ? path.startsWith(url) 
      : (position == 1) ? path.endsWith(url) 
      : path.equals(url); 
    } 

} 

public class GodFilterChain implements FilterChain { 

    private FilterChain chain; 
    private List<Filter> filters = new ArrayList<Filter>(); 
    private Iterator<Filter> iterator; 

    public GodFilterChain(FilterChain chain) { 
     this.chain = chain; 
    } 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { 
     if (iterator == null) { 
      iterator = filters.iterator(); 
     } 

     if (iterator.hasNext()) { 
      iterator.next().doFilter(request, response, this); 
     } else { 
      chain.doFilter(request, response); 
     } 
    } 

    public void addFilter(Filter filter) { 
     if (iterator != null) { 
      throw new IllegalStateException(); 
     } 

     filters.add(filter); 
    } 

} 

당신 수 필요한 경우 : (필요한 위 GodFilterprivate static 중첩 된 클래스를 할 수있는 경우) 그 작은 헬퍼 클래스와

public class GodFilter implements Filter { 

    private Map<Pattern, Filter> filters = new LinkedHashMap<Pattern, Filter>(); 

    @Override 
    public void init(FilterConfig config) throws ServletException { 
     Filter1 filter1 = new Filter1(); 
     filter1.init(config); 
     filters.put(new Pattern("/foo/*"), filter1); 

     Filter2 filter2 = new Filter2(); 
     filter2.init(config); 
     filters.put(new Pattern("*.bar"), filter2); 

     // ... 
    } 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { 
     HttpServletRequest hsr = (HttpServletRequest) request; 
     String path = hsr.getRequestURI().substring(hsr.getContextPath().length()); 
     GodFilterChain godChain = new GodFilterChain(chain); 

     for (Entry<Pattern, Filter> entry : filters.entrySet()) { 
      if (entry.getKey().matches(path)) { 
       godChain.addFilter(entry.getValue()); 
      } 
     } 

     godChain.doFilter(request, response); 
    } 

    @Override 
    public void destroy() { 
     for (Filter filter : filters.values()) { 
      filter.destroy(); 
     } 
    } 

} 

XML 구성 파일에 가능한 모든 필터가 있으므로 쉽게 구성 할 수 있습니다. 리플렉션을 사용하여 GodFilterinit()에 필터를 만들 수 있습니다.

은 신경 끄시 아, 그건 무엇 web.xml 이미 컨테이너가하고있는 ...

+0

GodFilterChain.doFilter()를 반복하지 않아야합니다 추가 된 모든 필터는 첫 번째 필터 만 사용하는 것보다? – MRalwasser

+0

@Malwasser : 어, 아니. 아마도 "Chain of Responsibility"디자인 패턴이 어떻게 작동하지 않았을까요? 필터 구현의'chain.doFilter()'호출은'GodFilterChain # doFilter()'를 다시 호출합니다 ('this'는'FilterChain' 인자로 전달 되었기 때문에). 그리고 반복자는 다음 요소로 넘어갈 것이고, 등. – BalusC

+0

아아, 그 후속 iterator.next() 호출은 더 깊은 "체인 레벨"내부에서 수행됩니다. 감사합니다, 이것을 지적하십시오. – MRalwasser

15

Servlet 3.0에는 필터를 정의하는 데 사용되는 @WebFilter 주석이 있습니다. 더 이상 web.xml에서 선언 할 필요가 없습니다.

그러나 필터에서 필터를로드하는 것은 지원되지 않습니다. 스스로 구현할 수도 있습니다 : 그것은 책임 패턴의 "단순한"체인이지만, 왜 그럴까요?

+2

내 대답을 삭제하고 30 초 만에 나를 때려> | – Dave

+2

@JB Nizet : TJR은 버전 서블릿 3.0을 요구하지 않고 서블릿 2.5 – developer

+0

@JB와 만 관련이 있습니다. 2.5를 사용하고 있다는 질문에 제가 추가했습니다. 그 3.0 기능은 저를 행복하게 만듭니다. – TJR

4

그것도 사전 서블릿 3.0 규격에 대한 쉬운 단계에서 달성 될 수

  1. 클래스의 정적 & 정렬 컬렉션 (고리)를 함유하는 필터를 추가한다.
  2. 모든 트래픽을 가로 채기 위해 필터를 매핑하십시오.
  3. & 순서대로 조작하십시오. 도우미 클래스가 존재합니다 (트래픽을 차단하면 필터가 개인적으로 호출합니다).

참고 : Xstream은 서블릿/필터에서는 잘 작동하지 않는 동일한 유형의 패턴을 사용합니다. :)

관련 문제