如何给网关设计一款专属的权限控制「责任链设计模式」
}
}
@Component
@Slf4j
public class ConversationHandler extends GatewayHandler {
@Override
public void service() {
log.info("第三关 用户的会话信息拦截.......");
}
}
基于数据库实现
相关 SQL 语句
CREATE TABLE gateway_handler
(
ID
int(11) NOT NULL AUTO_INCREMENT COMMENT '主键 ID',
handler_name
varchar(32) DEFAULT NULL COMMENT 'handler 名称',
handler_id
varchar(32) DEFAULT NULL COMMENT 'handler 主键 id',
prev_handler_id
varchar(32) DEFAULT NULL,
next_handler_id
varchar(32) DEFAULT NULL COMMENT '下一个 handler',
PRIMARY KEY (ID
)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COMMENT='权限表';
-- Records of gateway_handler
INSERT INTO gateway_handler
VALUES ('16', 'Api 接口限流', 'currentLimitHandler', null, 'blacklistHandler');
INSERT INTO gateway_handler
VALUES ('17', '黑名单拦截', 'blacklistHandler', 'currentLimitHandler', 'conversationHandler');
INSERT INTO gateway_handler
VALUES ('18', '会话验证', 'conversationHandler', 'blacklistHandler', null);
Utils
=========
@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);
}
}
GatewayHandlerService
=========================
/**
@title: GatewayHandlerService
*/
@Service
public class GatewayHandlerService {
@Autowired
private GatewayHandlerMapper gatewayHandlerMapper;
private GatewayHandler firstGatewayHandler;
/**
获取数据库第一个 handeler 封装
*/
public GatewayHandler getFirstGatewayHandler() {
if (firstGatewayHandler != null) {
return firstGatewayHandler;
}
//1.【第一个实体】
GatewayHandlerEntity firstGatewayHandlerEntity = gatewayHandlerMapper.getFirstGatewayHandler();
if(firstGatewayHandlerEntity==null){ return null; }
//2.【第一个 HandlerId】
String firstHhandlerId = firstGatewayHandlerEntity.getHandlerId();
//3.【第二个 HandlerId】
String secondHandlerId = firstGatewayHandlerEntity.getNextHandlerId();
//4.【第一个 bean 对象】
GatewayHandler firstGatewayHandler = SpringUtils.getBean(firstHhandlerId, GatewayHandler.class);
//5.【tmpHandler 为第一个 bean 对象】
GatewayHandler tmpHandler=firstGatewayHandler;
//如果下一个 HandlerId 不为 null,则继续
while (!StringUtils.isBlank(secondHandlerId)){
//6.【第二个 bean 对象】->11.【第三个 bean 对象】
GatewayHandler secondGatewayHandler = SpringUtils.getBean(secondHandlerId, GatewayHandler.class);
//7.【设置第一个 bean 对象的 next 为第二个 bean 对象】->12.【设置第二个 bean 对象的 next 为第三个 bean 对象】
tmpHandler.setNextGatewayHandler(secondGatewayHandler);
//8.【第二个实体】->13.【第三个实体】
GatewayHandlerEntity secondHandlerEntity = gatewayHandlerMapper.getByHandler(secondHandlerId);
if (secondHandlerEntity==null){ break; }
//9.【第三个 HandlerId】->14.【第四个 HandlerId】此时为 null,后面会退出循环
secondHandlerId=secondHandlerEntity.getNextHandlerId();
//10.【tmpHandler 为第二个 bean 对象】->15.【tmpHandler 为第三个 bean 对象】
tmpHandler=secondGatewayHandler;
}
//16.赋值
this.firstGatewayHandler=firstGatewayHandler;
//17.返回第一个 firstHandler 对象
return firstGatewayHandler;
}
}
数据库访问层
GatewayHandlerMapper
public interface GatewayHandlerMapper {
/**
获取第一个 GatewayHandler
*/
@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;;")
public GatewayHandlerEntity getFirstGatewayHandler();
@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}")
public GatewayHandlerEntity getByHandler(String handlerId);
}
Entity 层
@Data
public class GatewayHandlerEntity implements Serializable, Cloneable {
/**
主键 ID
*/
private Integer id;
/**
handler 名称
*/
private String handlerName;
/**
handler 主键 id
*/
private String handlerId;
/**
下一个 handler
*/
private String nextHandlerId;
}
Controller 层
/**
@title: HandlerController
*/
@RestController
public class HandlerController {
@Autowired
private GatewayHandlerService gatewayHandlerService;
@RequestMapping("/client")
public String client() {
GatewayHandler firstGatewayHandler = gatewayHandlerService.getFirstGatewayHandler();
firstGatewayHandler.service();
return "success";
}
}
相关配置信息
==========
版权 @须臾之余
https://my.oschina.net/u/3995125
application.yml
###服务启动端口号
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/design_pattern?useUnicode=true&characterEncoding=UTF-8&useSSL=true
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
####打印 MyBatias 日志
logging:
level:
开发环境使用 DEBUG 生产环境 info 或者 error
com.xuyu.mapper: DEBUG
Maven 依赖信息
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</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>
<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>
启动类
/**
@title: AppHandler
*/
@SpringBootApplication
@MapperScan("com.xuyu.mapper")
@EnableAutoConfiguration
public class AppHandler {
public static void main(String[] args) {
SpringApplication.run(AppHandler.class);
评论