设计模式-责任链模式

责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 处理链上的每个处理者均可对请求进行处理(修改request,response,return), 或将其传递给链上的下个处理者。

servlet模块即是使用了责任链模式来对请求进行过滤。

我们模仿servlet的过滤链处理来举例说明:

第一步

首先定义过滤器处理接口:Filter

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

其中FilterChain是过滤链接口,过滤链组合所有的过滤器并进行顺序过滤处理

1
2
3
public interface FilterChain {
void doFilter(Request request, Response response);
}

其中Request接口代表要处理的请求:

1
2
3
4
public interface Request {
String getParameter(String var1);
void setParameter(String key, String value);
}

其中Response接口代表要回复的响应:

1
2
3
4
public interface Response {
void writeContent(String var1);
String getContent();
}

然后定义一个FilterConfig接口,FilterConfig和Filter是1对1的关系,用于对Filter参数进行封装

1
2
3
4
5
6
7
8
/**
* @description: FilterConfig 管理具体的Filter,为不同的Filter配置不一样的参数
* @create: 2020-03-02 09:51
*/
public interface FilterConfig {
String getFilterParameter(String var1);
Filter getFilter();
}

最后定义一个Servlet接口,用于过滤处理完成之后的业务处理

1
2
3
4
5
6
7
/**
* @description: 过滤链处理完成后交给Servlet进行后续处理
* @create: 2020-03-03 09:39
*/
public interface Servlet {
void service(Request request, Response response);
}

第二步

我们实现两个具体Filter:EnCodingFilter用于对请求编码进行验证,ContentTypeFilter用于对请求内容类型进行验证:

EnCodingFilter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class EnCodingFilter implements Filter {
private FilterConfig filterConfig;

// 通过FilterConfig获取到过滤器参数
public final void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}

@Override
public void doFilter(Request request, Response response, FilterChain filterChain) {
// 1. do something
if (!this.filterConfig.getFilterParameter ( "encode" ).equalsIgnoreCase ( request.getParameter ( "encode" ) )) {
System.out.println ( "ENCODING FILTER CHECKING FAIL" );
return;
}
System.out.println ( "encode: " + request.getParameter ( "encode" ) + " OK!" );
response.writeContent ( "ENCODE OK;" );
// 2. 向下传递
filterChain.doFilter ( request, response );
}
}

ContentTypeFilter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class ContentTypeFilter implements Filter {
private FilterConfig filterConfig;

// 通过FilterConfig获取到过滤器参数
public final void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}

@Override
public void doFilter(Request request, Response response, FilterChain filterChain) {
// 1. do something
if (!this.filterConfig.getFilterParameter ( "content-type" ).equalsIgnoreCase ( request.getParameter ( "content-type" ) )) {
System.out.println ( "CONTENT-TYPE FILTER CHECKING FAIL" );
return;
}
System.out.println ( "content-type: " + request.getParameter ( "content-type" ) + " OK!" );
response.writeContent ( "CONTENT-TYPE OK;" );
// 2. 向下传递
filterChain.doFilter ( request, response );
}
}

第三步

实现一个具体的FilterConfig,一个具体的Filter对应一个FilterConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 一个具体的Filter对应一个AppFilterConfig
*/
public class AppFilterConfig implements FilterConfig {
private Filter filter;
private final Map<String, String> parameters = new HashMap ();

public AppFilterConfig(Filter filter, Map<String, String> parameters) {
this.filter = filter;
this.parameters.putAll ( parameters );
}

@Override
public String getFilterParameter(String var1) {
return parameters.get ( var1 );
}

@Override
public Filter getFilter() {
return filter;
}
}

第四步

