一、简介
上一节介绍的是通过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。