责任链模式的学习

责任链模式的学习

定义

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

责任链模式UML图

在这里插入图片描述

Filter:过滤器的抽象接口

TitleFilter:标题过滤器,实现了Filter接口

ArticleAbstractFilter:摘要过滤器,实现了Filter接口

ContentFilter:内容过滤器,实现了Filter接口

FilterChain:过滤器链,主要是处理过滤器的循环调用

DefaultFilterChainFilterChain的默认实现

Article:文章对象,相当于tomcat过滤器中的ServletRequest的作用

/**
 * @author : zwy
 * create at:  2021/6/1  下午10:26
 * @description: 过滤器
 */
public interface Filter {

    void doFilter(Article article,FilterChain filterChain);

}

/**
 * @author : zwy
 * create at:  2021/6/2  下午10:57
 * @description: 标题过滤器
 */
public class TitleFilter implements Filter{
    @Override
    public void doFilter(Article article, FilterChain filterChain) {
        System.out.println("过滤标题");
        filterChain.doFilter(article,filterChain);
    }
}


/**
 * @author : zwy
 * create at:  2021/6/2  下午10:58
 * @description: 摘要过滤器
 */
public class ArticleAbstractFilter implements Filter{

    @Override
    public void doFilter(Article article, FilterChain filterChain) {
        System.out.println("过滤摘要");
        filterChain.doFilter(article,filterChain);
    }
}

/**
 * @author : zwy
 * create at:  2021/6/2  下午10:59
 * @description: 文章内容过滤器
 */
public class ContentFilter implements Filter{

    @Override
    public void doFilter(Article article, FilterChain filterChain) {
        System.out.println("过滤文章内容");
        filterChain.doFilter(article,filterChain);
    }
}

/**
 * @author : zwy
 * create at:  2021/6/2  下午10:43
 * @description: 过滤器链
 */
public interface FilterChain {
    
    void doFilter(Article article,FilterChain filterChain);

}

/**
 * @author : zwy
 * create at:  2021/6/2  下午10:49
 * @description: 实现类
 */
public class DefaultFilterChain implements FilterChain{

  	//所有的过滤器
    private List<Filter> filterList = new ArrayList<>();

  	//执行到哪个过滤器
    private int pos = 0;

    public DefaultFilterChain(List<Filter> filterList) {
        this.filterList = filterList;
    }

    @Override
    public void doFilter(Article article, FilterChain filterChain) {
				//不是最后一个继续向下过滤
        if(pos != filterList.size()){
            filterList.get(pos++).doFilter(article,filterChain);
        }
    }
}


/**
 * @author : zwy
 * create at:  2021/6/1  下午10:32
 * @description: 文章
 */
public class Article {

    private String title;
    private String ArticleAbstract;
    private String content;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getArticleAbstract() {
        return ArticleAbstract;
    }

    public void setArticleAbstract(String articleAbstract) {
        ArticleAbstract = articleAbstract;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}


/**
 * @author : zwy
 * create at:  2021/6/2  下午11:00
 * @description: 客户端
 */
public class Client {

    public static void main(String[] args) {
				//创建过滤器
        Filter titleFilter = new TitleFilter();
        Filter articleAbstractFilter = new ArticleAbstractFilter();
        Filter contentFilter = new ContentFilter();
				//添加过滤器
        List<Filter> filterList = new ArrayList<>();
        filterList.add(titleFilter);
        filterList.add(articleAbstractFilter);
        filterList.add(contentFilter);
				//创建过滤器链,并将过滤器加入
        FilterChain filterChain = new DefaultFilterChain(filterList);
				//进行过滤
        filterChain.doFilter(new Article(),filterChain);

    }
}

运行结果

过滤标题
过滤摘要
过滤文章内容

过滤器的实现

在这里插入图片描述

下面简单解析一下过滤器的责任链模式的实现

public interface Filter {

    public default void init(FilterConfig filterConfig) throws ServletException {}

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException;

    public default void destroy() {}
}

看Filter接口的定义,init和destroy可以暂时忽略,最主要的就是doFilter,通过结合FilterChain及其实现类看一下

public interface FilterChain {

