这一部分是我也看了好久,才决定用Java的Robot + User32来实现。Robot是java.awt下的一个类,该类用于为测试自动化、自运行演示程序和其他需要控制鼠标和键盘的应用程序生成本机系统输入事件,因此可试用该类进行模拟鼠标键盘操作。User32是JNA下的一个类,该类提供对W32 USER32库的访问,也就是说可以试用该类来进行windows的一些操作,而这里我用来选择对话窗口。
其实我这里用到的awt和JNA都是它们其中的一个小功能点而已,还有很多其他的功能可以去学习使用。下面放一下我发送消息的方法。
/**
* @Function: SendMessageService.java
* @Description: 向指定QQ群发送消息
* @param: communityName 为必填的非空参数,用于发送消息。
* @param: message 要发送的消息内容。
* @param: communityId 为非必填参数,可为空,用于记录日志。
* @author: JuFF_白羽
* @date: 2018年7月15日 上午2:36:11
*/
private void sendQQMessage(String message, Long communityId, String communityName) throws AWTException {
WinDef.HWND hwnd = User32.INSTANCE.FindWindow(null, communityName); // 第一个参数是Windows窗体的窗体类,第二个参数是窗体的标题。不熟悉windows编程的需要先找一些Windows窗体数据结构的知识来看看,还有windows消息循环处理,其他的东西不用看太多。
if (hwnd == null) {
LOGGER.info("找不到[{}]聊天窗口", communityId);
} else {
Robot robot = new Robot();
boolean showWindow = User32.INSTANCE.ShowWindow(hwnd, 9); // SW_RESTORE
if (showWindow) {
boolean setForegroundWindow = User32.INSTANCE.SetForegroundWindow(hwnd);
if (setForegroundWindow) {
robot.delay(3000);// 等3秒
KeyboardUtil.keyPressString(robot, message);// 输入内容
KeyboardUtil.keyPress(robot, KeyEvent.VK_ENTER);// 按下回车
LOGGER.info("新消息已发送到[{}]聊天窗口", communityId);
} else {
LOGGER.info("设置前景窗口失败");
}
} else {
LOGGER.info("显示窗口失败");
}
}
}
从上面的代码来看,并没有什么复杂,而其实里面Robot和User32的调用过程都各有一个坑,先从调用Robot发现的问题说起好了。在JUnit Test运行时,Robot能正常实例化,然后模拟键盘按键和鼠标点击等操作,但打包成jar后部署到服务器上时,运行到实例化Robot对象时却报了 java.awt.AWTException: headless environment 这个异常。而这个异常我查了百度,发现很多都没说清楚具体原因,于是又去查了谷歌,相关解释见Java SE使用无头模式<