之前学了如何创建JMX技术的MBeans和MXBeans,并用JMX代理注册它们。可是,之前所用的都是已经存在的JMX客户端,JConsole。这里将演示如何创建自己的客户端。
一个普通的JMX客户端的例子,Cilent存在于jmx_example.zip中。JMX客户端与同样的MBean和MXbean,JMX 代理交互。由于Client类的大小,它将在块中检查。
导入JMX远程API类
创建从JMX客户端到运行在远程的JMX代理的连接,你需要使用javax.management.remote类。
package com.example; ... import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; public class Client { ...
这个Client创建JMXConntor实例,还需要一个JMXConnectorFactory和一个JMXServiceURL。
创建通知监听器
JMX客户端需要一个通知处理者,来监听和处理任何通知,这些通知由在JMX代理的MBean服务器上注册的MBeans发送。JMX客户端通知处理者是一个NotificationListener接口的实例,如下所示:
... public static class ClientListener implements NotificationListener { public void handleNotification(Notification notification, Object handback) { echo("\nReceived notification:"); echo("\tClassName: " + notification.getClass().getName()); echo("\tSource: " + notification.getSource()); echo("\tType: " + notification.getType()); echo("\tMessage: " + notification.getMessage()); if (notification instanceof AttributeChangeNotification) { AttributeChangeNotification acn = (AttributeChangeNotification) notification; echo("\tAttributeName: " + acn.getAttributeName()); echo("\tAttributeType: " + acn.getAttributeType()); echo("\tNewValue: " + acn.getNewValue()); echo("\tOldValue: " + acn.getOldValue()); } } } ...
通知监听器确定任何通知的来源,监听器接受和重新获取存在通知中的信息。。稍后根据接受的通知类型随着通知的信息执行不同操作,在这种情况下,当监听器接受到AttributeChangeNotification类型的通知时,t它将获取MBean已经改变的属性的名字和类型,还有老的和新的值,通过调用AttributeChangeNotification
的方法getAttributeName
,getAttributeType
, getNewValue
和getOldValue
.
在后面的代码中创建了新的ClientListener实例:
ClientListener listener = new ClientListener();
创建RMI连接器客户端
Client类创建一个RMI连接器客户端,被配置为连接一个RMI连接器服务,当你开启JMX代理的时候,启动Main。这样将使JMX客户端和JMX代理交互,如果它们运行在同一台机器上。
... public static void main(String[] args) throws Exception { echo("\nCreate an RMI connector client and " + "connect it to the RMI connector server"); JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi"); JMXConnector jmxc = JMXConnectorFactory.connect(url, null); ...
Client 定义了一个JMXServiceURL命名为url,表示了连接器服务的位置。URL允许连接客户端重新获取RMI连接服务的子jmxrmi,来自运行在本地主机端口号为9999的RMI注册表上,并连接RMI连接服务。
随着RMI注册表的定义,连接客户端被创建了。即lmxc,是接口JMXConnector的一个实例,由JMXFactory的connect方法创建,这个方法需要传递一个url和一个空的环境映射做为参数。
连接到远程的MBean服务
随着RMI连接到位,JMX客户端必须连接远程的MBean服务。这样它才可以与注册在远程JMX代理上的不同的MBeans交互。
... MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); ...
mbsc是MBeanServerConnection的实例,通过JMXConnector
的实例jmxc调用getMBeanServerConnection()
方法创建。
连接客户端现在连接到MBean服务器上,由JMX代理创建,能注册MBeans并能执行操作,在两端的连接上。
... echo("\nDomains:"); String domains[] = mbsc.getDomains(); Arrays.sort(domains); for (String domain : domains) { echo("\tDomain = " + domain); } ... echo("\nMBeanServer default domain = " + mbsc.getDefaultDomain()); echo("\nMBean count = " + mbsc.getMBeanCount()); echo("\nQuery MBeanServer MBeans:"); Set<ObjectName> names = new TreeSet<ObjectName>(mbsc.queryNames(null, null)); for (ObjectName name : names) { echo("\tObjectName = " + name); } ...
客户端调用了MBeanServerConnection
类的不同方法来获取领域,在领域中不同的Mbeans在操作注册在MBean服务上的大量MBeans和它发现的每个Mbean的对象名。
Performing Operations on Remote MBeans via Proxies
通过代理在远程Mbeans上执行操作
客户端访问MBean服务上的Hello Mbean,通过Mbean服务连接,由一个Mbean代理创建。MBean代理位于客户端,模拟了远程MBean。
... ObjectName mbeanName = new ObjectName("com.example:type=Hello"); HelloMBean mbeanProxy = JMX.newMBeanProxy(mbsc, mbeanName, HelloMBean.class, true); echo("\nAdd notification listener..."); mbsc.addNotificationListener(mbeanName, listener, null, null); echo("\nCacheSize = " + mbeanProxy.getCacheSize()); mbeanProxy.setCacheSize(150); echo("\nWaiting for notification..."); sleep(2000); echo("\nCacheSize = " + mbeanProxy.getCacheSize()); echo("\nInvoke sayHello() in Hello MBean..."); mbeanProxy.sayHello(); echo("\nInvoke add(2, 3) in Hello MBean..."); echo("\nadd(2, 3) = " + mbeanProxy.add(2, 3)); waitForEnterPressed(); ...
MBean代理允许你访问一个MBean,通过一个Java接口,允许你调用代理而不是写长长的代码访问一个远程MBean。Hello的MBean代理由调用Javax.management.JMX类的newMBeanProxy
()方法在这里创建,传递了一下参数,MBean的MBeanServerConnection
,对象名,MBean接口的类名和布尔值true,表示这个代理必须与NotificationBroadcast类的行为一样。JMX客户端可以现在可以执行由Hello
定义的操作,就好像是在本地注册的MBean的操作一样。JMX客户端也增加了一个配置监听器并改变了MBean的CacheSize
属性,使他发送一个通知。
Performing Operations on Remote MXBeans via Proxies
通过代理在远程Mbeans上执行操作你可以用创建MBean代理的方式创建MBeans代理
... ObjectName mxbeanName = new ObjectName ("com.example:type=QueueSampler"); QueueSamplerMXBean mxbeanProxy = JMX.newMXBeanProxy(mbsc, mxbeanName, QueueSamplerMXBean.class); QueueSample queue1 = mxbeanProxy.getQueueSample(); echo("\nQueueSample.Date = " + queue1.getDate()); echo("QueueSample.Head = " + queue1.getHead()); echo("QueueSample.Size = " + queue1.getSize()); echo("\nInvoke clearQueue() in QueueSampler MXBean..."); mxbeanProxy.clearQueue(); QueueSample queue2 = mxbeanProxy.getQueueSample(); echo("\nQueueSample.Date = " + queue2.getDate()); echo("QueueSample.Head = " + queue2.getHead()); echo("QueueSample.Size = " + queue2.getSize()); ...如上所示,为创建一个MBean代理,你所需要做的是调用
newMBeanProxy
实例。MXBean代理
mxbeanProxy
允许客户端调用
QueueSample
MXBean的操作就如注册在本地的MXBean的操作。
Closing the Connection
关闭连接
只要JMX客户端获取了它所需的所有信息并执行了远程JMX代理MBean服务上的所有请求的MBeans的操作,连接必须关闭。
jmxc.close();
通过调用JMXConnector.close()关闭。
To Run the Custom JMX Client Example
运行JMX客户端例子这个例子需要JAVA SE6版本。用一个通用JMX客户端Client监控MainJMX代理,按照以下步骤:
如果上一章一样