    public void doFilter(ServletRequest request, ServletResponse response)
            throws IOException, ServletException;
}



public final class ApplicationFilterChain implements FilterChain {

    //去除了一些代码,方便理解
 
    //记录所有的过滤器
    private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
    //过滤器执行到的位置
    private int pos = 0;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response)
        throws IOException, ServletException {

        if( Globals.IS_SECURITY_ENABLED ) {
            final ServletRequest req = request;
            final ServletResponse res = response;
            try {
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedExceptionAction<Void>() {
                        @Override
                        public Void run()
                            throws ServletException, IOException {
                            //执行下一个过滤器
                            internalDoFilter(req,res);
                            return null;
                        }
                    }
                );
            } catch( PrivilegedActionException pe) {
                Exception e = pe.getException();
                if (e instanceof ServletException)
                    throw (ServletException) e;
                else if (e instanceof IOException)
                    throw (IOException) e;
                else if (e instanceof RuntimeException)
                    throw (RuntimeException) e;
                else
                    throw new ServletException(e.getMessage(), e);
            }
        } else {
            //执行下一个过滤器
            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++];
            try {
                Filter filter = filterConfig.getFilter();

                if (request.isAsyncSupported() && "false".equalsIgnoreCase(
                        filterConfig.getFilterDef().getAsyncSupported())) {
                    request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
                }
                if( Globals.IS_SECURITY_ENABLED ) {
                    final ServletRequest req = request;
                    final ServletResponse res = response;
                    Principal principal =
                        ((HttpServletRequest) req).getUserPrincipal();

                    Object[] args = new Object[]{req, res, this};
                    SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
                } else {
                    //执行过滤器方法
                    filter.doFilter(request, response, this);
                }
            } catch (IOException | ServletException | RuntimeException e) {
                throw e;
            } catch (Throwable e) {
                e = ExceptionUtils.unwrapInvocationTargetException(e);
                ExceptionUtils.handleThrowable(e);
                throw new ServletException(sm.getString("filterChain.filter"), e);
            }
            return;
        }

        // We fell off the end of the chain -- call the servlet instance
        //执行完所有的过滤器,执行业务方法
        try {
            if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                lastServicedRequest.set(request);
                lastServicedResponse.set(response);
            }

            if (request.isAsyncSupported() && !servletSupportsAsync) {
                request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
                        Boolean.FALSE);
            }
            // Use potentially wrapped request from this point
            if ((request instanceof HttpServletRequest) &&
                    (response instanceof HttpServletResponse) &&
                    Globals.IS_SECURITY_ENABLED ) {
                final ServletRequest req = request;
                final ServletResponse res = response;
                Principal principal =
                    ((HttpServletRequest) req).getUserPrincipal();
                Object[] args = new Object[]{req, res};
                SecurityUtil.doAsPrivilege("service",
                                           servlet,
                                           classTypeUsedInService,
                                           args,
                                           principal);
            } else {
                servlet.service(request, response);
            }
        } catch (IOException | ServletException | RuntimeException e) {
            throw e;
        } catch (Throwable e) {
            e = ExceptionUtils.unwrapInvocationTargetException(e);
            ExceptionUtils.handleThrowable(e);
            throw new ServletException(sm.getString("filterChain.servlet"), e);
        } finally {
            if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                lastServicedRequest.set(null);
                lastServicedResponse.set(null);
            }
        }
    }

    void addFilter(ApplicationFilterConfig filterConfig) {

        // Prevent the same filter being added multiple times
        for(ApplicationFilterConfig filter:filters)
            if(filter==filterConfig)
                return;

        if (n == filters.length) {
            ApplicationFilterConfig[] newFilters =
                new ApplicationFilterConfig[n + INCREMENT];
            System.arraycopy(filters, 0, newFilters, 0, n);
            filters = newFilters;
        }
        filters[n++] = filterConfig;

    }

}

看上面ApplicationFilterChain拥有所有的过滤器,然后在doFilter中进行循环执行所有的过滤器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值