整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JDK自带工具概览

我们平常对java程序进行问题排查、性能调优时,如果没有合适的工具,很多时候会事倍功半,甚至无法继续进行下去。其实,jdk自身已经提供了很多强大的工具供我们使用。本文就对这些工具做一个概览性的描述。

笔者的开发环境是:OS X EI Captian 10.11.6

JDK版本:


JAVA_HOME/bin下的工具截图如下:

  • appletviewer: 用于运行并浏览applet小程序。
  • extcheck: 扩展检测工具,主要用于检测指定jar文件与当前已安装的Java SDK扩展之间是否存在版本冲突。
  • idlj: IDL转Java编译器(IDL-to-Java Compiler),用于为指定的IDL文件生成Java绑定。IDL意即接口定义语言(Interface Definition Language)。
  • jar: jar文件管理工具,主要用于打包压缩、解压jar文件。
  • jarsigner: jar密匙签名工具。
  • java: Java运行工具,用于运行.class字节码文件或.jar文件。
  • javac: Java编译工具(Java Compiler),用于编译Java源代码文件。
  • javadoc: Java文档工具,主要用于根据Java源代码中的注释信息生成HTML格式的API帮助文档。
  • javafxpackager: JavaFX包装器,用于执行与封装或签名JavaFX应用有关的任务。JDK 8u20已经迁移此工具到javapackager。
  • javah: Java头文件工具,用于根据Java类生成C/C++头文件和源文件(主要用于JNI开发领域)。
  • javap: Java反编译工具,主要用于根据Java字节码文件反汇编为Java源代码文件。
  • javapackager: 执行针对Java应用程序和JavaFX应用程序的打包和签名的任务。包含了javafxpackager的功能。
  • jcmd: Java 命令行(Java Command),用于向正在运行的JVM发送诊断命令请求。
  • jconsole: 图形化用户界面的监测工具,主要用于监测并显示运行于Java平台上的应用程序的性能和资源占用等信息。
  • jdeps: 用于分析Java class的依赖关系.
  • jdb: Java调试工具(Java Debugger),主要用于对Java应用进行断点调试。
  • jhat: Java堆分析工具(Java Heap Analysis Tool),用于分析Java堆内存中的对象信息。
  • jinfo: Java配置信息工具(Java Configuration Information),用于打印指定Java进程、核心文件或远程调试服务器的配置信息。
  • jjs: 对Nashorn引擎的调用。Nashorn是基于Java实现一个轻量级高性能的JavaScript运行环境。
  • jmap: Java内存映射工具(Java Memory Map),主要用于打印指定Java进程、核心文件或远程调试服务器的共享对象内存映射或堆内存细节。
  • jmc: Java任务控制工具(Java Mission Control),主要用于HotSpot JVM的生产时间监测、分析、诊断。开发者可以使用jmc命令来创建JMC工具。https://docs.oracle.com/javacomponents/jmc-5-5/jmc-user-guide/toc.htm
  • jps: JVM进程状态工具(JVM Process Status Tool),用于显示目标系统上的HotSpot JVM的Java进程信息。
  • jrunscript: Java命令行脚本外壳工具(command line script shell),主要用于解释执行javascript、groovy、ruby等脚本语言。
  • jsadebugd: Java可用性代理调试守护进程(Java Serviceability Agent Debug Daemon),主要用于附加到指定的Java进程、核心文件,或充当一个调试服务器。
  • jstack: Java堆栈跟踪工具,主要用于打印指定Java进程、核心文件或远程调试服务器的Java线程的堆栈跟踪信息。
  • jstat: JVM统计监测工具(JVM Statistics Monitoring Tool),主要用于监测并显示JVM的性能统计信息,包括gc统计信息。
  • jstatd: jstatd(VM jstatd Daemon)工具是一个RMI服务器应用,用于监测HotSpot JVM的创建和终止,并提供一个接口,允许远程监测工具附加到运行于本地主机的JVM上。
  • jvisualvm: JVM监测、故障排除、分析工具,主要以图形化界面的方式提供运行于指定虚拟机的Java应用程序的详细信息。
  • keytool: 密钥和证书管理工具,主要用于密钥和证书的创建、修改、删除等。主要用于获取或缓存Kerberos协议的票据授权票据。允许用户查看本地凭据缓存和密钥表中的条目(用于Kerberos协议)。Kerberos密钥表管理工具,允许用户管理存储于本地密钥表中的主要名称和服务密钥。
  • native2ascii: 本地编码到ASCII编码的转换器(Native-to-ASCII Converter),用于”任意受支持的字符编码”和与之对应的”ASCII编码和(或)Unicode转义”之间的相互转换。
  • orbd: 对象请求代理守护进程(Object Request Broker Daemon),它使客户端能够透明地定位和调用位于CORBA环境的服务器上的持久对象。
  • pack200: JAR文件打包压缩工具,它可以利用Java类特有的结构,对普通JAR文件进行高效压缩,以便于能够更快地进行网络传输。这是微软提供的对象包装程序,用于对象安装包。
  • policytool: 策略工具,用于管理用户策略文件(.java.policy)。
  • rmic: Java RMI 编译器,为使用JRMP或IIOP协议的远程对象生成stub、skeleton、和tie类,也用于生成OMG IDL。
  • rmid: Java RMI 激活系统守护进程,rmid启动激活系统守护进程,允许在虚拟机中注册或激活对象。
  • rmiregistry: Java 远程对象注册表,用于在当前主机的指定端口上创建并启动一个远程对象注册表。
  • schemagen: XML schema生成器,用于生成XML schema文件。
  • serialver: 序列版本命令,用于生成并返回serialVersionUID。
  • servertool: Java IDL 服务器工具,用于注册、取消注册、启动和终止持久化的服务器。
  • tnameserv: Java IDL瞬时命名服务。
  • unpack200: JAR文件解压工具,将一个由pack200打包的文件解压提取为JAR文件。
  • wsgen: XML Web Service 2.0的Java API,生成用于JAX-WS Web Service的JAX-WS便携式产物。
  • wsimport: XML Web Service 2.0的Java API,主要用于根据服务端发布的wsdl文件生成客户端存根及框架
  • xjc: 主要用于根据XML schema文件生成对应的Java类。

