责任链模式优化参数多重校验
责任链模式优化参数多重校验的好处在于可以将复杂的多个校验逻辑分离成独立的处理单元(handler),通过灵活的组合和链式调用,使得校验逻辑更加清晰、可维护和可扩展。当有新的校验需求时,只需添加新的 handler 而无需修改已有的校验代 码,提高了开发效率,同时也增强了代码的可读性和可测试性。
简单责任链
Handler模版
public abstract class Handler<T> {
protected Handler next;
private void next(Handler next) {
this.next = next;
}
public abstract void doHandler(User user);
public static class Builder<T> {
private Handler<T> head;
private Handler<T> tail;
public Builder<T> addHandler(Handler handler) {
if (this.head == null) {
this.head = this.tail = handler;
return this;
}
this.tail.next(handler);
this.tail = handler;
return this;
}
public Handler<T> build() {
return this.head;
}
}
}
AuthHandler
public class AuthHandler extends Handler {
@Override
public void doHandler(User user) {
if (!"管理员".equals(user.getRoleName())) {
System.out.println("您不是管理员,没有操作权限");
return;
}
if (null != next) {
next.doHandler(user);
}
}
}
BusinessLogicHandler
public class BusinessLogicHandler extends Handler {
@Override
public void doHandler(User user) {
System.out.println("业务逻辑校验!");
if (null != next) {
next.doHandler(user);
}
}
}
LoginHandler
public class LoginHandler extends Handler {
@Override
public void doHandler(User user) {
System.out.println("用户校验!");
if (null != next) {
next.doHandler(user);
}
}
}
ValidateHandler
public class ValidateHandler extends Handler {
@Override
public void doHandler(User user) {
if (StringUtils.isEmpty(user.getUserName()) ||
StringUtils.isEmpty(user.getPassWord())) {
System.out.println("用户名和密码不能为空");
return;
}
if (null != next) {
next.doHandler(user);
}
}
}
测试
责任链+工厂+枚举
需求:对接口进行api接口限流 ,然后黑名单拦截,然后用户会话拦截
原来的做法
定义抽象类:
public abstract class AbstractGatewayHandler {
/**
* 下一关用当前抽象类来接收
*/
protected AbstractGatewayHandler next;
public void setNext(AbstractGatewayHandler next) {
this.next = next;
}
public abstract void service();
}
实现方法:
public class ApiLimitGatewayHandler extends AbstractGatewayHandler {
@Override
public void service() {
System.out.println("api接口限流");
if (this.next != null) {
this.next.service();
}
}
}
public class BlacklistGatewayHandler extends AbstractGatewayHandler {
@Override
public void service() {
System.out.println("黑名单拦截");
if (this.next != null) {
this.next.service();
}
}
}
public class SessionGatewayHandler extends AbstractGatewayHandler {
@Override
public void service() {
System.out.println("用户会话拦截");
if (this.next != null) {
this.next.service();
}
}
}
使用:
public class GetewayClientBefore {
public static void main(String[] args) {
//api接口限流 黑名单拦截 用户会话拦截
AbstractGatewayHandler firstPassHandler = new ApiLimitGatewayHandler();
AbstractGatewayHandler secondPassHandler = new BlacklistGatewayHandler();
AbstractGatewayHandler thirdPassHandler = new SessionGatewayHandler();
firstPassHandler.setNext(secondPassHandler);
secondPassHandler.setNext(thirdPassHandler);
firstPassHandler.service();
}
}
优化
定义枚举:
public enum GatewayEnum {
// handlerId, 拦截者名称,全限定类名,preHandlerId,nextHandlerId
API_HANDLER(new GatewayEntity(1, "api接口限流", "com.yunfei.ApiLimitGatewayHandler", null, 2)),
BLACKLIST_HANDLER(new GatewayEntity(2, "黑名单拦截", "com.yunfei.BlacklistGatewayHandler", 1, 3)),
SESSION_HANDLER(new GatewayEntity(3, "用户会话拦截", "com.yunfei.SessionGatewayHandler", 2, null)),
;
GatewayEntity gatewayEntity;
public GatewayEntity getGatewayEntity() {
return gatewayEntity;
}
GatewayEnum(GatewayEntity gatewayEntity) {
this.gatewayEntity = gatewayEntity;
}
}
@Data
@AllArgsConstructor
public class GatewayEntity {
private Integer handlerId;
private String name;
private String conference;
private Integer preHandlerId;
private Integer nextHandlerId;
}
实现类:
public class GatewayImpl implements GatewayDao {
/**
* 初始化,将枚举中配置的handler初始化到map中,方便获取
*/
private static Map<Integer, GatewayEntity> gatewayEntityMap = new HashMap<>();
static {
GatewayEnum[] values = GatewayEnum.values();
for (GatewayEnum value : values) {
GatewayEntity gatewayEntity = value.getGatewayEntity();
gatewayEntityMap.put(gatewayEntity.getHandlerId(), gatewayEntity);
}
}
@Override
public GatewayEntity getGatewayEntity(Integer handlerId) {
return gatewayEntityMap.get(handlerId);
}
@Override
public GatewayEntity getFirstGatewayEntity() {
for (Map.Entry<Integer, GatewayEntity> entry : gatewayEntityMap.entrySet()) {
GatewayEntity value = entry.getValue();
// 没有上一个handler的就是第一个
if (value.getPreHandlerId() == null) {
return value;
}
}
return null;
}
}
public interface GatewayDao {
/**
* 根据 handlerId 获取配置项
*
* @param handlerId
* @return
*/
GatewayEntity getGatewayEntity(Integer handlerId);
/**
* 获取第一个处理者
*
* @return
*/
GatewayEntity getFirstGatewayEntity();
}
工厂:
public class GatewayHandlerEnumFactory {
private static GatewayDao gatewayDao = new GatewayImpl();
// 提供静态方法,获取第一个handler
public static AbstractGatewayHandler getFirstGatewayHandler() {
GatewayEntity firstGatewayEntity = gatewayDao.getFirstGatewayEntity();
AbstractGatewayHandler firstAbstractGatewayHandler = newGatewayHandler(firstGatewayEntity);
if (firstAbstractGatewayHandler == null) {
return null;
}
GatewayEntity tempGatewayEntity = firstGatewayEntity;
Integer nextHandlerId = null;
AbstractGatewayHandler tempAbstractGatewayHandler = firstAbstractGatewayHandler;
// 迭代遍历所有handler,以及将它们链接起来
while ((nextHandlerId = tempGatewayEntity.getNextHandlerId()) != null) {
GatewayEntity gatewayEntity = gatewayDao.getGatewayEntity(nextHandlerId);
AbstractGatewayHandler abstractGatewayHandler = newGatewayHandler(gatewayEntity);
tempAbstractGatewayHandler.setNext(abstractGatewayHandler);
tempAbstractGatewayHandler = abstractGatewayHandler;
tempGatewayEntity = gatewayEntity;
}
// 返回第一个handler
return firstAbstractGatewayHandler;
}
/**
* 反射实体化具体的处理者
*
* @param firstGatewayEntity
* @return
*/
private static AbstractGatewayHandler newGatewayHandler(GatewayEntity firstGatewayEntity) {
// 获取全限定类名
String className = firstGatewayEntity.getConference();
try {
// 根据全限定类名,加载并初始化该类,即会初始化该类的静态段
Class<?> clazz = Class.forName(className);
return (AbstractGatewayHandler) clazz.newInstance();
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
return null;
}
}
测试:
/**
* 用责任链模式 + 工厂模式 + 枚举,动态配置请求链并调用。
*/
public class GatewayClient {
public static void main(String[] args) {
AbstractGatewayHandler firstAbstractGatewayHandler = GatewayHandlerEnumFactory.getFirstGatewayHandler();
firstAbstractGatewayHandler.service();
}
}
结果: