2016-03-24 167 views
1

假設我們在服務器端有預定義的API的MBean。
我想直接使用API​​從客戶端機器調用該MBean。
如何創建簡單的JMX客戶端通過RMI獲取遠程Java對象?簡單的JMX客戶端

回答

1

使用

private CacheMBean<String, Message> messageStorage = newJmxClient( 
    CacheMBean.class, 
    "com.my.company:type=cache,name=MessageCacheImpl", 
    "service:jmx:rmi:///jndi/rmi://<host>:<port>/karaf-root", 
    "smx", 
    "smx"); 
... 
Message message = messageStorage.get(messageId); 

實施

import com.google.common.collect.ImmutableMap; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import java.io.IOException; 
import java.lang.management.ManagementFactory; 
import java.util.Map; 

import javax.management.InstanceAlreadyExistsException; 
import javax.management.JMX; 
import javax.management.MBeanServer; 
import javax.management.MBeanServerConnection; 
import javax.management.MalformedObjectNameException; 
import javax.management.ObjectInstance; 
import javax.management.ObjectName; 
import javax.management.StandardMBean; 
import javax.management.remote.JMXConnector; 
import javax.management.remote.JMXConnectorFactory; 
import javax.management.remote.JMXServiceURL; 

public final class JmxUtils { 

    private static final Logger LOG = LoggerFactory.getLogger(JmxUtils.class); 

    private JmxUtils() { 
    } 

    public static <T> T newJmxClient(Class<T> clazz, String objectName, String serviceUrl) { 
     return newJmxClient(clazz, objectName, serviceUrl, null, null); 
    } 

    public static <T> T newJmxClient(Class<T> clazz, String objectName, String serviceUrl, final String user, final String pass) { 
     try { 
      JMXServiceURL jmxServiceUrl = new JMXServiceURL(serviceUrl); 
      Map<String, ?> env = user == null ? null : ImmutableMap.of(JMXConnector.CREDENTIALS, new String[] {user, pass}); 
      JMXConnector jmxc = JMXConnectorFactory.connect(jmxServiceUrl, env); 
      MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); 
      ObjectName mbeanName = new ObjectName(objectName); 
      return JMX.newMBeanProxy(mbsc, mbeanName, clazz, true); 
     } catch (IOException | MalformedObjectNameException e) { 
      throw new RuntimeException("Can not create client for remote JMX " + serviceUrl, e); 
     } 
    } 

    /** 
    * @param objName 
    *   domain:type=value[,name=value] 
    * @param implementation 
    * @param mbeanInterface 
    * @see ObjectName 
    * @see StandardMBean 
    */ 
    public static <I> ObjectInstance registerMBean(String objName, I implementation, Class<I> mbeanInterface) { 
     int counter = 0; 
     String uniqueSuffix = ""; 
     MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
     while (true) { 
      try { 
       ObjectName name = new ObjectName(objName + uniqueSuffix); 
       StandardMBean mbean = new StandardMBean(implementation, mbeanInterface); 
       return mbs.registerMBean(mbean, name); 
      } catch (InstanceAlreadyExistsException e) { 
       LOG.trace("JMX instance exists, trying next available", e); 
       uniqueSuffix = "" + ++counter; 
      } catch (Exception e) { 
       throw new RuntimeException(e); 
      } 
     } 
    } 

    /** 
    * @param objName 
    * @see ObjectName 
    */ 
    public static void unregisterMBean(String objName) { 
     try { 
      final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
      final ObjectName name = new ObjectName(objName); 
      mbs.unregisterMBean(name); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 
}