聊聊RespCommand
序
本文主要研究一下RespCommand
RespCommand
resp-server-0.16.0/src/main/java/com/github/tonivade/resp/command/RespCommand.java
@FunctionalInterface
public interface RespCommand {
RedisToken execute(Request request);
}
- RespCommand定义了execute方法,接收Request参数,返回RedisToken
Request
resp-server-0.16.0/src/main/java/com/github/tonivade/resp/command/Request.java
public interface Request {
String getCommand();
ImmutableArray<SafeString> getParams();
SafeString getParam(int i);
Option<SafeString> getOptionalParam(int i);
int getLength();
boolean isEmpty();
Session getSession();
ServerContext getServerContext();
boolean isExit();
}
- Request接口定义了getCommand、getParams、getParam、getOptionalParam、getLength、isEmpty、getSession、getServerContext、isExit方法
DefaultRequest
resp-server-0.16.0/src/main/java/com/github/tonivade/resp/command/DefaultRequest.java
public class DefaultRequest implements Request {
private final SafeString command;
private final ImmutableArray<SafeString> params;
private final Session session;
private final ServerContext server;
public DefaultRequest(ServerContext server, Session session, SafeString command, ImmutableArray<SafeString> params) {
this.server = server;
this.session = session;
this.command = requireNonNull(command);
this.params = requireNonNull(params);
}
@Override
public String getCommand() {
return command.toString();
}
@Override
public ImmutableArray<SafeString> getParams() {
return params;
}
@Override
public SafeString getParam(int i) {
if (i < params.size()) {
return params.get(i);
}
return null;
}
@Override
public Option<SafeString> getOptionalParam(int i) {
return Option.of(() -> getParam(i));
}
@Override
public int getLength() {
return params.size();
}
@Override
public boolean isEmpty() {
return params.isEmpty();
}
@Override
public boolean isExit() {
return command.toString().equalsIgnoreCase("quit");
}
@Override
public Session getSession() {
return session;
}
@Override
public ServerContext getServerContext() {
return server;
}
@Override
public String toString() {
return command + "[" + params.size() + "]: " + params;
}
}
- DefaultRequest实现了Request接口,它定义了command、params、session、server属性,均在构造器中传入
CommandSuite
resp-server-0.16.0/src/main/java/com/github/tonivade/resp/command/CommandSuite.java
public class CommandSuite {
private static final Logger LOGGER = LoggerFactory.getLogger(CommandSuite.class);
private final Map<String, Class<?>> metadata = new HashMap<>();
private final Map<String, RespCommand> commands = new HashMap<>();
private final NullCommand nullCommand = new NullCommand();
private final CommandWrapperFactory factory;
public CommandSuite() {
this(new DefaultCommandWrapperFactory());
}
public CommandSuite(CommandWrapperFactory factory) {
this.factory = factory;
addCommand(PingCommand.class);
addCommand(EchoCommand.class);
addCommand(QuitCommand.class);
addCommand(TimeCommand.class);
}
public RespCommand getCommand(String name) {
return commands.getOrDefault(name.toLowerCase(), nullCommand);
}
public boolean isPresent(String name, Class<? extends Annotation> annotationClass) {
return getMetadata(name).isAnnotationPresent(annotationClass);
}
public boolean contains(String name) {
return commands.get(name) != null;
}
protected void addCommand(Class<?> clazz) {
Try.of(clazz::newInstance)
.onSuccess(this::processCommand)
.onFailure(e -> LOGGER.error("error loading command: " + clazz.getName(), e));
}
protected void addCommand(String name, RespCommand command) {
commands.put(name.toLowerCase(), factory.wrap(command));
}
private void processCommand(Object command) {
Class<?> clazz = command.getClass();
Command annotation = clazz.getAnnotation(Command.class);
if (annotation != null) {
commands.put(annotation.value(), factory.wrap(command));
metadata.put(annotation.value(), clazz);
} else {
LOGGER.warn("annotation not present at {}", clazz.getName());
}
}
private Class<?> getMetadata(String name) {
return metadata.getOrDefault(name.toLowerCase(), Void.class);
}
}
- CommandSuite的构造器添加了PingCommand、EchoCommand、QuitCommand、TimeCommand四个command;addCommand方法将factory.wrap(command)的命令放入commands中
CommandWrapperFactory
resp-server-0.16.0/src/main/java/com/github/tonivade/resp/command/CommandWrapperFactory.java
public interface CommandWrapperFactory {
RespCommand wrap(Object command);
}
- CommandWrapperFactory定义了wrap方法,将command包装为RespCommand
DefaultCommandWrapperFactory
resp-server-0.16.0/src/main/java/com/github/tonivade/resp/command/DefaultCommandWrapperFactory.java
public class DefaultCommandWrapperFactory implements CommandWrapperFactory {
@Override
public RespCommand wrap(Object command) {
if (command instanceof RespCommand) {
return new CommandWrapper((RespCommand) command);
}
throw new IllegalArgumentException("must implements command interface");
}
}
- DefaultCommandWrapperFactory实现了CommandWrapperFactory接口,其wrap方法使用CommandWrapper包装RespCommand
CommandWrapper
resp-server-0.16.0/src/main/java/com/github/tonivade/resp/command/CommandWrapper.java
public class CommandWrapper implements RespCommand {
private int params;
private final RespCommand command;
public CommandWrapper(RespCommand command) {
this.command = command;
ParamLength length = command.getClass().getAnnotation(ParamLength.class);
if (length != null) {
this.params = length.value();
}
}
@Override
public RedisToken execute(Request request) {
if (request.getLength() < params) {
return error("ERR wrong number of arguments for '" + request.getCommand() + "' command");
}
return command.execute(request);
}
}
- CommandWrapper会读取ParamLength注解,若读的到则将注解的value值赋值给params,用于execute方法对request的参数长度进行校验
小结
RespCommand定义了execute方法,接收Request参数,返回RedisToken;CommandSuite的构造器添加了PingCommand、EchoCommand、QuitCommand、TimeCommand四个command;addCommand方法将factory.wrap(command)的命令放入commands中;DefaultCommandWrapperFactory实现了CommandWrapperFactory接口,其wrap方法使用CommandWrapper包装RespCommand;CommandWrapper会读取ParamLength注解,若读的到则将注解的value值赋值给params,用于execute方法对request的参数长度进行校验
doc
- MySQL错误修复记录:Table xx is marked as crashed and should be repaired
- WordPress百度自动推送JS优化,规避错误、重复推送问题
- Oracle 12c中DBCA搭建备库体验(r11笔记第92天)
- 一行代码彻底禁用WordPress缩略图自动裁剪功能
- MySQL中xtrabackup备份恢复全攻略(r12笔记第11天)
- 分享一次Linux任务计划crontab不执行的问题排查过程
- MySQL 5.6, 5.7并行复制测试(r12笔记第9天)
- MySQL 5.6, 5.7并行复制测试(二)(r12笔记第10天)
- MySQL主从报错解决:Failed to initialize the master info structure
- 使用pt工具检测MySQL主从延迟(r12笔记第7天)
- WordPress发布/更新文章、提交/审核评论自动清理VeryCloud缓存
- MySQL中的binlog和redo浅析(r12笔记第5天)
- WordPress发布/更新文章、提交/审核评论自动清理腾讯云CDN缓存
- 使用sysbench压力测试MySQL(一)(r11笔记第3天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Octave 笔记
- VSCode如何设置Vue前端的debug调试
- Istio安全-授权(实操三)
- SpringBoot入门建站全系列(三十六)AspectJ做AOP日志管理
- 图像处理笔记(1)----OpenCV 图像BGR转RGB
- Intellij IDEA常用操作整理手册
- IDEA类和方法注释模板设置(非常详细)
- 《JavaScript 模式》读书笔记(7)— 设计模式2
- 《JavaScript 模式》读书笔记(7)— 设计模式3
- 弄它!!!Ospf--动态路由--链路状态路由协议!全面解析OSPF协议!
- 弄它!!!理论加实验,小小ISIS分分钟拿下!!
- 「Mysql索引原理(二)」Mysql高性能索引实践,索引概念、BTree索引、B+Tree索引
- 「Mysql索引原理(一)」1.存储引擎简介
- 弄它!!!小小BGP!理论加实验分分钟拿下!带你体验大网的世界!
- 搞它!!!Linux常用命令合集