02.责任链模式

1.什么是责任链设计模式

客户端发起一个请求、链上面所有的对象都有机会处理该请求

2.责任链角色

抽象处理者角色(Handler)

具体处理者角色(ConcreateHandler)

3.应用场景

filter过滤器中doFiler方法

4.通过工厂实现责任链模式

链接:https://pan.baidu.com/s/1QgyEWDCotAteOVxh2-6ErQ 
提取码:jtim

 

1)pom依赖

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.11.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
    </dependencies>

2)抽象处理者handler

public abstract class GatewayHandler {

    private GatewayHandler nextGatewayHandler;

    public void setNextGatewayHandler(GatewayHandler nextGatewayHandler) {
        this.nextGatewayHandler = nextGatewayHandler;
    }

    /**
     * 实现的handler 处理方案 强制必须实现
     */
    public abstract void service();

    /**
     * 执行下一个handler
     */
    public void nextService() {
        if (nextGatewayHandler != null) {
            nextGatewayHandler.service();// 指向下一关黑名单
        }
    }
}

3)具体处理者ConcreateHandler

import com.demo.handler.GatewayHandler;
import org.springframework.stereotype.Component;

@Component
public class CurrentLimitHandler extends GatewayHandler {

    public void service() {
        System.out.println("第一关 API接口限流操作.....");
        // 指向下一关
        nextService();
    }
}
import com.demo.handler.GatewayHandler;
import org.springframework.stereotype.Component;

@Component
public class BlacklistHandler extends GatewayHandler {

    public void service() {
        System.out.println("第二关 黑名单拦截.......");
        nextService();
    }
}
import com.demo.handler.GatewayHandler;
import org.springframework.stereotype.Component;

@Component
public class ConversationHandler extends GatewayHandler {

    public void service() {
        System.out.println("第三关 用户的会话信息拦截.......");
    }
}

 4)工厂

import com.demo.handler.GatewayHandler;
import com.demo.handler.impl.BlacklistHandler;
import com.demo.handler.impl.ConversationHandler;
import com.demo.handler.impl.CurrentLimitHandler;

public class FactoryHandler {

    /**
     * 使用工厂模式封装Handler责任链
     */
    public static GatewayHandler getGatewayHandler() {
        //第一关
        CurrentLimitHandler currentLimitHandler = new CurrentLimitHandler();

        //第二关
        BlacklistHandler blacklistHandler = new BlacklistHandler();
        currentLimitHandler.setNextGatewayHandler(blacklistHandler);

        //第三关
        ConversationHandler conversationHandler = new ConversationHandler();
        blacklistHandler.setNextGatewayHandler(conversationHandler);
        return currentLimitHandler;
    }

}

 5)控制层

import com.demo.factory.FactoryHandler;
import com.demo.handler.GatewayHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HandlerController {

    @RequestMapping("/client")
    public String client() {
        GatewayHandler gatewayHandler = FactoryHandler.getGatewayHandler();
        gatewayHandler.service();
        return "success";
    }
}

6)启动类 

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AppHandler {

    public static void main(String[] args) {
        SpringApplication.run(AppHandler.class);
    }

}

 7)测试

http://localhost:8080/client

5.通过数据库实现责任链模式

链接:https://pan.baidu.com/s/1-lzzEC96Xxdc4pMYZptpVw 
提取码:7mfi 

 

1)数据库

/*
 Navicat Premium Data Transfer

 Source Server         : localhost
 Source Server Type    : MySQL
 Source Server Version : 50727
 Source Host           : localhost:3306
 Source Schema         : design_pattern

 Target Server Type    : MySQL
 Target Server Version : 50727
 File Encoding         : 65001

 Date: 21/02/2022 13:28:11
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for gateway_handler
-- ----------------------------
DROP TABLE IF EXISTS `gateway_handler`;
CREATE TABLE `gateway_handler`  (
  `handler_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'handler名称',
  `handler_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'handler主键id',
  `prev_handler_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '第一个handler',
  `next_handler_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '下一个handler',
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of gateway_handler
-- ----------------------------
INSERT INTO `gateway_handler` VALUES ('API接口限流操作', 'currentLimitHandler', NULL, 'blacklistHandler', 1);
INSERT INTO `gateway_handler` VALUES ('黑名单拦截', 'blacklistHandler', 'currentLimitHandler', 'conversationHandler', 2);
INSERT INTO `gateway_handler` VALUES ('用户的会话信息拦截', 'conversationHandler', 'blacklistHandler', NULL, 3);

SET FOREIGN_KEY_CHECKS = 1;

2)pom依赖

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.11.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <!-- sprinboot web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <!-- mysql 依赖 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>

3)yml

###服务启动端口号
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/design_pattern?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
####打印MyBatias日志
logging:
  level:
    ### 开发环境使用DEBUG 生产环境info或者error
    com.demo.mapper: DEBUG

4)entity

import lombok.Data;

import java.io.Serializable;

@Data
public class GatewayHandlerEntity implements Serializable, Cloneable {
    /**
     * 主键ID
     */
    private Integer id;
    /**
     * handler名称
     */
    private String handlerName;
    /**
     * handler主键id
     */
    private String handlerId;
    /**
     * 下一个handler
     */
    private String nextHandlerId;

}