昨天发布《JavaFX学习入门篇,想用Java写窗口应用的同学可以看看》的基础上,今天继续介绍JavaFX控件绑定及交互事件处理。昨天的文章中已经对新建立的demo.fxml指定了控制器类DemoController,这个控制器类就是今天学习中要用到的主类。在JavaFX中通过注解@FXML来绑定fxml文件中的控件或控件的交互事件。前面已经在场景中添加了菜单组件,菜单组件中默认已经添加了三个菜单,且都有一个子菜单,目前点击任何一个菜单都不会有响应。

下面介绍如何响应菜单的点击事件,首先在Netbeans中双击demo.fxml,然后在JavaFX Scene Builder中找到场景中的菜单组件。在左侧Document节点下Hierarchy中展开菜单,点击选中要添加事件监听的MenuItem,然后在右侧Inspector中展开Code节点,在On Action中输入该菜单点击时回调函数的名称,这里函数名称为closeAction,输入完成按回车并Ctrl+S保存修改。具体操作如下图所示:

为MenuItem设置Action回调函数

完成以上操作之后回到Netbeans中,在DemoController中添加刚才的函数,注意需要添加@FXML注解,函数参数可以为空也可以是javafx.event.ActionEvent,参数可根据需要添加,但不是什么参数都可以。本例中函数如下:

@FXML

private void closeAction(ActionEvent event){//函数名必需与fxml中的一致

System.out.println("invoke close menu action");

}

到此菜单事件的绑定已经完成了,同样的道理其他任何交互控件的事件绑定都类似。每个控件可监听的事件都不太一样,例如输入框可以监听鼠标事件、键盘事件、触屏事件等等,交互事件监听都可以参考此操作。

接下来继续介绍控件的绑定,我们开发一个桌面应用表单元素是必不可少的。我们需要知道用户输入了什么内容,或者选择了哪个值。这些就需要用到控件的绑定,控件绑定操作也很简单,细心的读者或许已经发现前面的截图中On Action之前有个fx:id,没错这里就是通过这个id进行控件绑定。我们将一个输入框(TextField)拖放到场景中,并指定fx:id为input,为了触发显示我们输入的值,再监听这个输入框的键盘按键释放事件On Key Released,函数名为keyRelease,具体设置如下图:

添加输入框并设置ID和key release事件监听

编辑完场景之后保存,回到Netbeans中在DemoController中添加一个TextField变量及一个方法keyRelease,注意变量及方法都需要添加@FXML注解,此处keyRelease的参数可以为空或javafx.scene.input.KeyEvent,其他参数会抛出IllegalArgumentException: argument type mismatch异常。添加代码如下:

