1.作用

通过写java代码,实现自己想要定义的命令,并且也可以实现按Tab键命令补全,help命令功能,退出程序功能。

2.需要的jar包

jar包名

说明

jline-3.6.2.jar

提供命令行开发需要的类和方法(核心jar包)

因为在windows上需要用到系统的dll文件(动态链接库),所以还需要下面五个jar包:

jar包名

说明

jansi-1.17.jar

Jansi是一个用于生成和解释ANSI转义序列的java库

jna-4.2.2.jar

Java本机访问

jsr305-3.0.2.jar

Findbugs的JSR305注释

juniversalchardet-1.0.3.jar

Java编码检测器库

sshd-core-1.4.0.jar

3.搭建一个最基础的框架

(1)计算机上的虚拟终端

Terminal terminal = TerminalBuilder.builder().system(true).build();

代码

说明

TerminalBuilder

TerminalBuilder类,创建终端的生成器类

.builder()

返回new TerminalBuilder()

.system(true)

给TerminalBuilder类中的system赋值并返回TerminalBuilder类

.build()

调用TerminalBuilder类中的build()方法获取Terminal 并返回Terminal

(2)通过输入从控制台读取行

LineReader lineReader = LineReaderBuilder.builder().terminal(terminal).build();

代码

说明

LineReaderBuilder

LineReaderBuilder 类

.builder()

返回new LineReaderBuilder ()

.terminal(terminal)

给LineReaderBuilder 类中的terminal赋值并返回LineReaderBuilder 类

.build()

返回LineReader

(3)原样输出输入的内容的demo

