责任链模式

  • 责任链模式,顾名思义主要应用场景为一步一步往下走,比如审核。
public class Main {
    public static class HandlerDTO {
        private String msg;
        public HandlerDTO(String msg) {
            this.msg = msg;
        }
    }
    interface Filter {
        Boolean doFilter(HandlerDTO s);
    }
    public static class FilterChain implements Filter{
        public List<Filter> filterChainList = new ArrayList<>();
        public void add(Filter filter){
            filterChainList.add(filter);
        }
        public void addAll(List<Filter> filters){
            filterChainList.addAll(filters);
        }
        @Override
        public Boolean doFilter(HandlerDTO handler){
            return filterChainList.stream().map(filter -> filter.doFilter(handler)).noneMatch(aBoolean -> !aBoolean);
        }
    }
    public static class DataFilter implements Filter{ //过滤敏感信息
        @Override
        public Boolean doFilter(HandlerDTO s) {
            return s.msg.contains("996");
        }
    }
    public static class MgFilter implements Filter{ // 防止js 注入
        @Override
        public Boolean doFilter(HandlerDTO s) {
            return s.msg.contains("<");
        }
    }
    public static void main(String[] args) {
        String a = "hello,i am xxx,<script>alert()</script> ,我天天996,真是太辛苦了";
        var handler = new HandlerDTO(a);
        var filterChain = new FilterChain();
        filterChain.addAll(List.of(new DataFilter(),new MgFilter()));
        var filterChain2 = new FilterChain();
        filterChain.addAll(List.of(new DataFilter(),new MgFilter()));
        filterChain.add(filterChain2);
        filterChain.doFilter(handler);
        System.out.println(handler.msg);
    }
}
  • 对同一个对象做不同处理,把他们职责拆分开,用不同的实现类取实现,以达到解耦,可组合的效果。
  • 由于filterChain 也实现了filter 接口 FilterChain 之间也是可组合的。
  • 挺巧妙的当filterChain 里的 list 也是filterChain时 调用其doFIlter 会 循环其内部的Filter实现类。
  • 我觉得比起Filter 返回false 如果更复杂的业务场景下可以把boolean 当作一个Handler 对象中的参数存起来,比如 我不光要过滤敏感数据,还得返回是否存在敏感数据的需求。

  • 实现servlet 的责任链
/**
 * 实现一个filter从头到后过滤request,从后到前过滤response
 */
public class ServletMain {
    public static class FilterChain {
        public List<Filter> filterChainList = new ArrayList<>();
        int index = 0;

        public void add(Filter filter) {
            filterChainList.add(filter);
        }

        public void addAll(List<Filter> filters) {
            filterChainList.addAll(filters);
        }

        public void doFilter(Request request, Response response,FilterChain chain) {
            if(index == filterChainList.size()){
                return;
            }
            Filter f = filterChainList.get(index);
            index ++;

            f.doFilter(request, response, this);
        }
    }

    interface Filter {
        void doFilter(Request request, Response response,FilterChain filterChain);
    }

    public static class DataFilter implements Filter { //过滤敏感信息
        @Override
        public void doFilter(Request request, Response response,FilterChain chain) {
           request.str = request.str.replaceAll("996","955");
            chain.doFilter(request,response,chain);
            response.str += "DataFilter";
        }
    }

    public static class MgFilter implements Filter { // 防止js 注入
        @Override
        public void doFilter(Request request, Response response,FilterChain chain) {
            request.str = request.str.replaceAll("<","[").replaceAll(">","]");
            chain.doFilter(request,response,chain);
           response.str += "MgFilter++";
        }
    }

    public static class Request {
        private String str;

        public String getStr() {
            return str;
        }

        public Request setStr(String str) {
            this.str = str;
            return this;
        }
    }

    public static class Response {
        private String str;

        public String getStr() {
            return str;
        }

        public Response setStr(String str) {
            this.str = str;
            return this;
        }
    }
    
    public static void main(String[] args) {
        var request = new Request().setStr("我天天996 <script>alert()</script>");
        var response = new Response().setStr("");

        var filterChain = new FilterChain();
        filterChain.addAll(List.of(new DataFilter(), new MgFilter()));

        filterChain.doFilter(request, response,filterChain);
        System.out.println(request.str);
        System.out.println(response.str);
    }
}