@FXML

private TextField input;//变量名必需与fxml文件中的fx:id值一致

@FXML

private void keyRelease(KeyEvent event){//函数名必需与fxml中的一致

System.out.println(input.getText());

}

到些控件的绑定也介绍完了,此时可以将项目运行起来看看效果。好奇的小伙伴或许对场景中的输入框文字“这是输入框”存在疑问,是默认值吗?这个是JavaFX的Prompt Text等同于HTML中的placeholder,即输入提示文字,当该控件得到光标时提示文字会消失。具体设置在右侧Inspector中的Properties页面中,本例源码已上传到作者github:https://github.com/ajtdnyy/JavaFXDemo。Prompt Text如下图所示:

设置输入框的Prompt Text

ebView2 是越来越香了。

WebView2 不但是 Win11 自带的系统组件,Win10 也已经自动推送安装。即使是少量没有安装 WebView2 的系统 —— 使用 aardio 中的 web.view 也会自动安装( 不需要写任何代码 )。

我用 WebView2 开发了很多项目,不得不说 WebView2 稳定可靠、性能强悍,接口简洁,是真的让人省心。

htmx.js

这里介绍一个适合用于 WebView2 的极简前端组件 htmx.js ,这个组件最大的特色就是简单,一学就会,也很容易理解。

我们正常浏览一个网页的过程是在浏览器里输入网址,向 HTTP 服务器发送请求。然后服务器返回 HTML 代码,浏览器显示页面。

但是 htmx.js 脑洞大开,让网页上的每一个 HTML 节点都可以向服务器发送请求并获取 HTML,并实时更新页面上指定的节点。而且不需要写任何 JavaScript 代码。

起步

首先我们打开 aardio ,创建 WebView2 工程并选择 htmx.js 模板:

生成的工程如下:

点『运行』可直接测试效果,点『发布』可生成独立 EXE 文件 。

在工程管理器中右键点『网页』弹出菜单,然后点『用外部编辑器打开』,如果安装了 VS Code 会使用 VS Code 打开网页目录。

在 VS Code 中点击并打开 index.html 源码:

htmx.js 基础

打开 index.html ,先看最简单的 htmx.js 示例:

<button hx-get="/api/index.aardio" 
    hx-swap="innerHTML" 
    hx-trigger="click" 
    hx-target="#info-div"  >
    点这里发送 GET 请求
</button><br>

<div id="info-div"></div>

注意看凡是 "hx-" 前缀的属性都是用于 htmx.js 。

hx-trigger 用于指定在什么事件发生时触发 HTTP 请求,例如:

hx-trigger="click" 

表示在 click 单击事件发生时触发请求。

hx-trigger 可使用标准网页事件名,常用事件如下:

  • load - 网页元素首次加载时触发请求
  • click - 单击时触发请求这是除表单,表单控件之外所有元素的默认事件
  • change - 控件值改变时触发请求。input,textarea,select 等控件的默认事件
  • submit - 提交表单时触发请求。表单的默认事件
  • keydown - 按键时触发请求
  • keyup - 放开按键时触发请求
  • mouseenter - 鼠标进入时触发请求
  • mouseleave - 鼠标离开时触发请求
  • every 时间 - 定时触发请求,例如 hx-trgger = "every 1s" 指定每隔 1 秒发送一次请求。

事件名后面还可以添加修饰器,例如修饰器 once 表示只允许触发一次 :

hx-trigger="click once" 

其他事件修饰器:

  • changed - 只有在元素的值更改时发出请求
  • delay:延时 - 在指定的延时后发出请求,例如 hx-trgger = "load delay:1s" 指定元素加载后延迟 1 秒发送请求。如果服务端不断地返回相同 HTML 并替换节点自身,也可以实现轮询的效果( aardio 后端可以控制何时停止轮询 )。
  • throttle:延时 - 节流,避免在指定时间内重复请求
  • from:CSS选择器 - 监听指定元素上的事件。

下面的 HTML 使用了多个事件修饰器:

<input type="text" 
  hx-trigger="keyup changed delay:500ms"
  hx-post="/api/index.aardio" >

这表示在按键放开( keyup ),文本框的内容发生改变( changed )时触发,并且延时 500 毫秒再发送请求。