public static void main(String[] args) {
	try {
		Terminal terminal = TerminalBuilder.builder().system(true).build();
		LineReader lineReader = LineReaderBuilder.builder().terminal(terminal).build();
		String prompt = "demo > "; // 输入命令提示信息
		// 用while死循环,可以在执行完命令后不退出程序,可以继续输入命令
		while (true) {
			String line = lineReader.readLine(prompt); // 获取输入的信息
			System.out.println("输入的命令是:" + line); // 输出输入的信息
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}

执行结果如下:

demo > a
输入的命令是:a
demo > b
输入的命令是:b
demo >

4.执行命令

把输入的命令解析成的list传进需要执行命令的方法中,逐个取值,通过switch判断需要执行哪个方法,依次执行。

public static void main(String[] args) {
	try {
		Terminal terminal = TerminalBuilder.builder().system(true).build();
		LineReader lineReader = LineReaderBuilder.builder().terminal(terminal).build();
		String prompt = "demo > ";
		while (true) {
			String line = lineReader.readLine(prompt);
			System.out.println("输入的命令是:" + line);
			if (null == line) {
				continue;
			}
	
			line = line.trim();
			if (!line.isEmpty()) {
				ParsedLine parsedLine = lineReader.getParsedLine(); // 解析输入的命令
				if (null == parsedLine) {
					continue;
				}
				List<String> words = parsedLine.words(); // 获取输入的命令解析成的list
				System.out.println("解析命令生成的list为:" + words);
				
				Demo.executeCommand(words); // 执行命令
			}
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}

public static void executeCommand(List<String> commands) throws Exception {
	switch (commands.get(0)) {
	case "schema":
		if (commands.size() >= 2) {
			Demo.schemaCommand(commands);
		} else {
			System.out.println("schema命令");
		}
		break;
	case "table":
		if (commands.size() >= 2) {
			Demo.tableCommand(commands);
		} else {
			System.out.println("table命令");
		}
		break;
	case "help":
		System.out.println("帮助");
		break;
	case "quit":
		System.out.println("退出程序");
		System.exit(0);
		break;
	default:
		System.out.println("不支持该命令");
	}
}

public static void schemaCommand(List<String> commands) throws Exception {
	switch (commands.get(1)) {
	case "select":
		System.out.println("查询schema");
		break;
	case "update":
		System.out.println("修改schema");
		break;
	default:
		System.out.println("不支持该命令");
	}
}

public static void tableCommand(List<String> commands) throws Exception {
	switch (commands.get(1)) {
	case "select":
		System.out.println("查询表");
		break;
	case "update":
		System.out.println("修改表");
		break;
	default:
		System.out.println("不支持该命令");
	}
}

执行结果如下:

demo > schema select
输入的命令是:schema select
解析命令生成的list为:[schema, select]
查询schema
demo > schema update
输入的命令是:schema update
解析命令生成的list为:[schema, update]
修改schema
demo > table select
输入的命令是:table select
解析命令生成的list为:[table, select]
查询表
demo > help
输入的命令是:help
解析命令生成的list为:[help]
帮助
demo > quit
输入的命令是:quit
解析命令生成的list为:[quit]
退出程序

5.help命令

把所有命令放到list里面,执行help命令时,输出list中的内容

public static void executeCommand(List<String> commands) throws Exception {
	switch (commands.get(0)) {
	case "schema":
		if (commands.size() >= 2) {
			Demo.schemaCommand(commands);
		} else {
			System.out.println("schema命令");
		}
		break;
	case "table":
		if (commands.size() >= 2) {
			Demo.tableCommand(commands);
		} else {
			System.out.println("table命令");
		}
		break;
	case "help":
		System.out.println("帮助");
		List<Command> commandList = getCommandList();
		for (int i = 0; i < commandList.size(); i++) {
			System.out.print(commandList.get(i).getCommand());
			System.out.println(commandList.get(i).getDescription());

			List<Command> childCommandList = commandList.get(i).getChildCommandList();
			if (null != childCommandList) {
				for (int j = 0; j < childCommandList.size(); j++) {
					System.out.print("    " + childCommandList.get(j).getCommand());
					System.out.println(childCommandList.get(j).getDescription());
				}
			}
		}
		break;
	case "quit":
		System.out.println("退出程序");
		System.exit(0);
		break;
	default:
		System.out.println("不支持该命令");
	}
}

public static List<Command> getCommandList() throws Exception {
	List<Command> commandList = new ArrayList<Command>();
		
	List<Command> schemaCommandList = new ArrayList<Command>();
	schemaCommandList.add(new Command("select", "查询模式", null));
	schemaCommandList.add(new Command("update", "修改模式", null));
	commandList.add(new Command("schema", "操作模式", schemaCommandList));
		
	List<Command> tableCommandList = new ArrayList<Command>();
	tableCommandList.add(new Command("select", "查询表", null));
	tableCommandList.add(new Command("update", "修改表", null));
	commandList.add(new Command("table", "操作表", tableCommandList));
		
	commandList.add(new Command("help", "帮助", null));
	commandList.add(new Command("quit", "退出程序", null));
		
	return commandList;
}

Command对象类

public class Command {

	private String command;
	private String description;
	private List<Command> childCommandList;

	public String getCommand() {
		return command;
	}

	public void setCommand(String command) {
		this.command = command;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public List<Command> getChildCommandList() {
		return childCommandList;
	}

	public void setChildCommandList(List<Command> childCommandList) {
		this.childCommandList = childCommandList;
	}
	
	public Command(String command, String description, List<Command> childCommandList) {
		this.command = command;
		this.description = description;
		this.childCommandList = childCommandList;
	}
}

执行结果如下:

demo > help
输入的命令是:help
解析命令生成的list为:[help]
帮助
schema操作模式
    select查询模式
    update修改模式
table操作表
    select查询表
    update修改表
help帮助
quit退出程序
demo > quit
输入的命令是:quit
解析命令生成的list为:[quit]
退出程序

6.Tab命令补全

tab命令补全只需要在初始化LineReader类的时候添加上即可。
由原来的

LineReader lineReader = LineReaderBuilder.builder().terminal(terminal).build();

改为

LineReader lineReader = LineReaderBuilder.builder().terminal(terminal).completer(Demo.getCompleter()).build();

getCompleter()方法相关代码如下:

private static Completer getCompleter() {
	Completer completer = new AggregateCompleter(
		getSchemaCompleter(),
		getTableCompleter(),
		getHelpCompleter(),
		getQuitCompleter()
	);
	return completer;
}
	
private static  Completer getSchemaCompleter() {
	Completer schemaCompleter = new TreeCompleter(
		node("schema",
			node("select", node(NullCompleter.INSTANCE)),
			node("update", node(NullCompleter.INSTANCE))
		)
	);
	return schemaCompleter;
}
	
private static Completer getTableCompleter() {
	Completer tableCompleter = new TreeCompleter(
		node("table",
			node("select", node(NullCompleter.INSTANCE)),
			node("update", node(NullCompleter.INSTANCE))
		)
	);
	return tableCompleter;
}
	
private static Completer getHelpCompleter() {
	return new ArgumentCompleter(new StringsCompleter("help"), NullCompleter.INSTANCE);
}
	
private static Completer getQuitCompleter() {
	return new ArgumentCompleter(new StringsCompleter("quit"), NullCompleter.INSTANCE);
}
  • StringsCompleter 只能实现一个单词的补全
  • ArgumentCompleter 补全整条命令
  • AggregateCompleter将多种可能的补全方式组合到一起
  • TreeCompleter是树形的集合,node添加子命令
  • ArgumentCompleter 相当于串联电路,而 AggregateCompleter 相当于并联电路

7.输入密码不显示但能获取到密码(ReadPassword)

java.io.Console类可以不回显输入的密码
我用的eclipse,因为eclipse没有主控制台console,所以取不到console,System.console()只能是null
程序打包之后是可以正常用的

public static void main(String[] args) {
	Console console = System.console();
	if (console != null) {
		String name = console.readLine("input name: ");
		char[] password = console.readPassword("input password: ");
		String pwd = new String(password);
		System.out.println("name = " + name + "  password = " + pwd);
	}
}

执行结果如下:

JAVA用户交互 java 命令行交互_退出程序