5)mapper

import com.demo.entity.GatewayHandlerEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface GatewayHandlerMapper {

    /**
     * 获取第一个GatewayHandler
     *
     * @return
     */
    @Select("SELECT  handler_name AS handlerName,handler_id AS handlerid ,prev_handler_id AS prevhandlerid ,next_handler_id AS nexthandlerid  FROM gateway_handler WHERE  prev_handler_id is null;")
    GatewayHandlerEntity getFirstGatewayHandler();

    /**
     * 根据handler_id 获取
     * */
    @Select("SELECT  handler_name AS handlerName,handler_id AS handlerid ,prev_handler_id AS prevhandlerid ,next_handler_id AS nexthandlerid   FROM gateway_handler WHERE  handler_id=#{handlerId}")
    GatewayHandlerEntity getByHandler(String handlerId);

}

 6)抽象处理者handler

public abstract class GatewayHandler {

    private GatewayHandler nextGatewayHandler;

    public void setNextGatewayHandler(GatewayHandler nextGatewayHandler) {
        this.nextGatewayHandler = nextGatewayHandler;
    }

    /**
     * 实现的handler 处理方案 强制必须实现
     */
    public abstract void service();

    /**
     * 执行下一个handler
     */
    public void nextService() {
        if (nextGatewayHandler != null) {
            nextGatewayHandler.service();// 指向下一关黑名单
        }
    }
}

7)具体处理者ConcreateHandler

import com.demo.handler.GatewayHandler;
import org.springframework.stereotype.Component;

@Component
public class CurrentLimitHandler extends GatewayHandler {

    public void service() {
        System.out.println("第一关 API接口限流操作.....");
        // 指向下一关
        nextService();
    }
}
import com.demo.handler.GatewayHandler;
import org.springframework.stereotype.Component;

@Component
public class BlacklistHandler extends GatewayHandler {

    public void service() {
        System.out.println("第二关 黑名单拦截.......");
        nextService();
    }
}
import com.demo.handler.GatewayHandler;
import org.springframework.stereotype.Component;

@Component
public class ConversationHandler extends GatewayHandler {

    public void service() {
        System.out.println("第三关 用户的会话信息拦截.......");
    }
}

8)utils

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 获取applicationContext
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通过name获取 Bean
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    /**
     * 通过class获取Bean
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     * 通过name,以及Clazz返回指定的Bean
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

}

9)service

import com.demo.entity.GatewayHandlerEntity;
import com.demo.handler.GatewayHandler;
import com.demo.mapper.GatewayHandlerMapper;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import com.demo.utils.SpringUtils;

import javax.annotation.Resource;

@Service
public class GatewayHandlerService {

    @Resource
    private GatewayHandlerMapper gatewayHandlerMapper;

    private GatewayHandler firstGatewayHandler;

    /**
     * 获取数据库第一个handeler封装
     * @return
     */
    public GatewayHandler getFirstGatewayHandler() {
        if (firstGatewayHandler != null) {
            return firstGatewayHandler;
        }
        // 1.从数据库获取第一个handler
        GatewayHandlerEntity firstGatewayHandlerEntity = gatewayHandlerMapper.getFirstGatewayHandler();
        if (firstGatewayHandlerEntity == null) {
            return null;
        }
        String handlerId = firstGatewayHandlerEntity.getHandlerId();
        GatewayHandler firstGatewayHandler = SpringUtils.getBean(handlerId, GatewayHandler.class);

        // 2.获取下一个handler容器beanid
        String nextHandlerId = firstGatewayHandlerEntity.getNextHandlerId();

        // 3. 记录当前循环hanlder对象
        GatewayHandler tempGatewayHandler = firstGatewayHandler;
        while (StringUtils.isNotEmpty(nextHandlerId)) {
            // 4.从springboot容器获取下一个handerl对象
            GatewayHandler nextGatewayHandler = SpringUtils.getBean(nextHandlerId, GatewayHandler.class);
            tempGatewayHandler.setNextGatewayHandler(nextGatewayHandler);

            // 5.设置下一个nextHandlerId
            GatewayHandlerEntity nextGatewayHandlerEntity = gatewayHandlerMapper.getByHandler(nextHandlerId);
            if (nextGatewayHandlerEntity == null) {
                break;
            }
            nextHandlerId = nextGatewayHandlerEntity.getNextHandlerId();
            tempGatewayHandler = nextGatewayHandler;
        }
        this.firstGatewayHandler = firstGatewayHandler;
        return firstGatewayHandler;
    }
}

10)controller

import com.demo.handler.GatewayHandler;
import com.demo.service.GatewayHandlerService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class HandlerController {

    @Resource
    private GatewayHandlerService gatewayHandlerService;

    @RequestMapping("/client")
    public String client() {
        GatewayHandler firstGatewayHandler = gatewayHandlerService.getFirstGatewayHandler();
        firstGatewayHandler.service();
        return "success";
    }
}

11)测试

http://localhost:8080/client

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值