hx-get 则指定要请求的是哪个后端页面,例如:

hx-get="/api/index.aardio" 

表示事件触发时,请求 "/api/index.aardio" 这个页面。因为 aardio 在启动 SPA 应用时自动指定了后端根目录为 "/web",所以实际请求的是 "/web/api/aardio" 。

而 hx-swap 则指定要将返回的 HTML 写入到哪里,"innerHTML" 指定是更新网页节点内部 HTML,"outerHTML" 指定替换目标网页节点的全部 HTML ,其他还有 "afterbegin" , "beforebegin" , "beforeend" , "afterend" , "none" 。这些看名字就知道是什么作用,就不解释了。

hx-target 属性用 CSS 选择器指定要写入的网页节点,例如:

 hx-target="#info-div" 

指定服务器返回的 HTML 写入 id 为 "info-div" 的节点。如果省略 hx-target 属性表示写入目标是当前节点自身。

hxmx.js 在更新 HTML 时,如果发现新旧 html 中有 id 相同的元素会进行优化并平滑显示。

看到这里,htmx.js 您已经会用了。

虽然 htmx.js 文档里有更多花式用法,但一般可能用不上。有些事搞太复杂了也不一定是好事。

htmx.js + aardio 后端

aardio 提供了嵌入式 HTTP 服务器,可以直接使用 aardio 代码写网页,支持与 PHP 类似的模板语法。

aardio 的模板语法很简单,aardio 代码写在 <? ?> 内部,而 HTML 代码写在 <? ?> 外部就可以了。实际上 <? ?>外部的代码被转换为了 aardio 中 print 函数的参数。

例如服务端有下面的 aardio 代码:

<span>abc</span>
<?
  response.write("123")
?>

运行后会自动转换为纯 aardio 代码如下:

print("<span>abc</span>");
response.write("123");

在 HTTP 后端中,print 函数实际上就是指向用于向 HTTP 客户端输出数据的 response.write() 函数。

在 HTTP 后端有两个最常用的对象,request 对象包含了所有 HTTP 请求信息,而 response 对象为 HTTP 响应对象,用于向客户端发送数据。

打开 aardio 自带「工具 > 库函数文档」,点击 fastcgi.client 的文档可以查看 request, response 对象的所有属性与方法。aardio 中的所有 HTTP 服务端实现都统一兼容 fastcgi.client 文档规定的 request, response 用法。

也可以参考 aardio 开始页的 《 aardio 网站开发、FastCGI开发入门教程 》。至于 aardio 模板语法,请参考 《 aardio 语法与使用手册 > aardio 语言 > 模板语法 》

aardio 的模板语法不仅仅可以用于写 HTTP 后端,也不仅仅是可以用于输出 HTML,实际上可以用于生成任何字符串。aardio 中的很多功能都支持这种模板语法,例如运行时编译 C# 代码就支持用 aardio 模板语法生成 C# 代码。另外 aardio 提供 string.loadcode() 函数可以直接解析 aardio 模板并返回字符串。

htmx.js指示动画,aardio 后端线程

这里要注意,上面范例工程默认导入的 HTTP 服务器是:

wsock.tcp.simpleHttpServer;

这是一个多线程的 HTTP 服务端,每次被请求执行的 aardio 代码都是在后台线程中运行。aardio 多线程开发要注意的是每个线程都运行在独立的环境,全局变量是相互隔离的,这个限制实际上让 aardio 的多线程开发更简洁,坑更少,具体请参考 aardio 自带「范例程序 > aardio 语言 > 多线程」。

如果改为 wsock.tcp.asynHttpServer 则是单线程异步的 HTTP 服务器。

下面我们仍然使用默认的 simpleHttpServer 。多线程的好处是耗时操作不会卡界面。后端在进行耗时操作时,网页前端通常需要显示一个动画,htmx.js 做这事就很简单。

我们只要简单的修改一下前面讲过的网页代码如下:

<button hx-get="/api/index.aardio" 
    hx-indicator="#indicator" >
    点这里发送 GET 请求
</button><br>

<img id="indicator" 
    class="htmx-indicator" 
    src="/images/loading.gif"/>

主要是增加了 hx-indicator 属性,该属性的值用一个 CSS 选择器指定了发送 HTTP 请求时要显示的 HTML 元素,这里指定的是 id 为 "indicator" 的元素。

