Java设计模式-责任链模式

设计模式-责任链模式

通过模式数据库来配置责任链顺序,运用案例,网关需要过滤api限制;黑名单;参数过滤;session过滤等相关功能

定义抽象handler

package com.example.spring.boot.test.chainresponsibility.handle;

public abstract class GatewayHandle {

    public GatewayHandle next;

    public void setNext(GatewayHandle next){
        this.next = next;
    }

    public abstract void service();
}

该抽象类里面包含一个next节点,可以理解为单向链表数据结构。

各个任务组件子类

ApiLimitGatewayHandle

package com.example.spring.boot.test.chainresponsibility.handle.impl;

import com.example.spring.boot.test.chainresponsibility.handle.GatewayHandle;

public class ApiLimitGatewayHandle extends GatewayHandle {
    @Override
    public void service() {
        System.out.println("api limit......");
        if(this.next != null){
            this.next.service();
        }
    }
}

BlacklistGetwayHandler

package com.example.spring.boot.test.chainresponsibility.handle.impl;

import com.example.spring.boot.test.chainresponsibility.handle.GatewayHandle;

public class BlacklistGetwayHandler extends GatewayHandle {
    @Override
    public void service() {
        System.out.println("black list......");
        if(this.next != null){
            this.next.service();
        }
    }
}

ParamGetwayHandler

package com.example.spring.boot.test.chainresponsibility.handle.impl;

import com.example.spring.boot.test.chainresponsibility.handle.GatewayHandle;

public class ParamGetwayHandler extends GatewayHandle {
    @Override
    public void service() {
        System.out.println("param......");
        if(this.next != null){
            this.next.service();
        }
    }
}

SessionGetwayHandler

package com.example.spring.boot.test.chainresponsibility.handle.impl;

import com.example.spring.boot.test.chainresponsibility.handle.GatewayHandle;

public class SessionGetwayHandler extends GatewayHandle {
    @Override
    public void service() {
        System.out.println("session......");
        if(this.next != null){
            this.next.service();
        }
    }
}

通过枚举类来模拟数据库存储配置

创建网关实体类GatewayEntity

package com.example.spring.boot.test.chainresponsibility.entity;

import lombok.Data;

@Data
public class GatewayEntity {

    /**
     * 实体ID
     */
    private Integer id;

    /**
     * 描述
     */
    private String desc;

    /**
     * 组件类全限定名
     */
    private String handleClassName;

    /**
     * 上一个组件的ID
     */
    private Integer preId;

    /**
     * 下一个组件的ID
     */
    private Integer nextId;


    public GatewayEntity(Integer id, String desc, String handleClassName, Integer preId, Integer nextId) {
        this.id = id;
        this.desc = desc;
        this.handleClassName = handleClassName;
        this.preId = preId;
        this.nextId = nextId;
    }
}

创建枚举类

package com.example.spring.boot.test.chainresponsibility.enums;

import com.example.spring.boot.test.chainresponsibility.entity.GatewayEntity;

public enum GatewayEnum {
    API_HANDLER(new GatewayEntity(1,"api接口限流","com.example.spring.boot.test.chainresponsibility.handle.impl.ApiLimitGatewayHandle",null,2)),
    BLACKLIST_HANDLER(new GatewayEntity(2,"黑名单拦截","com.example.spring.boot.test.chainresponsibility.handle.impl.BlacklistGetwayHandler",1,3)),
    SESSION_HANDLER(new GatewayEntity(3,"用户会话拦截","com.example.spring.boot.test.chainresponsibility.handle.impl.SessionGetwayHandler",2,4)),

    /**
     * 这是最后一个处理者,因此没有下一个 nexthandlerId 也就是它的 nexthandlerId = null
     */
    PARAM_HANDLER(new GatewayEntity(4,"参数过滤拦截","com.example.spring.boot.test.chainresponsibility.handle.impl.ParamGetwayHandler",3,null)),

    ;

    private GatewayEntity gatewayEntity;

    GatewayEnum(GatewayEntity entity){
        this.gatewayEntity = entity;
    }

    public GatewayEntity getGatewayEntity() {
        return gatewayEntity;
    }
}