实现一个FilterChain,保存所有配置的Filter,并进行过滤链的调用处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* FilterChain 有序保存所有的Filter,按顺序调用所有的Filter进行过滤处理
*/
public class AppFilterChain implements FilterChain {
private AppFilterConfig[] filters = new AppFilterConfig[0];
private int pos = 0;
private int n = 0;
private Servlet servlet = null;

void setServlet(Servlet servlet) {
this.servlet = servlet;
}

void addFilter(AppFilterConfig filterConfig) {
AppFilterConfig[] newFilters = this.filters;
int var3 = newFilters.length;

// 1.判断filter里是否已经存在
for(int var4 = 0; var4 < var3; ++var4) {
AppFilterConfig filter = newFilters[var4];
if (filter == filterConfig) {
return;
}
}
// 2.判断filter数组是否需要扩容
if (this.n == this.filters.length) {
newFilters = new AppFilterConfig[this.n + 10];
System.arraycopy(this.filters, 0, newFilters, 0, this.n);
this.filters = newFilters;
}
// 3.添加filter
this.filters[this.n++] = filterConfig;
}

@Override
public void doFilter(Request request, Response response) {
if (this.pos < this.n) {
AppFilterConfig filterConfig = this.filters[this.pos++];
Filter filter = filterConfig.getFilter ();
filter.doFilter(request, response, this);
} else {
// filter chain 处理完毕,交给业务处理
this.servlet.service ( request, response );
}
}
}

第五步

实现一个具体的业务Servlet:AppServlet

1
2
3
4
5
6
public class AppServlet implements Servlet {
@Override
public void service(Request request, Response response) {
System.out.println ( "通过FILTER CHAIN处理,进入业务服处理: Response: " + response.getContent () );
}
}

第六步

提供一个工具类来组装FilterChain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 组装FilterChain
*/
public final class AppFilterFactory {
public static AppFilterChain createFilterChain(Request request, Servlet servlet) {
// 1. 实例化FilterChain
AppFilterChain appFilterChain = new AppFilterChain ();
appFilterChain.setServlet ( servlet );
// 2. 添加具体的Filter,此处添加的顺序即表示Filter被处理的顺序
EnCodingFilter enCodingFilter = new EnCodingFilter ();
Map<String, String> enCodingParams = new HashMap<> ( );
enCodingParams.put ( "encode", "utf-8" );
AppFilterConfig appFilterConfig = new AppFilterConfig ( enCodingFilter, enCodingParams);
enCodingFilter.init ( appFilterConfig );
appFilterChain.addFilter ( appFilterConfig );

ContentTypeFilter contentTypeFilter = new ContentTypeFilter ();
Map<String, String> contentTypeParams = new HashMap<> ( );
contentTypeParams.put ( "content-type", "application/json" );
appFilterConfig = new AppFilterConfig ( contentTypeFilter, contentTypeParams );
contentTypeFilter.init ( appFilterConfig );
appFilterChain.addFilter ( appFilterConfig );

return appFilterChain;
}
}

第七步

实现一个具体的请求类AppRequest和响应类AppResponse:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class AppRequest implements Request {
private Map<String, String> parameters = new HashMap<> ( );

@Override
public void setParameter(String key, String value) {
this.parameters.put ( key, value );
}

@Override
public String getParameter(String var1) {
return this.parameters.get ( var1 );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AppResponse implements Response {
private String content;
// 此处写到String,打印
// 实际的HttpServletResponse通过PrintWriter将返回内容写到Socket
private StringWriter writer = new StringWriter ( );

@Override
public void writeContent(String var1) {
this.writer.append ( var1 );
this.content = this.writer.toString ();
}

@Override
public String getContent() {
return this.content;
}
}

整个责任链模式实现完成,最后来使用下

1
2
3
4
5
6
7
8
9
10
11
public class ChainUsage {
public static void main(String[] args) {
Request request = new AppRequest ();
request.setParameter ( "encode", "utf-8" );
request.setParameter ( "content-type", "application/json" );
Servlet servlet = new AppServlet ();
Response response = new AppResponse ();
FilterChain filterChain = AppFilterFactory.createFilterChain ( request, servlet );
filterChain.doFilter ( request, response );
}
}

提供和过滤器配置的参数一样,则过滤器处理成功,交给业务处理,输出如下:

1
2
3
encode: utf-8 OK!
content-type: application/json OK!
通过FILTER CHAIN处理,进入业务服处理: Response: ENCODE OK;CONTENT-TYPE OK;

修改request.setParameter ( “encode”, “utf-16” );测试,编码过滤器处理不通过直接返回,输出如下:

1
ENCODING FILTER CHECKING FAIL

修改request.setParameter ( “content-type”, “multipart/form-data” );测试,内容类型过滤器处理不通过直接返回,输出如下:

1
2
encode: utf-8 OK!
CONTENT-TYPE FILTER CHECKING FAIL
-------------本文结束感谢您的阅读-------------
Good for you!