实际上我们可以自定义这个请求动画的样式,我们打开样式文件 index.css 添加下面的样式:

.htmx-indicator{
    display:none;
}
.htmx-request.htmx-indicator{
    display:inline;
}

在发送请求时,网页上被设定的指示元素会自动添加 CSS 类 "htmx-request",HTTP 请求结束会移除该类。

然后我们打开对应的 aardio 后端代码 /web/api/index.aardio ,输入以下代码:

<span>
<?

if( request.method == "GET"){
    
    /*
    这是多线程后端,
    这里等 2 秒,网页会显示加载动画
    */
    sleep(2000);
    
    response.write( time() )    
} 
?></span>


上面的代码的作用是:如果收到 GET 请求,线程就休眠 2 秒以模拟耗时操作。然后输出当前时间。

我们运行一下看看效果:

请求参数

htmx.js 提交请求的节点如果是一个表单控件,只要指定 name 属性 —— 就会自动以该名字发送请求参数,参数值就是控件的值。

如果提交请求的节点是表单,则 HTTP 请求参数为表单内所有控件的值。

也可以在节点的 hx-vals 属性中用一个 JSON 对象指定请求参数,例如网页这样写:

<button hx-get="/api/index.aardio" 
    hx-vals='{"myVal": "值"}'>
    点这里发送 GET 请求
</button><br>

aardio 后端就可以使用:

request.get["myval"]

取到 HTTP 请求参数 myval 的值。

如果使用 POST 发送请求,例如:

<button hx-post="/api/index.aardio" 
    hx-vals='{"myVal": "值"}'>
    点这里发送 GET 请求
</button><br>

那么 aardio 后端可以使用

request.post["myval"]

取到 HTTP 请求参数 myval 的值。

在 aardio 后端使用:

request.query("myval")

可以取到 GET 或 POST 发送的 myval 参数值。

hx-vals 还可以通过加上 javascript: 或者 js: 前缀后使用 JS 对象返回请求参数,例如:

<button hx-get="/api/index.aardio"  
    hx-vals='javascript:{myVal: "值"}'    >
    点这里发送 GET 请求
</button> 

web.form 也玩 htmx.js

有趣的是 web.form 也可以支持 htmx.js 。

web.form 是基于系统自带的 IE 内核控件,注意系统虽然删除了 IE 浏览器,但 IE 控件属于系统组件,Windows 有说明该控件不会被移除。IE 控件的好处是从 XP 到 Win11 所有操作系统都自带。

而且 IE 控件很轻量,与本地程序交互的接口也非常方便。Win10 ,Win11 自带的是 IE11 内核,写写一般的网页还是很好用的。至于 Win7 —— 因为只有极低的份额,一般软件不用考虑。

htmx.js 最后一个支持 IE 11 的版本是 1.6.1 ,这个足够用了。前面说过我们需要的只是局部请求刷新的功能,其他功能我们用不上,所以追新无意义。

首先我们打开 aardio 工程向导,选择「 Web 界面 > Web Form 」然后创建工程即可,新版工程模板默认就是使用 htmx.js 。

其他 HTML 代码写法与前面介绍的 WebView2 基本一样。不过 web.form 本就支持 EXE 内嵌资源文件,所以默认并不会启动 HTTP 服务器,需要多写几句代码。

打开工程的 webPage.aardio 源码:

可以看到源码中是如下启动 HTTP 服务器的:

import web.form;
var wb  = web.form(winform); 

//多线程后端
import wsock.tcp.simpleHttpServer;
wsock.tcp.simpleHttpServer.documentBase = "\web"
var indexUrl = wsock.tcp.simpleHttpServer.startUrl("\index.html")
 
wb.go(indexUrl);

我并没有把这几句代码封装到 wb.go() 函数中。

有些新手总以为代码越少越好,其实并非如此,有时候多写几句更容易看清楚代码的思路,更容易理解我们正在使用的技术。

下面我们看下 web.form + htmx.js 范例的运行效果:

上面示例程序的主窗口是使用 win.ui.tabs 做的,只有其中一个标签页用到了网页。

其实一般桌面软件的界面并不是一定要全部使用网页实现。有时候我们将界面中适合用网页呈现的部分用网页做,可能会更好。

我们在使用任何技术时,都要考虑一下适不适合。没有一样技术能适合做所有的事,多个选择总是好事。


上一篇:div并排显示
下一篇:9.HTML链接标签