责任链模式的学习
定义
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
责任链模式UML图
Filter
:过滤器的抽象接口
TitleFilter
:标题过滤器,实现了Filter
接口
ArticleAbstractFilter
:摘要过滤器,实现了Filter
接口
ContentFilter
:内容过滤器,实现了Filter
接口
FilterChain
:过滤器链,主要是处理过滤器的循环调用
DefaultFilterChain
:FilterChain
的默认实现
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中进行循环执行所有的过滤器