通过Spring Shell 开发 Java 命令行应用

提到 Java,大家都会想到 Java 在服务器端应用开发中的使用。实际上,Java 在命令行应用的开发中也有一席之地。在很多情况下,相对于图形用户界面来说,命令行界面响应速度快,所占用的系统资源少。在与用户进行交互的场景比较单一时,命令行界面是更好的选择。命令行界面有其固定的交互模式。通常是由用户输入一系列的参数,在执行之后把相应的结果在控制台输出。命令行应用通常需要处理输入参数的传递和验证、输出结果的格式化等任务。Spring Shell 可以帮助简化这些常见的任务,让开发人员专注于实现应用的业务逻辑。本文对 Spring Shell 进行详细的介绍。

Spring Shell 入门

最简单的创建 Spring Shell 应用的方式是使用 Spring Boot。从 Spring Initializr 网站(http://start.spring.io/)上创建一个新的基于 Apache Maven 的 Spring Boot 应用,然后添加 Spring Shell 相关的依赖即可。本文介绍的是 Spring Shell 2.0.0.M2 版本,目前还只是 Milestone 版本,因此需要在 pom.xml 中添加 Spring 提供的包含 Milestone 版本工件的 Maven 仓库,如代码清单 1 所示。否则的话,Maven 会无法找到相应的工件。

清单 1. 添加 Spring Shell 的 Maven 仓库

<repositories>
 <repository>
 <id>spring-milestone</id>
 <name>Spring Repository</name>
 <url>https://repo.spring.io/milestone</url>
 </repository>
</repositories>

在添加了 Spring Shell 的 Maven 仓库之后,可以在 Spring Boot 项目中添加对于spring-shell-starter 的依赖,如代码清单 2 所示。

清单 2. 添加 Spring Shell 所需 Maven 依赖

<dependency>
 <groupId>org.springframework.shell</groupId>
 <artifactId>spring-shell-starter</artifactId>
 <version>2.0.0.M2</version>
</dependency>

我们接着可以创建第一个基于 Spring Shell 的命令行应用。该应用根据输入的参数来输出相应的问候语,完整的代码如清单 3 所示。从代码清单 3 中可以看到,在 Spring Shell 的帮助下,完整的实现代码非常简单。代码的核心是两个注解:@ShellComponent 声明类GreetingApp 是一个 Spring Shell 的组件;@ShellMethod 表示方法 sayHi 是可以在命令行运行的命令。该方法的参数 name 是命令行的输入参数,而其返回值是命令行执行的结果。

清单 3. 输出问候语的命令行应用

<dependency>
 <groupId>org.springframework.shell</groupId>
 <artifactId>spring-shell-starter</artifactId>
 <version>2.0.0.M2</version>
</dependency>

接下来我们运行该应用。运行起来之后,该应用直接进入命令行提示界面,我们可以输入 help 来输出使用帮助。help 是 Spring Shell 提供的众多内置命令之一,在列出的命令中,可以看到我们创建的 say-hi 命令。我们输入"say-hi Alex"来运行该命令,可以看到输出的结果"Hi Alex"。如果我们直接输入"say-hi",会看到输出的错误信息,告诉我们参数"--name"是必须的。从上面的例子可以看出,在 Spring Shell 的帮助下,创建一个命令行应用是非常简单的。很多实用功能都已经默认提供了。在使用 Spring Initializr 创建的 Spring Boot 项目中,默认提供了一个单元测试用例。这个默认的单元测试用例与 Spring Shell 在使用时存在冲突。在进行代码清单 3 中的项目的 Maven 构建时,该测试用例需要被禁用,否则构建过程会卡住。

参数传递与校验

下面我们讨论 Spring Shell 中的参数传递和校验。Spring Shell 支持两种不同类型的参数,分别是命名参数和位置参数。命名参数有名称,可以通过类似--arg 的方式来指定;位置参数则按照其在方法的参数列表中的出现位置来进行匹配。命名参数和位置参数可以混合起来使用,不过命名参数的优先级更高,会首先匹配命名参数。每个参数都有默认的名称,与方法中的对应的参数名称一致。

在代码清单 4 中的方法有 3 个参数 a、b 和 c。在调用该命令时,可以使用"echo1 --a 1 --b 2 --c 3",也可以使用"echo1 --a 1 2 3"或"echo1 1 3 --b 2"。其效果都是分别把 1,2 和 3 赋值给 a、b 和 c。

清单 4. 包含多个参数的命令方法

@ShellMethod("Echo1")
public String echo1(int a, int b, int c) {
 return String.format("a = %d, b = %d, c = %d", a, b, c);
}

如果不希望使用方法的参数名称作为命令对应参数的名称,可以通过@ShellOption 来标注所要使用的一个或多个参数名称。我们可以通过指定多个参数名称来提供不同的别名。在代码清单 5 中,为参数 b 指定了一个名称 boy。可以通过"echo2 1 --boy 2 3"来调用。

清单 5. 指定参数名称

@ShellMethod("Echo2")
public String echo2(int a, @ShellOption("--boy") int b, int c) {
 return String.format("a = %d, b = %d, c = %d", a, b, c);
}

对于命名参数,默认使用的是"--"作为前缀,可以通过@ShellMethod 的属性 prefix 来设置不同的前缀。方法对应的命令的名称默认是从方法名称自动得到的,可以通过属性 key 来设置不同的名称,属性 value 表示的是命令的描述信息。如果参数是可选的,可以通过@ShellOption 的属性 defaultValue 来设置默认值。在代码清单 6 中,我们为方法 withDefault 指定了一个命令名称 default,同时为参数 value 指定了默认值"Hello"。如果直接运行命令"default",输出的结果是"Value: Hello";如果运行命令"default 123",则输出的结果是"Value: 123"。

清单 6. 指定方法名称和参数默认值

@ShellComponent
public class NameAndDefaultValueApp {
 @ShellMethod(key = "default", value = "With default value")
 public void withDefault(@ShellOption(defaultValue = "Hello") final String value) {
 System.out.printf("Value: %s%n", value);
 }
}

一个参数可以对应多个值。通过@ShellOption 属性 arity 可以指定一个参数所对应的值的数量。这些参数会被添加到一个数组中,可以在方法中访问。在代码清单 7 中,方法 echo3 的参数 numbers 的 arity 值是 3,因此可以映射 3 个参数。在运行命令"echo3 1 2 3"时,输出的结果是"a = 1, b =2, c = 3"。

清单 7. 参数对应多个值

@ShellMethod("Echo3")
public String echo3(@ShellOption(arity = 3) int[] numbers) {
 return String.format("a = %d, b = %d, c = %d", numbers[0], numbers[1], numbers[2]);
}

如果参数的类型是布尔类型 Boolean,在调用的时候不需要给出对应的值。当参数出现时就表示值为 true。

Spring Shell 支持对参数的值使用 Bean Validation API 进行验证。比如我们可以用@Size 来限制字符串的长度,用@Min 和@Max 来限制数值的大小,如代码清单 8 所示。

清单 8. 校验参数

@ShellComponent
public class ParametersValidationApp {
 @ShellMethod("String size")
 public String stringSize(@Size(min = 3, max = 16) String name) {
 return String.format("Your name is %s", name);
 }
 @ShellMethod("Number range")
 public String numberRange(@Min(10) @Max(100) int number) {
 return String.format("The number is %s", number);
 }
}

结果处理

Spring Shell 在运行时,内部有一个处理循环。在每个循环的执行过程中,首先读取用户的输入,然后进行相应的处理,最后再把处理的结果输出。这其中的结果处理是由 org.springframework.shell.ResultHandler 接口来实现的。Spring Shell 中内置提供了对于不同类型结果的处理实现。命令执行的结果可能有很多种:如果用户输入的参数错误,输出的结果应该是相应的提示信息;如果在命令的执行过程中出现了错误,则需要输出相应的错误信息;用户也可能直接退出命令行。Spring Shell 默认使用的处理实现是类 org.springframework.shell.result.IterableResultHandler。IterableResultHandler 负责处理 Iterable 类型的结果对象。对于 Iterable 中包含的每个对象,把实际的处理请求代理给另外一个 ResultHandler 来完成。IterableResultHandler 默认的代理实现是类 org.springframework.shell.result.TypeHierarchyResultHandler。TypeHierarchyResultHandler 其实是一个复合的处理器,它会把对于不同类型结果的 ResultHandler 接口的实现进行注册,然后根据结果的类型来选择相应的处理器实现。如果找不到类型完全匹配的处理器实现,则会沿着结果类型的层次结构树往上查找,直到找到对应的处理器实现。Spring Shell 提供了对于 Object 类型结果的处理实现类 org.springframework.shell.result.DefaultResultHandler,因此所有的结果类型都可以得到处理。DefaultResultHandler 所做的处理只是把 Object 类型转换成 String,然后输出到控制台。

了解了 Spring Shell 对于结果的处理方式之后,我们可以添加自己所需要的特定结果类型的处理实现。代码清单 9 给了一个作为示例的处理结果类 PrefixedResult。PrefixedResult 中包含一个前缀 prefix 和实际的结果 result。

清单 9. 带前缀的处理结果

public class PrefixedResult {
 private final String prefix;
 private final String result;
 public PrefixedResult(String prefix, String result) {
 this.prefix = prefix;
 this.result = result;
 }
 public String getPrefix() {
 return prefix;
 }
 public String getResult() {
 return result;
 }
}

在代码清单 10 中,我们为 PrefixedResult 添加了具体的处理器实现。该实现也非常简单,只是把结果按照某个格式进行输出。

清单 10. PrefixedResult 对应的处理器实现

@Component
public class PrefixedResultHandler implements ResultHandler<PrefixedResult> {

 @Override
 public void handleResult(PrefixedResult result) {
 System.out.printf("%s --> %s%n", result.getPrefix(), result.getResult());
 }
}

在代码清单 11 中,命令方法 resultHandler 返回的是一个 PrefixedResult 对象,因此会被代码清单 10 中的处理器来进行处理,输出相应的结果。

清单 11. 使用 PrefixedResult 的命令

@ShellComponent
public class CustomResultHandlerApp {
 @ShellMethod("Result handler")
 public PrefixedResult resultHandler() {
 return new PrefixedResult("PRE", "Hello!");
 }
}

代码清单 12 给出了具体的命令运行结果。

清单 12. 命令的处理结果

myshell=>result-handler
PRE --> Hello!

自定义提示符

在启动命令行应用时,会发现该应用使用的是默认提示符"shell:>"。该提示符是可以定制的,只需要提供接口 org.springframework.shell.jline.PromptProvider 的实现即可。接口 PromptProvider 中只有一个方法,用来返回类型为 org.jline.utils.AttributedString 的提示符。在代码清单 13 中,我们定义了一个 PromptProvider 接口的实现类,并使用"myshell=>"作为提示符,而且颜色为蓝色。

清单 13. 自定义提示符

@Bean
public PromptProvider promptProvider() {
 return () -> new AttributedString("myshell=>",
  AttributedStyle.DEFAULT.foreground(AttributedStyle.BLUE));
}

动态命令可用性

前面所创建的命令都是一直可用的。只要应用启动起来,就可以使用这些命令。不过有些命令的可用性可能取决于应用的内部状态,只有内部状态满足时,才可以使用这些命令。对于这些命令,Spring Shell 提供了类 org.springframework.shell.Availability 来表示命令的可用性。通过类 Availability 的静态方法 available()和 unavailable()来分别创建表示命令可用和不可用的 Availability 对象。

在代码清单 14 中,我们创建了两个命令方法 runOnce()和 runAgain()。变量 run 作为内部状态。在运行 runOnce()之后,变量 run 的值变为 true。命令 runAgain 的可用性由方法 runAgainAvailability()来确定。该方法根据变量 run 的值来决定 runAgain 是否可用。按照命名惯例,检查命令可用性的方法的名称是在命令方法名称之后加上 Availability 后缀。如果需要使用不同的方法名称,或是由一个检查方法控制多个方法,可以在检查方法上添加注解@ShellMethodAvailability 来声明其控制的方法名称。

清单 14. 动态命令可用性

@ShellComponent
public class RunTwiceToEnableApp {
 private boolean run = false;
 @ShellMethod("Run once")
 public void runOnce() {
 this.run = true;
 }
 @ShellMethod("Run again")
 public void runAgain() {
 System.out.println("Run!");
 }
 public Availability runAgainAvailability() {
 return run
  ? Availability.available()
  : Availability.unavailable("You should run runOnce first!");
 }
}

输入参数转换

之前的@ShellMethod 标注的方法使用的都是简单类型的参数。Spring Shell 通过 Spring 框架的类型转换系统来进行参数类型的转换。Spring 框架已经内置提供了对常用类型的转换逻辑,包括原始类型、String 类型、数组类型、集合类型、Java 8 的 Optional 类型、以及日期和时间类型等。我们可以通过 Spring 框架提供的扩展机制来添加自定义的转换实现。

代码清单 15 中的 User 类是作为示例的一个领域对象,包含了 id 和 name 两个属性。

清单 15. User

public class User {
 private final String id;
 private final String name;
 public User(String id, String name) {
 this.id = id;
 this.name = name;
 }
 public String getName() {
 return name;
 }
}

代码清单 16 中的 UserService 用来根据 id 来查找对应的 User 对象。作为示例,UserService 只是简单使用一个 HashMap 来保存作为测试的 User 对象。

清单 16. UserService

public class UserService {
 private final Map<String, User> users = new HashMap<>();
 public UserService() {
 users.put("alex", new User("alex", "Alex"));
 users.put("bob", new User("bob", "Bob"));
 }
 public User findUser(String id) {
 return users.get(id);
 }
}

在代码清单 17 中,UserConverter 实现了 Spring 中的 Converter 接口并添加了从 String 到 User 对象的转换逻辑,即通过 UserService 来进行查找。

清单 17. 使用类型转换

@Component
public class UserConverter implements Converter<String, User> {
 private final UserService userService = new UserService();
 @Override
 public User convert(String source) {
 return userService.findUser(source);
 }
}

在代码清单 18 中,命令方法 user 的参数是 User 类型。当运行命令"user alex"时,输入参数 alex 会通过代码清单 17 中的类型转换服务转换成对应的 User 对象,然后输出 User 对象的属性值 name。如果找不到与输入参数值对应的 User 对象,则输出"User not found"。

清单 18. 使用类型转换的命令

@ShellComponent
public class UserCommandApp {
 @ShellMethod("User")
 public void user(final User user) {
 if (user != null) {
  System.out.println(user.getName());
 } else {
  System.out.println("User not found");
 }
 }
}

命令组织方式

当创建很多个命令时,需要有一种把这些命令组织起来。Spring Shell 提供了不同的方式来对命令进行分组。处于同一分组的命令会在 help 命令输出的帮助中出现在一起。默认情况下,同一个类中的命令会被添加到同一分组中。默认的分组名称根据对应的 Java 类名来自动生成。除了默认分组之外,还可以显式的设置分组。可以使用@ShellMethod 注解的属性 group 来指定分组名称;还可以为包含命令的类添加注解@ShellCommandGroup,则该类中的所有命令都在由@ShellCommandGroup 指定的分组中;还可以把@ShellCommandGroup 注解添加到包声明中,则该包中的所有命令都在由@ShellCommandGroup 指定的分组中。

在代码清单 19 中,通过@ShellCommandGroup 为命令所在类添加了自定义的分组名称 Special。其中的方法 command2 则通过@ShellMethod 的 group 属性指定了不同的分组名称"Basic Group"。

清单 19. 组织命令

@ShellComponent
@ShellCommandGroup("Special")
public class CommandsGroupApp {
 @ShellMethod("Command1")
 public void command1() {}
 @ShellMethod(value = "Command2", group = "Basic Group")
 public void command2() {}
}

图 1 显示了示例应用的 help 命令的输出结果,从中可以看到命令的分组情况。

图 1. 所有的命令列表

commands.png

内置命令

Spring Shell 提供了很多内置的命令,如下所示。

运行 help 命令可以列出来应用中的所有命令和对应的描述信息。
运行 clear 命令可以进行清屏操作。
运行 exit 命令可以退出命令行应用。
运行 script 命令可以执行一个文件中包含的所有命令。
如果不需要某个内置命令,可以通过把上下文环境中的属性 spring.shell.command.<command>.enabled 的值设为 false 来禁用。如果希望禁用全部的内置命令,可以把 spring-shell-standard-commands 从 Maven 依赖中排除,如代码清单 20 所示。

清单 20. 排除内置命令对应的 Maven 依赖

<dependency>
 <groupId>org.springframework.shell</groupId>
 <artifactId>spring-shell-starter</artifactId>
 <version>2.0.0.M2</version>
 <exclusions>
 <exclusion>
  <groupId>org.springframework.shell</groupId>
  <artifactId>spring-shell-standard-commands</artifactId>
 </exclusion>
 </exclusion>
</dependency>

小结

命令行应用以其简单易用,占有资源少,速度快的特点,仍然在 Java 应用开发中占据一席之地。Spring Shell 为开发命令行应用提供了坚实的基础,可以极大的提高开发效率。本文对 Spring Shell 进行了详细的介绍,从基础的入门,到参数的传递和校验,再到结果处理、自定义提示符、动态命令可用性、输入参数转换、命令组织和内置命令等。在阅读本文之后,读者可以了解如何使用 Spring Shell 开发命令行应用。

以上所述是小编给大家介绍的通过Spring Shell 开发 Java 命令行应用,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • SpringBoot文件上传控制及Java 获取和判断文件头信息

    之前在使用SpringBoot进行文件上传时,遇到了很多问题.于是在翻阅了很多的博文之后,总算将上传功能进行了相应的完善,便在这里记录下来,供自己以后查阅. 首先,是建立一个标准的SpringBoot 的工程,这里使用的IDE是Intellij Idea,为了方便配置,将默认的配置文件替换为了application.yml. 1.在index.html中进行文件上传功能,这里使用的文件上传方式是ajax,当然也可以按照自己的具体要求使用传统的表单文件上传. <!DOCTYPE html> &l

  • java springmvc实现验证码功能

    本文实例为大家分享了springmvc实现验证码功能展示的具体代码,供大家参考,具体内容如下 先看效果图: 思路: 首先验证码是一张图片,是一张有着随机字母.数字.图案等组成的图片,所以这图片肯定不是固定不变的,肯定是由后端随机制造出来的,前端用img的src去不断访问这个制造的方法. 第一步:前端页面编写 登录使用的是ajax方法,所以使用的是调用点击事件进行,验证码的图片放在a标签中是为了方便点击变换验证码.显示图片用的是img的src属性,因为使用的是spingmvc所以调用后台方法使用a

  • spring的@Transactional注解用法解读

    概述 事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性. Spring Framework对事务管理提供了一致的抽象,其特点如下: 为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects) 支持声明式事务管理,特别是基于注解的声明式事务管理,简单易用 提供比其他事务API如JTA更简单的编程式事务管

  • Java中Spring WebSocket详解

    首先 pom.xml <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> </parent> <dependency> <groupId>org.apache.com

  • springboot的java配置方式(实例讲解)

    1.创建User实体类. @Data public class User { private String username; private String password; private Integer age; } 2.创建UserDao用于模拟数据库交互. public class UserDao{ public List<User> queryUserList() { List<User> result = new ArrayList<User>(); //

  • Java编程实现springMVC简单登录实例

    Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面.Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块.使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts1,Struts2等. 1.新建web项目:springmvc 2.导入springmvc需要的jar包 3.配置web.xml文件(核心代码)

  • Java框架搭建之Maven、Mybatis、Spring MVC整合搭建(图文)

    本文主要介绍了Java框架搭建之Maven.Mybatis.Spring MVC整合搭建(图文),分享给大家,具体如下: SSM(Spring+SpringMVC+Mybatis),目前较为主流的企业级架构方案.标准的MVC设计模式,将整个系统划分为显示层.Controller层.Service层.Dao层四层,使用SpringMVC负责请求的转发和视图管理,Spring实现业务对象管理, MyBatis作为数据对象持久化引擎. 框架详情 Spring 是一个轻量级的Java开发框架,它是为了解

  • java使用spring实现读写分离的示例代码

    最近上线的项目中数据库数据已经临近饱和,最大的一张表数据已经接近3000W,百万数据的表也有几张,项目要求读数据(select)时间不能超过0.05秒,但实际情况已经不符合要求,explain建立索引,使用redis,ehcache缓存技术也已经满足不了要求,所以开始使用读写分离技术,可能以后数据量上亿或者更多的时候,需要再去考虑分布式数据库的部署,但目前来看,读写分离+缓存+索引+表分区+sql优化+负载均衡是可以满足亿级数据量的查询工作的,现在就一起来看一下亲测可用的使用spring实现读写

  • 通过Spring Shell 开发 Java 命令行应用

    提到 Java,大家都会想到 Java 在服务器端应用开发中的使用.实际上,Java 在命令行应用的开发中也有一席之地.在很多情况下,相对于图形用户界面来说,命令行界面响应速度快,所占用的系统资源少.在与用户进行交互的场景比较单一时,命令行界面是更好的选择.命令行界面有其固定的交互模式.通常是由用户输入一系列的参数,在执行之后把相应的结果在控制台输出.命令行应用通常需要处理输入参数的传递和验证.输出结果的格式化等任务.Spring Shell 可以帮助简化这些常见的任务,让开发人员专注于实现应用

  • 如何使用Spring Boot ApplicationRunner解析命令行中的参数

    使用Spring提供的CommandLineRunner接口可以实现了一个命令行应用程序.但是,参数/选项/参数处理却不是那么好.幸运的是,有一种更好的方法可以使用Spring Boot编写命令行应用程序,并且还可以使用ApplicationRunner接口进行解析. 在我们开始快速说明之前.在这两种情况下,无论是CommandLineRunner还是ApplicationRunner,都始终支持Spring的属性处理.我们可以像往常一样使用@Value注释注入值. 完整的工作源代码在这里 首先

  • Java命令行运行错误之找不到或无法加载主类问题的解决方法

    目录 前言: 一. 问题分析 二. 问题解决 1. 类名错误 2. 类所在位置未添加至类加载路径中 三.扩展知识 1. JDK目录结构及环境变量介绍 2. 为什么jdk1.5后不需要配置环境变量了? 总结 前言: 虽然学习Java语言约有两年多,但在最近需要使用命令行工具编译并运行Java程序时,还是报错了.花费了一些时间,解决了该问题,发现解决方法在初学Java时使用过.一则,为了避免以后再出现同样的问题而浪费不必要的时间:二则,作为使用该语言的程序员,对于该语言的一些基本问题,应该有清晰的理

  • Shell $0, $#, $*, $@, $?, $$和命令行参数的使用

    特殊变量列表 变量 含义 $0 当前脚本的文件名 $n 传递给脚本或函数的参数.n 是一个数字,表示第几个参数.例如,第一个参数是$1,第二个参数是$2. $# 传递给脚本或函数的参数个数. $* 传递给脚本或函数的所有参数. $@ 传递给脚本或函数的所有参数.被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到. $? 上个命令的退出状态,或函数的返回值. $$ 当前Shell进程ID.对于 Shell 脚本,就是这些脚本所在的进程ID. 命令行参数 运行脚本时传递给脚本的参数

  • Do All in Cmd Shell一切在命令行下完成第1/6页

    文件传输 对于溢出漏洞获得的cmd shell,最大的问题就是如何上传文件.由于蠕虫病毒流行,连接ipc$所需要的139或445端口被路由封锁.再加上WinXP系统加强了对ipc$的保护,通过ipc$及默认共享上传文件的手段基本无效了.ftp和tftp是两种可行的方法,介于其已被大家熟知,本文就不介绍了.还有三种大家熟悉的办法,作为总结我再提一下: 1,用Echo命令写ASP木马. 前提当然是目标主机上已经安装了IIS. 一般的ASP木马"体积"较大,不适合直接用echo命令写入文件,

  • Java命令行下Jar包打包小结

    jar包打包实现 jar包打包可以使用jar指令实现打包,在命令行中输入jar可以查看jar指令的内容 从最后显示的两个示例看出存在两种打包的方法,两者的区别就是是否使用自己定义的MANIFEST清单文件.第一个示例没有使用MANIFEST文件进行打包,所以最终生成的jar包中MANIFEST文件为默认文件,这种方式适用于比较简单的jar包结构,不存在其他jar包依赖以及生成的jar包不需要可执行.这种方式生成的jar包不能使用java -jar XXX.jar命令执行,因为MANIFEST文件

  • C++和Java命令行绘制心形图案

    心形线 心形线,是一个圆上的固定一点在它绕着与其相切且半径相同的另外一个圆周滚动时所形成的轨迹,因其形状像心形而得名. 心脏线亦为蚶线的一种.在曼德博集合正中间的图形便是一个心脏线.心脏线的英文名称"Cardioid"是 de Castillon 在1741年的<Philosophical Transactions of the Royal Society>发表的:意为"像心脏的". 极坐标方程 水平方向: ρ=a(1-cosθ) 或 ρ=a(1+cos

  • C#开发交互式命令行应用示例

    目录 前言 Sharprompt介绍 Demo 结论 前言 如果你开发过vue应用,应该对其交互式命令行印象深刻: 它允许你无需任何编程经验,仅需回答问题,就可完成vue应用创建. 虽然作为.NETer,大部分情况下我们不会使用命令行,但是还是希望能用C#开发出这样的交互式命令行应用,比如代码生成器. Sharprompt介绍 Sharprompt是一个基于C#的交互式命令行应用框架,具有如下特点: 多平台支持 支持常用的提示方式(普通输入/密码/选择项等) 支持基于模型的提示(预览中) 输入值

  • Linux Shell 常见的命令行格式简明总结

    复制代码 代码如下: #在后台执行 cmd 指令cmd & #命令序列. 在同一行执行多个命令cmd1 ; cmd2 #在当前 shell 中以一组的形式执行多个命令{ cmd1 ; cmd2 ; } #在子 shell 中以一组的形式执行多个命令(cmd1 ; cmd2) #管道. 以 cmd1 的执行输出作为 cmd2 的输入cmd1 | cmd2 #命令替换. 以 cmd2 的执行输出作为 cmd1 的参数cmd1 `cmd2` #POSIX 命令替换. 允许嵌套cmd1 $(cmd2)

  • 解决java 命令行乱码的问题

    虚拟机参数加上 -Dfile.encoding=GBK -Ddefault.client.encoding=GBK -Duser.language=zh -Duser.region=CN 补充:java执行cmd命令,返回结果中文乱码问题解决 public static void main(String[] args) { try { // 执行ping命令 Process process = Runtime.getRuntime().exec("cmd /c e:&dir")

随机推荐