本文通过书写自定义拦截器的方式模仿SpringSecurity中Filter的链式调用机制
在web.xml中配置拦截器,自定义拦截器
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>com.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
被拦截器拦截下的请求会进入DelegatingFilterProxy 中
package com.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.web.filter.GenericFilterBean;
public class DelegatingFilterProxy extends GenericFilterBean {
private Filter delegate=new FilterChainProxy();
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
// TODO Auto-generated method stub
// Let the delegate perform the actual doFilter operation.
invokeDelegate(delegate,request,response,filterChain);
}
private void invokeDelegate(Filter delagate, ServletRequest request,
ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
// TODO Auto-generated method stub
delagate.doFilter(request, response, filterChain);
}
}
实现链式调用的核心环节
package com.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.web.FilterInvocation;
import org.springframework.web.filter.GenericFilterBean;
public class FilterChainProxy extends GenericFilterBean implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain fc) throws IOException, ServletException {
// TODO Auto-generated method stub
// 此处的List为举例数据,实际情况中可以动态获取
FilterInvocation fi=new FilterInvocation(request,response,fc);
List<Filter> filters = getFilters(fi.getRequest());
if (filters == null || filters.size() == 0) {
fc.doFilter(request, response);
return;
}
VirtualFilterChain virtualFilterChain = new VirtualFilterChain(fi, filters);
virtualFilterChain.doFilter(fi.getRequest(), fi.getResponse());
}
private List<Filter> getFilters(HttpServletRequest request) {
// TODO Auto-generated method stub
List<Filter> filters=new ArrayList<Filter>();
filters.add(new UsernamePasswordAuthenticationFilter());
return filters;
}
private static class VirtualFilterChain implements FilterChain {
private final FilterInvocation fi;
private final List<Filter> additionalFilters;
private final int size;
private int currentPosition = 0;
private VirtualFilterChain(FilterInvocation filterInvocation, List<Filter> additionalFilters) {
this.fi = filterInvocation;
this.additionalFilters = additionalFilters;
this.size = additionalFilters.size();
}
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
if (currentPosition == size) {
fi.getChain().doFilter(request, response);
} else {
currentPosition++;
Filter nextFilter = additionalFilters.get(currentPosition - 1);
nextFilter.doFilter(request, response, this);
}
}
}
}
样例UsernamePasswordAuthenticationFilter 类,作为链中的一环出现
package com.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.web.filter.GenericFilterBean;
public class UsernamePasswordAuthenticationFilter extends GenericFilterBean {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain fc) throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("-----------");
fc.doFilter(request, response);
System.out.println("-----------");
}
}