1、簡介html
Model MBean是基於DynamicMBean的更實用的MBean,若是編寫被管理的類爲標準MBean,咱們必須爲它們實現一套以MBean爲後綴名的接口,這樣使代碼的耦合度增高。而基於Model Mbean,咱們能夠用配置文件等動態的方式來管理類,被管理的類能夠是普通的類,這樣也下降了系統的耦合性。java
2、準備工做數組
一、爲了Web方式管理MBean,咱們引入jmxtools.jar瀏覽器
3、代碼實例函數
3.1 configmodel代碼ui
package com.muyu.jmx; public class ConfigModel { private String configLocation; public String getConfigLocation() { return configLocation; } public void printConfigLocation() { System.out.println(configLocation); } public void printConfigLocation(String i_ConfigLocation) { System.out.println(i_ConfigLocation); } public void setConfigLocation(String configLocation) { this.configLocation = configLocation; } }
3.2 configagent代碼this
package com.muyu.jmx; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import javax.management.modelmbean.RequiredModelMBean; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; import com.sun.jdmk.comm.HtmlAdaptorServer; public class ConfigAgent { public static void main(String[] args) throws Exception { MBeanServer server = MBeanServerFactory.createMBeanServer(); ObjectName configName = new ObjectName("LuisFigo:name=configModel"); RequiredModelMBean config = ModelMBean.createModelMBean(); server.registerMBean(config, configName); ObjectName adapterName = new ObjectName("HelloAgent:name=htmladapter,port=8000"); //經過Web來管理MBean HtmlAdaptorServer adapter = new HtmlAdaptorServer(); adapter.setPort(8000); server.registerMBean(adapter, adapterName); adapter.start(); System.out.println("adapter start....."); //經過RMI方式來管理MBean Registry registry = LocateRegistry.createRegistry(9999); JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/mserver"); JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server); cs.start(); System.out.println("rmi start....."); } }
3.3 modelmbean代碼url
package com.muyu.jmx; import javax.management.Attribute; import javax.management.AttributeNotFoundException; import javax.management.Descriptor; import javax.management.InstanceNotFoundException; import javax.management.InvalidAttributeValueException; import javax.management.MBeanException; import javax.management.MBeanParameterInfo; import javax.management.ReflectionException; import javax.management.RuntimeOperationsException; import javax.management.modelmbean.DescriptorSupport; import javax.management.modelmbean.InvalidTargetObjectTypeException; import javax.management.modelmbean.ModelMBeanAttributeInfo; import javax.management.modelmbean.ModelMBeanInfo; import javax.management.modelmbean.ModelMBeanInfoSupport; import javax.management.modelmbean.ModelMBeanOperationInfo; import javax.management.modelmbean.RequiredModelMBean; public class ModelMBean { private static final boolean READABLE = true; private static final boolean WRITABLE = true; private static final boolean IS = true; private final static String STRING_CLASS = "java.lang.String"; public static RequiredModelMBean createModelMBean() throws RuntimeOperationsException, MBeanException, InstanceNotFoundException, InvalidTargetObjectTypeException, AttributeNotFoundException, InvalidAttributeValueException, ReflectionException { RequiredModelMBean modelMBean = null; modelMBean = new RequiredModelMBean(); modelMBean.setManagedResource(new ConfigModel(), "ObjectReference"); ModelMBeanInfo info = createModelMBeanInfo(); modelMBean.setModelMBeanInfo(info); modelMBean.setAttribute(new Attribute("ConfigLocation", "test initial")); return modelMBean; } public static ModelMBeanInfo createModelMBeanInfo() { Descriptor portAttrDesc = new DescriptorSupport(); portAttrDesc.setField("name", "ConfigLocation"); portAttrDesc.setField("descriptorType", "attribute"); portAttrDesc.setField("displayName", "ConfigLocation"); portAttrDesc.setField("getMethod", "getConfigLocation"); portAttrDesc.setField("setMethod", "setConfigLocation"); //屬性 ModelMBeanAttributeInfo nameAttrInfo = new ModelMBeanAttributeInfo("ConfigLocation", // 屬性名 STRING_CLASS, //屬性類型 "luisfigo location", // 描述文字 READABLE, WRITABLE, !IS, // 讀寫 portAttrDesc ); //方法 Descriptor getStateDesc = new DescriptorSupport(new String[] { "name=getConfigLocation", "descriptorType=operation", "class=com.muyu.jmx.ConfigModel", "role=operation" }); // 構造 setConfigLocation操做描述符信息 Descriptor setStateDesc = new DescriptorSupport(new String[] { "name=setConfigLocation", "descriptorType=operation", "class=com.muyu.jmx.ConfigModel", "role=operation" }); ModelMBeanOperationInfo getConfigLocation = new ModelMBeanOperationInfo( "getConfigLocation", "get configLocation attribute", null, "java.lang.String", ModelMBeanOperationInfo.ACTION, getStateDesc ); MBeanParameterInfo[] setStateParms = new MBeanParameterInfo[] { (new MBeanParameterInfo( "configLocation_para", "java.lang.String", "new configLocation value")) }; ModelMBeanOperationInfo setConfigLocation = new ModelMBeanOperationInfo( "setConfigLocation", "set configLocation attribute", setStateParms, "void", ModelMBeanOperationInfo.ACTION, setStateDesc ); ModelMBeanOperationInfo printConfig = new ModelMBeanOperationInfo("printConfigLocation", "控制檯輸出configLocation信息", null, "void", ModelMBeanOperationInfo.INFO, null); ModelMBeanOperationInfo printConfig_1 = null; MBeanParameterInfo[] params = new MBeanParameterInfo[1]; params[0] = new MBeanParameterInfo("i_ConfigLocation", STRING_CLASS, "Hello , I am LuisFigo"); printConfig_1 = new ModelMBeanOperationInfo("printConfigLocation", "控制檯輸出configLocation_para信息", params, "void", ModelMBeanOperationInfo.INFO, null); ModelMBeanInfo mbeanInfo = new ModelMBeanInfoSupport(// RequiredModelMBean.class.getName(), // MBean類 "ModelMBeanInfoSupport Dynamic MBean", // 描述文字 new ModelMBeanAttributeInfo[] { // 全部的屬性信息(數組) nameAttrInfo },//只有一個屬性 null, // 全部的構造函數信息 new ModelMBeanOperationInfo[] { // 全部的操做信息(數組) getConfigLocation, setConfigLocation, printConfig, printConfig_1},// null, null ); return mbeanInfo; } }
3.4 configclient代碼code
package com.muyu.jmx; import java.io.IOException; import java.util.Iterator; import java.util.Set; import javax.management.Attribute; import javax.management.AttributeNotFoundException; import javax.management.InstanceNotFoundException; import javax.management.InvalidAttributeValueException; import javax.management.MBeanException; import javax.management.MBeanServerConnection; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.management.ReflectionException; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; public class ConfigClient { public static void main(String[] args) throws IOException, MalformedObjectNameException, NullPointerException, InstanceNotFoundException, MBeanException, ReflectionException, AttributeNotFoundException, InvalidAttributeValueException { JMXServiceURL url = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://localhost:9999/mserver"); JMXConnector jmxc = JMXConnectorFactory.connect(url, null); 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=configModel"); mbsc.invoke(stdMBeanName, "printConfigLocation", new String[]{"helloworld"}, new String[]{"java.lang.String"}); mbsc.setAttribute(stdMBeanName, new Attribute("ConfigLocation", "LuisFigo, this is a new configLocation")); mbsc.invoke(stdMBeanName, "printConfigLocation", null, null); jmxc.close(); } }
說明:orm
運行ConfigAgent後,在瀏覽器裏輸入地址http://localhost:8000/,點擊name=configModel後進行configModel MBean管理頁面,能夠對configMBean進行一些操做,同第二節介紹的標準MBean很類似。運行ConfigClient能夠發現,經過RMI能夠管理ConfigAgent中註冊的MBean。
4、總結
動態ModelMBean實現了被管理類與JMX的解耦,在ModelMBean類裏咱們能夠暴露一些操做和屬性。而客戶端看起來像什麼事都沒有發生同樣。若是採用JMX來管理系統的話,咱們只須要提供一個ModelMBean這樣一個管理類就能夠,而不須要破壞原來的系統代碼,真正實現了系統與JMX的解耦。