创建Dao和DaoImpl

package com.example.spring.boot.test.chainresponsibility.dao;

import com.example.spring.boot.test.chainresponsibility.entity.GatewayEntity;

public interface GatewayDao {

    /**
     * 通过ID获取网关实体
     * @param id 
     * @return
     */
    GatewayEntity getEntityById(Integer id);

    /**
     * 获取第一个网关实体类
     * @return 
     */
    GatewayEntity getFirstEntity();

}

实现类

package com.example.spring.boot.test.chainresponsibility.dao.impl;

import com.example.spring.boot.test.chainresponsibility.dao.GatewayDao;
import com.example.spring.boot.test.chainresponsibility.entity.GatewayEntity;
import com.example.spring.boot.test.chainresponsibility.enums.GatewayEnum;

import java.util.HashMap;
import java.util.Map;

public class GatewayDaoImpl implements GatewayDao {

    private static Map<Integer, GatewayEntity> map = new HashMap<>();
    static{
        for(GatewayEnum gatewayEnum: GatewayEnum.values()){
            map.put(gatewayEnum.getGatewayEntity().getId(), gatewayEnum.getGatewayEntity());
        }
    }
    @Override
    public GatewayEntity getEntityById(Integer id) {
        if(id == null){
            return null;
        }
        return map.get(id);
    }

    @Override
    public GatewayEntity getFirstEntity() {
        for(GatewayEntity entity: map.values()){
            if(entity.getPreId() == null){
                return entity;
            }
        }
        return null;
    }
}

创建Facatory构建责任链(将组建编排起来)采用了工厂模式

package com.example.spring.boot.test.chainresponsibility.factory;

import com.example.spring.boot.test.chainresponsibility.dao.GatewayDao;
import com.example.spring.boot.test.chainresponsibility.dao.impl.GatewayDaoImpl;
import com.example.spring.boot.test.chainresponsibility.entity.GatewayEntity;
import com.example.spring.boot.test.chainresponsibility.handle.GatewayHandle;

public class GatewayHandlerEnumFactory {

    private static GatewayDao gatewayDao = new GatewayDaoImpl();

    public static GatewayHandle buildGatewayHandler(){
        // 1. 获取第一处理者 那么那个是第一个处理者呢 preId == null 的就是第一个handler
        GatewayEntity firstEntity = gatewayDao.getFirstEntity();
        GatewayHandle firstGatewayHandler = newGatewayHandler(firstEntity);

        if(firstGatewayHandler == null){
            return null;
        }
        setNextGatewayHandler(firstEntity, firstGatewayHandler);

        return firstGatewayHandler;
    }

    private static void setNextGatewayHandler(GatewayEntity gatewayEntity,GatewayHandle gatewayHandle){
        if(gatewayHandle != null && gatewayEntity != null){
            Integer nextId = gatewayEntity.getNextId();
            GatewayEntity nextEntity = gatewayDao.getEntityById(nextId);
            GatewayHandle newGatewayHandler = newGatewayHandler(nextEntity);
            gatewayHandle.setNext(newGatewayHandler);
            //递归 设置
            setNextGatewayHandler(nextEntity, newGatewayHandler);
        }
    }

    /**
     * 反射实体化具体的处理者
     * @param gatewayEntity
     * @return
     */
    private static GatewayHandle newGatewayHandler(GatewayEntity gatewayEntity){
        if(gatewayEntity == null){
            return null;
        }
        String handlerClassName = gatewayEntity.getHandleClassName();
        try {
            Class<?> clazz = Class.forName(handlerClassName);
            return (GatewayHandle) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }
}

测试

package com.example.spring.boot.test.chainresponsibility;

import com.example.spring.boot.test.chainresponsibility.factory.GatewayHandlerEnumFactory;
import com.example.spring.boot.test.chainresponsibility.handle.GatewayHandle;

public class GatewayClient {

    public static void main(String[] args) {
        GatewayHandle gatewayHandle = GatewayHandlerEnumFactory.buildGatewayHandler();
        gatewayHandle.service();
    }
}

结果

api limit......
black list......
session......
param......
0%