spring之我见--从Filter机制看设计模式(责任链模式,装饰器模式)
最近为公司⼀个项⽬写⼀个简单的⽹关,其实也就是⼀个filter做⼀些token解析/校验。但是光这⼀个filter就不简单,现在就说说⾥⾯运⽤的设计模式。
Filter的核⼼-责任链模式
Filter: 属于javaweb中⼀个重要的组件,对请求资源进⾏处理(request和response)。
FilterChain: 管理着所有filter的顺序和执⾏,就像⼀个链条。通过这种链式串联,我们就可以对同⼀种对象资源实现不同业务场景的处理,达到业务解耦。
再看看spring⾥的源码实现:
FilterChain实现:
public final class ApplicationFilterChain implements FilterChain {
/**
* Filters.
*/
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
/**
* The int which is used to maintain the current position
* in the filter chain.
*/
private int pos = 0;
/**
* The int which gives the current number of filters in the chain.
*/
private int n = 0;
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
internalDoFilter(request,response);
}
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
/
/ Call the next filter if there is one
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = Filter();
filter.doFilter(request, response, this);
}
}
}
Filter的⼀个实现:
public class GateWayFilter implements Filter {
@Override
filter过滤对象数组public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {      //这⾥填充业务代码
filterChain.doFilter(servletRequest, servletResponse);
}
}
我删除了绝⼤部分跟涉及模式⽆关的代码,这个FilterChain 和 Filter 做了什么就很清晰了。
FilterChain 拥有 所有filter集合的配置类(ApplicationFilterConfig),每次请求都会 初始化 pos(filter数组下标) 和 n (filter过滤器总数)。 然后每次⾛完第⼀个 filter,都会执⾏ filterChain对象 的 doFilter继续执⾏下⼀个filter。
filterChain.doFilter(servletRequest, servletResponse);
责任链模式让我们的request 和response经过数⼗个filter的处理后(各个filter之间不耦合,可拓展性强),最终到达spring 的endpoint 层,体会到了设计的精妙。
Filter的得⼒助⼿-装饰器模式
还是以具体场景为例,我在写⽹关过滤器的时候需要在过滤器中临时新加⼀些header信息,本来以为request会提供addHeader的⽅法,但是很遗憾,这个⽅法需要⾃⼰来实现。很明显的是,我们需要增强HttpServletRequest接⼝。这时候HttpServletRequestWrapper装饰器类登场了,它的构造器只接收⼀个HttpServletRequest对象,并且可以⽅便覆写HttpServletRequest的⽅法。
public class HttpServletRequestWrapper extends ServletRequestWrapper implements
HttpServletRequest {
/**
* Constructs a request object wrapping the given request.
*
* @param request The request to wrap
*
* @throws java.lang.IllegalArgumentException
*            if the request is null
*/
public HttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
。。。。。。
}
我们写⼀个继承HttpServletRequestWrapper的类。增加⼀个map变量,然后新增⼀个putHeader⽅法,⽤来实现我们增加header信息的⽬的,但是这样别⼈调⽤getHeaders⽅法还是取不到我们新增的键值对,我们需要复写getHeaders⽅法来实现⽬的。
class MutableHttpServletRequest extends HttpServletRequestWrapper {
private final Map<String, String> customHeaders;
public MutableHttpServletRequest(HttpServletRequest request) {
super(request);
this.customHeaders = new HashMap<>();
}
public void putHeader(String name, String value) {
this.customHeaders.put(name, value);
}
@Override
public Enumeration<String> getHeaders(String name) {
Enumeration<String> headers = Headers(name);
if (null == headers || !headers.hasMoreElements()) {
String value = (name);
if (StringUtils.isNotBlank(value)) {
umeration(Arrays.asList(value));
}
} else {
return headers;
}
return null;
}
@Override
public String getHeader(String name) {
/
/ check the custom headers first
String headerValue = (name);
if (StringUtils.isNotBlank(headerValue)) {
return headerValue;
}
// else return from into the original wrapped object
Header(name);
}
@Override
public Enumeration<String> getHeaderNames() {
// create a set of the custom header names
Set<String> set = new HashSet<>(customHeaders.keySet());
// now add the headers from the wrapped request object
@SuppressWarnings("unchecked")
Enumeration<String> e = ((HttpServletRequest) getRequest()).getHeaderNames();
while (e.hasMoreElements()) {
// add the names of the request headers into the list
String n = e.nextElement();
set.add(n);
}
// create an enumeration from the set and return
umeration(set);
}
}
结语
虽然filter并不是spring的内容,但是设计模式处处都有,所以多看⼀些优秀的源码来提⾼⾃⼰的编码⽔平还是有道理的

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。