一、简介
上一节介绍的是通过Web方式访问和操控MBean,本节所要介绍的是通过RMI方式,实现客户端与服务器端的通信,即客户端获取MBeanServerConnection,然后对服务器端被注册的MBean进行操作。
二、代码实例
2.1 mserver代码
package com.muyu.jmx; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import javax.management.remote.JMXAuthenticator; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXPrincipal; import javax.management.remote.JMXServiceURL; import javax.security.auth.Subject; public class MServer { public static void main(String[] args) { MBeanServer server = MBeanServerFactory.createMBeanServer(); ObjectName configName; try { configName = new ObjectName("LuisFigo:name=config"); Config config = new Config(); server.registerMBean(config, configName); //注册RMI端口号 Registry registry = LocateRegistry.createRegistry(9999); JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/mserver"); //权限验证 Map env = new HashMap(); env.put(JMXConnectorServer.AUTHENTICATOR, new JMXAuthenticator() { public Subject authenticate(Object credentials) { String[] sCredentials = (String[]) credentials; String userName = sCredentials[0]; String password = sCredentials[1]; if ("admin".equals(userName) && "admin".equals(password)) { Set principals = new HashSet(); principals.add(new JMXPrincipal(userName)); return new Subject(true, principals, Collections.EMPTY_SET, Collections.EMPTY_SET); } else throw new SecurityException("Authentication failed! "); } } ); JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, server); cs.start(); System.out.println("rmi start....."); } catch (Exception e) { e.printStackTrace(); } } }
2.2 mclient代码
package com.muyu.jmx; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.management.Attribute; import javax.management.MBeanServerConnection; import javax.management.MBeanServerInvocationHandler; import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; public class MClient { public static void main(String[] args) { try { JMXServiceURL url = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://localhost:9999/mserver"); Map env = new HashMap(); env.put(JMXConnector.CREDENTIALS, new String[]{"admin", "admin"}); JMXConnector jmxc = JMXConnectorFactory.connect(url, env); MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); Set names = mbsc.queryNames(null, null); for (Iterator i = names.iterator(); i.hasNext();) { System.out.println("\tObjectName = " + (ObjectName) i.next()); } ObjectName stdMBeanName = new ObjectName("LuisFigo:name=config"); mbsc.invoke(stdMBeanName, "printConfigLocation", new String[]{"helloworld"}, new String[]{"java.lang.String"}); mbsc.setAttribute(stdMBeanName, new Attribute("ConfigLocation", "LuisFigo, this is a new configLocation")); ConfigMBean proxy = (ConfigMBean) MBeanServerInvocationHandler .newProxyInstance(mbsc, stdMBeanName, ConfigMBean.class, false); System.out.println(proxy.getConfigLocation()); proxy.setConfigLocation("Beckham"); System.out.println(proxy.getConfigLocation()); proxy.printConfigLocation(); jmxc.close(); } catch (Exception e) { e.printStackTrace(); } } }
说明
运行MServer,其中LocateRegistry.createRegistry(9999)这段代码是为了注册RMI端口,下面JMXServiceURL会用 到9999这个端口。Env用于控制新连接器服务器的行为的一组属性,上面的部分代码是为了实现权限验证。如果客户端不输入正确的用户名和密码,则获取MServer服务端的连接。执行MClient,会发现一些有意思的现象,执行mbsc.invoke(stdMBeanName, "printConfigLocation", new String[]{"helloworld"}, new String[]{"java.lang.String"});这段代码时,其实是MServer端的MBean在执行printConfigLocation方法。假如MServer部署在一个JVM上,而MClient部署在另一个不同的JVM上,会得到同样的效果。不难看出利用远程调用方法也可以轻松实现分布式处理。
三、 总结
使用JMX框架,可以用SUN自带的web方式管理MBean,也可以通过RMI接口自己实现对服务端MBean进行操作。下一节还会详细介绍Spring怎样集成MX4J实现JMX编程,MX4J自己实现了一套比较实用的界面来管理MBean。