责任链设计模式
定义:
为请求定义一条处理链,请求者不用关心链中的执行过程与方法,当链中的一个请求成功了,会继续向下一个链执行,直到调用链结束。
举个栗子
以我们常用的鉴权为例:请求token进入,首先判断token是否合法,再判断token是否过期,再判断用户是否有权限访问该接口。
废话不多说,上代码:
- 首先定义一个token对象,稍后会验证该token是否合法
/**
* @date 2022/10/24 17:05
*/
public class Token {
/**
* 过期时间
*/
private Date expirationTime;
/**
* 权限标识符
*/
private List<String> auths;
/**
* token数据
*/
private String data;
public Date getExpirationTime() {
return expirationTime;
}
public void setExpirationTime(Date expirationTime) {
this.expirationTime = expirationTime;
}
public List<String> getAuths() {
return auths;
}
public void setAuths(List<String> auths) {
this.auths = auths;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
- 抽象处理类
/**
* 抽象处理类
*
* @date 2022/10/24 16:49
*/
public abstract class Handler<T> {
protected Handler<?> nextHandler;
public final void next(Handler<?> nextHandler) {
this.nextHandler = nextHandler;
}
/**
* 处理函数
*/
public abstract void doHandler(Token token);
}
- 抽象处理类的具体实现类(token的合法性校验)
/**
* token合法性校验
*
* @date 2022/10/24 17:20
*/
public class LegalAuthHandler<T> extends Handler<T> {
/**
* 处理函数
*
* @param token
*/
@Override
public void doHandler(Token token) {
String data = token.getData();
if (data != null && !"".equals(data)) {
System.out.println("合法性校验通过");
this.nextHandler.doHandler(token);
} else {
System.out.println("合法性校不通过,认证失败");
return;
}
}
}
- 抽象处理类的具体实现类(时间的过期认证)
/**
* 时间认证
*
* @date 2022/10/24 17:20
*/
public class DateAuthHandler<T> extends Handler<T> {
/**
* 处理函数
*
* @param token
*/
@Override
public void doHandler(Token token) {
Date expirationTime = token.getExpirationTime();
if (Objects.isNull(expirationTime)) {
System.out.println("验证失败");
return;
}
boolean result = expirationTime.after(new Date());
if (result) {
System.out.println("时间认证通过");
this.nextHandler.doHandler(token);
} else {
System.out.println("时间不通过,认证失败");
return;
}
}
}
- 抽象处理类的具体实现类(权限认证)
/**
* 权限认证
*
* @date 2022/10/24 17:20
*/
public class SecurityAuthHandler<T> extends Handler<T> {
/**
* 处理函数
*
* @param token
*/
@Override
public void doHandler(Token token) {
List<String> auths = token.getAuths();
if (Objects.isNull(auths)) {
System.out.println("权限认证不通过");
return;
}
if (auths.contains("system:user:list")) {
System.out.println("权限认证通过");
this.nextHandler.doHandler(token);
}
}
}
- 认证服务
/**
* @date 2022/10/24 19:09
*/
public class AuthService {
public void auth(Token token) {
LegalAuthHandler<?> legalAuthHandler = new LegalAuthHandler<>();
DateAuthHandler<?> dateAuthHandler = new DateAuthHandler<>();
SecurityAuthHandler<?> securityAuthHandler = new SecurityAuthHandler<>();
legalAuthHandler.next(dateAuthHandler);
dateAuthHandler.next(securityAuthHandler);
legalAuthHandler.doHandler(token);
}
}
- 测试
/**
* @date 2022/10/24 19:07
*/
public class Test {
public static void main(String[] args) {
Token token = new Token();
token.setExpirationTime(new Date(System.currentTimeMillis() + 1000));
token.setData("aa.bb.cc");
AuthService authService = new AuthService();
authService.auth(token);
}
}
结果:
合法性校验通过
时间认证通过
权限认证不通过
到此,恭喜你学会了责任链模式,后面的可以不看了,也可以拓展下。。。。。
接下来-----------------整合构建者模式,不然的话,我们在AuthService 写链式太麻烦了不是
- 抽象处理类的具体实现类(结束处理器)
/**
* 结束处理器
*
* @date 2022/10/25 9:25
*/
public class EndHandler<T> extends Handler<T> {
@Override
public void doHandler(Token token) {
System.out.println("结束,通过");
}
}
- 改造一下抽象处理类Handler
/**
* 抽象处理类
*
* @date 2022/10/24 16:49
*/
public abstract class Handler<T> {
protected Handler<?> nextHandler;
public final void next(Handler<?> nextHandler) {
this.nextHandler = nextHandler;
}
/**
* 处理函数
*/
public abstract void doHandler(Token token);
public static class Builder<T> {
private Handler<T> head;
private Handler<T> current;
public Builder<T> addHandler(Handler<T> handler) {
//判断是否是第一个(如果只有一个,next就是空,防止后续判断空,所以给一个结束处理器)
if (this.head == null) {
this.head = this.current = handler;
this.current.next(new EndHandler<>());
return this;
}
this.current.next(handler);
this.current = handler;
return this;
}
public Handler<T> build() {
return this.head;
}
}
}
- 优化简化下AuthService类
/**
* @date 2022/10/24 19:09
*/
public class AuthService {
public void auth(Token token) {
Handler.Builder<Handler<?>> builder = new Handler.Builder<>();
builder
.addHandler(new LegalAuthHandler<>())
.addHandler(new DateAuthHandler<>())
.addHandler(new SecurityAuthHandler<>());
builder.build().doHandler(token);
}
}
一个超级简单的责任链模式完成,搞定