前言
Tomcat容器以及一些Web框架都使用了责任链设计模式来对请求和响应进行逐步的处理或者过滤,本文使用Java语言来模拟过滤器的实现。其序列图如下:
如果简单的使用 责任链模式 ,用一个List来实现层层过滤,则会导致request的处理是按照顺序来执行,response也会按照顺序来执行,这就与我们期望的response按照倒序来执行相悖。因此要用一种方式实现request顺序处理,response倒序处理。
实现
类图大致如下:
首先,写两个实体类,Request和Response
Request.java
public class Request { private String requestStr; public String getRequestStr() { return requestStr; } public void setRequestStr(String requestStr) { this.requestStr = requestStr; } }
Response.java
public class Response { private String responseStr; public String getResponseStr() { return responseStr; } public void setResponseStr(String responseStr) { this.responseStr = responseStr; } } }
面向接口编程 ,编写过滤器接口。
Filter.java
public interface Filter { void doFilter(Request request, Response response, FilterChain chain); }
这里每次进行过滤后,都将过滤器链指向下一个过滤器,进行过滤,执行完后,再逐层返回,有点类似于递归。
编写过滤器链
FilterChain.java
public class FilterChain implements Filter{ private List<Filter> filters = new ArrayList<>(); private int index = 0; public FilterChain addFilter(Filter f){ this.filters.add(f); return this; } @Override public void doFilter(Request request, Response response, FilterChain chain) { if(index == filters.size()) return; Filter f = filters.get(index); index ++; f.doFilter(request, response, chain); } }
该类中进行了两个操作,一个是过滤器的添加,一个是每一次过滤完成后,将索引加一后,再到下一个过滤器进行过滤,当走到尽头,再逐层返回。这有点类似于双向链表,先从头指针往后走,到了尽头再往前走。
编写两个过滤器类
HtmlFilter.java
public class HtmlFilter implements Filter { @Override public void doFilter(Request request, Response response, FilterChain chain) { request.setRequestStr(request.getRequestStr().replace('<', '[').replace('>', ']') + "---HtmlFilter"); chain.doFilter(request, response, chain); response.setResponseStr(response.getResponseStr() + "---HtmlFilter"); } }
将尖括号替换为中括号。
SeansitiveFilter.java
public class SensitiveFilter implements Filter { @Override public void doFilter(Request request, Response response,FilterChain chain) { request.setRequestStr(request.getRequestStr().replace("被就业", "就业").replace("敏感", "") + "---SensitiveFilter"); chain.doFilter(request, response, chain); response.setResponseStr(response.getResponseStr() + "---SensitiveFilter"); } }
去掉敏感词汇
最后编写测试用例
Main.java
public class Main { public static void main(String[] args) { String msg = "大家好:),<script>,敏感,被就业"; Request request = new Request(); request.setRequestStr(msg); Response response = new Response(); response.setResponseStr("response"); FilterChain fc = new FilterChain(); fc.addFilter(new HtmlFilter()).addFilter(new SensitiveFilter()); fc.doFilter(request, response, fc); System.out.println(request.getRequestStr()); System.out.println(response.getResponseStr()); } }
最终输出的结果为:
大家好:),[script],,就业---HtmlFilter---SensitiveFilter response---SensitiveFilter---HtmlFilter
如果因为某一原因不进行接下来的过滤,则在FilterChain中加一个判断条件,在第几个过滤器不满足条件时,则不执行下一个过滤器的过滤,直接return即可,这样就直接返回了,response不会再进行相应过滤器的加工处理。