JMX一步步來(lái)_第1頁(yè)
JMX一步步來(lái)_第2頁(yè)
JMX一步步來(lái)_第3頁(yè)
JMX一步步來(lái)_第4頁(yè)
JMX一步步來(lái)_第5頁(yè)
已閱讀5頁(yè),還剩26頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

JMX 一步步來(lái) 1、 JMX的 Hello World 一、 JMX 簡(jiǎn)介 什么是 JMX?在一篇網(wǎng)文中是這樣說(shuō)的: JMX(Java Management Extensions)是一個(gè)為應(yīng)用程序植入管理功能的框架。 JMX 是一套標(biāo)準(zhǔn)的代理和服務(wù),實(shí)際上,用戶(hù)可以在任何 Java 應(yīng)用程序中使用這些代理和服務(wù)實(shí)現(xiàn)管理 ,這句話(huà)我現(xiàn)在看著還是不知所云,云里霧里。 我們還是從 JMX 能給我們提供什么好處入手來(lái)理解吧。舉一個(gè)應(yīng)用實(shí)例:在一個(gè)系統(tǒng)中常常會(huì)有一些配置信息,比如服務(wù)的 IP 地址,端口號(hào)什么的,那么如何來(lái)寫(xiě)這些代碼 呢? 程序初哥一般是寫(xiě)死在程序里,到要改變時(shí)就去改程序,然后再編譯發(fā)布; 程序熟手則一般把這些信息寫(xiě)在一個(gè)配置文件里( JAVA 一般都是 *.properties 文件),到要改變時(shí)只要改配置文件,但還是重新啟動(dòng)系統(tǒng),以便讀取配置文件里的新值; 程序好手則會(huì)寫(xiě)一個(gè)段代碼,把配置值緩存起來(lái),系統(tǒng)在讀值的時(shí)候,先看看配置文件有沒(méi)有更動(dòng)。如有更改則重讀一遍,否則從緩存里讀取值 程序高手則懂得取物為我所用,用 JMX!把配置屬性集中在一個(gè)類(lèi),然后寫(xiě)一個(gè)叫MBean 的東東,再配置一下就輕松搞定了。而且 JMX 自動(dòng)提供了一個(gè) WEB 頁(yè)面來(lái)給你來(lái)改變這些配置信息。 二、準(zhǔn)備工作 JMX 是一份規(guī)范, SUN 依據(jù)這個(gè)規(guī)范在 JDK( 1.3、 1.4、 5.0)提供了 JMX 接口。而根據(jù)這個(gè)接口的實(shí)現(xiàn)則有很多種,比如 Weblogic 的 JMX 實(shí)現(xiàn)、 MX4J、 JBoss 的 JMX 實(shí)現(xiàn)。在 SUN 自己也實(shí)現(xiàn)了一份,不過(guò)在 JDK1.4之前,這件 JMX 實(shí)現(xiàn)(一些 JAR 包)是可選的,你得去它的網(wǎng)站上下載。 JDK5.0則內(nèi)嵌了進(jìn)來(lái),安裝 JDK5.0就可以開(kāi)發(fā)基于 JMX 的代碼了。 但 JDK5.0并非包含所有 SUN 的關(guān)于 JMX 的代碼,有一些工具類(lèi)是排除在 JDK5.0之外的。下面根據(jù)所使用的 JDK 版本情況,談一談開(kāi)發(fā)環(huán)境的準(zhǔn)備。 1、 JDK1.3、 1.4 去 SUN 網(wǎng)站下載 SUN 的 JMX 實(shí)現(xiàn),共兩個(gè) ZIP 文件,下載網(wǎng)址:/products/JavaManagement/download.html。 ( 1) jmx-1_2_1-ri.zip 解壓后的 lib 目錄包含: jmxri.jar、 jmxtools.jar ( 2) jmx_remote-1_0_1_03-ri.zip 解壓后的 lib 目錄包含: jmxremote.jar、 jmxremote_optional.jar、 rmissl.jar 如果在 DOS 下用命令行開(kāi)發(fā),則把這五個(gè) JAR 包加入到 classpath 系統(tǒng)變量中。如果你用 Eclipse 開(kāi)發(fā),則把 JAR 包加入到項(xiàng)目屬性的 Libratries(庫(kù))引用中。 2、 JDK5.0 JDK5.0的 jrelibrt.jar 已經(jīng)包含了 jmxri.jar、 jmxremote.jar、 rmissl.jar 三個(gè)包的代碼。如果你用到j(luò)mxtools.jar、 jmxremote_optional.jar 的類(lèi),則需要將這兩個(gè)類(lèi)加入到 classpath 或 Eclipse 的項(xiàng)目庫(kù)引用中。 3、我使用的開(kāi)發(fā)環(huán)境: JDK5.0 Eclipse3.2。 注:因?yàn)橛玫?jmxtools.jar 中的 HtmlAdaptorServer 類(lèi),所以將此包加入到項(xiàng)目庫(kù)引用中。jmxremote_optional.jar 暫時(shí)不用到,不管它。 三、 HelloWorld 實(shí)例 1、 Hello 是一個(gè)需要被管理的類(lèi)(普通 類(lèi)) java 代碼 package com.sunhill.jmx; public class Hello implements HelloMBean private String name; public String getName() return name; public void setName(String name) = name; public void printHello() System.out.println(Hello World, + name); public void printHello(String whoName) System.out.println(Hello , + whoName); 2、要管理 Hello 則必須創(chuàng)建一個(gè)相應(yīng) MBean,如 下: java 代碼 package com.sunhill.jmx; public interface HelloMBean public String getName(); public void setName(String name); public void printHello(); public void printHello(String whoName); 說(shuō)明:包含在 MBean 中方 法都將是可以被管理的。 MBean 起名是有規(guī)范的,就是原類(lèi)名后加上 MBean字樣。 3、創(chuàng)建一個(gè) Agent 類(lèi) java 代碼 package com.sunhill.jmx; import java.lang.management.ManagementFactory; import javax.management.MBeanServer; import javax.management.ObjectName; import m.HtmlAdaptorServer; public class HelloAgent public static void main(String args) throws Exception / MBeanServer server = MBeanServerFactory.createMBeanServer(); MBeanServer server = ManagementFactory.getPlatformMBeanServer(); ObjectName helloName = new ObjectName(chengang:name=HelloWorld); server.registerMBean(new Hello(), helloName); ObjectName adapterName = new ObjectName( HelloAgent:name=htmladapter,port=8082); HtmlAdaptorServer adapter = new HtmlAdaptorServer(); server.registerMBean(adapter, adapterName); adapter.start(); System.out.println(start.); 說(shuō)明: 先創(chuàng)建了一個(gè) MBeanServer,用來(lái)做 MBean 的容器 將 Hello 這個(gè)類(lèi)注入到 MBeanServer 中,注入需要?jiǎng)?chuàng)建一個(gè) ObjectName 類(lèi) 創(chuàng)建一個(gè) AdaptorServer,這個(gè)類(lèi)將決定 MBean 的管理界面,這里用最普通的 Html 型界面。AdaptorServer 其實(shí)也是一個(gè) MBean。 chengang:name=HelloWorld 的名字是有一定規(guī)則的,格式為: “域名 :name=MBean 名稱(chēng) ”,域名和 MBean 名稱(chēng)都可以任意取。 4、運(yùn)行 HelloAgent,然后打開(kāi)網(wǎng)頁(yè): http:/localhost:8082/,看效果 ! 五、總結(jié) 在實(shí)際系統(tǒng)中我們可以把 name 變成決定數(shù)庫(kù)鏈接池的變量,這樣我就可以對(duì)系統(tǒng)的運(yùn)行參數(shù)進(jìn)行實(shí)現(xiàn)的監(jiān)控和配置(管理)。而且也可以對(duì)一些方法(如 printHello)進(jìn)行遠(yuǎn)程調(diào)用了。 2、 JMX簡(jiǎn)介 一、 JMX 簡(jiǎn)介 JMX 是一種 JAVA 的正式規(guī)范,它主要目的是讓程序且有被管理的功能,那么怎么理解所謂的 “被管理 ”呢?試想你開(kāi)發(fā)了一個(gè)軟件(如網(wǎng)站),它是在小時(shí)不簡(jiǎn)斷運(yùn)行的,那么你可能會(huì)想要 “監(jiān)控 ”這個(gè)軟件的運(yùn)行情況,比如收到了多少數(shù)據(jù),有多少人登錄等等?;蛘?你又想 “配置 ”這個(gè)軟件,比如現(xiàn)在訪(fǎng)問(wèn)人數(shù)比較多,你想把數(shù)據(jù)連接池設(shè)置得大一些。 當(dāng)然,你也許會(huì)專(zhuān)門(mén)為這些管理來(lái)開(kāi)發(fā)軟件,但如果你借助 JMX,則會(huì)發(fā)現(xiàn)創(chuàng)建這樣的管理程序是如此簡(jiǎn)單。因?yàn)槟銦o(wú)需為管理程序來(lái)開(kāi)發(fā)界面,已經(jīng)有通用的 JMX 管理軟件,如 MC4J,或者是用一般都附帶提供的 HTML 網(wǎng)頁(yè)來(lái)管理,你要做的僅僅是將自己要被管理和監(jiān)控類(lèi)的按照 JMX 規(guī)范修改一下即可。 中間件軟件 WebLogic 的管理頁(yè)面就是基于 JMX 開(kāi)發(fā)的,而 JBoss 則整個(gè)系統(tǒng)都基于 JMX 構(gòu)架。下面將 JMX 的一些概念,從 JMX 規(guī)范轉(zhuǎn)帖如下 : 二、 JMX 構(gòu)架中的各層及相關(guān)的組件 工具層( Instrumentation Level) (a) MBeans(標(biāo)準(zhǔn)的,動(dòng)態(tài)的,開(kāi)放的和模型 MBeans) (b) 通知模型: Notification、 NotificationListener 等類(lèi) (c) MBean 元數(shù)據(jù)類(lèi): Attribute、 Opreator 等類(lèi) 代理層( Agent Level) (a) MBean Server (b) 代理服務(wù)。如前一篇的 HtmlAdaptorServer 等。 MBean 中有 getter 和 setter 的就是屬性,如前一篇的 Hello 類(lèi)中 Name。如果只有 getter 則表示該屬性只讀。一共有四種 MBean,如下: 標(biāo)準(zhǔn) MBeans( Standard MBeans)設(shè)計(jì)和實(shí)現(xiàn)是最簡(jiǎn)單的,這類(lèi) MBean 使用自己的方法名作為管理接口; 動(dòng)態(tài) MBeans( Dynamic MBeans)必須實(shí)現(xiàn)一個(gè)指定的接口,由于動(dòng)態(tài) MBeans在運(yùn)行期間暴露它們的管理接口,因此更為靈活; 開(kāi)放 MBeans( Open MBeans)屬于動(dòng)態(tài) MBeans,這類(lèi) MBean 依靠基礎(chǔ)數(shù)據(jù)類(lèi)型來(lái)實(shí)現(xiàn)通用管理, 并為友情用戶(hù)進(jìn)行自我聲明; 模型 MBeans( Model MBeans)同樣也是動(dòng)態(tài) MBeans,這類(lèi) MBeans 是完全可配置的,在運(yùn)行期間進(jìn)行自我聲明;它們?yōu)橘Y源動(dòng)態(tài)工具提供一個(gè)一般性的,有默認(rèn)行為的 MBeans 類(lèi)。 在前一篇中的 Hello、 HelloMBean 就是一個(gè)標(biāo)準(zhǔn) MBeans( Standard MBeans)。后面接下來(lái)的幾篇,我們會(huì)繼續(xù)介紹其他幾種 MBean。 3、 Notification的使用 一、簡(jiǎn)介 Mbean 之間的通信是必不可少的, Notification 就起到了在 Mbean 之間溝通橋梁的作用。 JMX notification 由四部分組成: Notification 這個(gè)相當(dāng)于一個(gè)信息包,封裝了需要傳遞的信息 Notification broadcaster 這相當(dāng)于一個(gè)廣播器,把消息廣播出去 Notification listerner 這是一個(gè)監(jiān)聽(tīng)器,用于監(jiān)聽(tīng)廣播出來(lái)的 Notification 消息 Notification filter 這是一個(gè)過(guò)濾器,過(guò)濾掉不需要的 Notification 消息 Notification broadcaster 不需要我們實(shí)現(xiàn), JMX 的內(nèi)部已經(jīng)有了。 Notification filter 一般也很少用。下面的例子主要用到了 Notification、 Notification listerner。 二、實(shí)例 在第一篇的 Hello 中有一個(gè) printHello(String whoName)方法,意思根據(jù)碰到的是誰(shuí)來(lái)打招呼,比如: Jack 從對(duì)面走過(guò)來(lái),說(shuō): “hi” 我們回之以禮,說(shuō): “Hello, jack” 首先這需要 Jack 先說(shuō)一個(gè) hi(相應(yīng)一個(gè)操作方法),然后他說(shuō)的話(huà)封裝成聲波(相當(dāng) Notification 消息包)傳遞出去。然后我們還要給 Jakc 裝上一個(gè)監(jiān)聽(tīng)器( Hello 的耳朵? _),這個(gè)監(jiān)聽(tīng)器將捕捉到 Jack的聲波語(yǔ)音包,并進(jìn)行相應(yīng)處理,即說(shuō) “Hello, jack”。 好,我們看看如何實(shí)現(xiàn)的: 1、 Jack 類(lèi)及其相應(yīng)的 MBean 我們把 Jack 寫(xiě)成一個(gè) MBean,如下: java 代碼 import javax.management.Notification; import javax.management.NotificationBroadcasterSupport; public class Jack extends NotificationBroadcasterSupport implements JackMBean private int seq = 0; public void hi() Notification n = new Notification(/創(chuàng)建一個(gè)信息包 jack.hi,/給這個(gè) Notification起個(gè)名稱(chēng) this, /由誰(shuí)發(fā)出的 Notification +seq,/一系列通知中的序列號(hào) ,可以設(shè)任意數(shù)值 System.currentTimeMillis(),/發(fā)出時(shí)間 Jack);/發(fā)出的消息文本 /發(fā)出去 sendNotification(n); 說(shuō)明: 必需繼承 NotificationBroadcasterSupport 此類(lèi)只有一個(gè) hi 方法,方法只有兩句:創(chuàng)建一個(gè) Notification 消息包,然后將包發(fā)出去 如果你還要在消息包上附加其他數(shù)據(jù), Notification 還有一個(gè) setUserData 方法可供使用 2、接下來(lái)是他的 MBean java 代碼 public interface JackMBean public void hi(); 3、 創(chuàng)建一個(gè) Listener,監(jiān)聽(tīng)到的 Notification 消息包將由此類(lèi)負(fù)責(zé)處理。 java 代碼 import javax.management.Notification; import javax.management.NotificationListener; public class HelloListener implements NotificationListener public void handleNotification(Notification n, Object handback) System.out.println(type= + n.getType(); System.out.println(source= + n.getSource(); System.out.println(seq= + n.getSequenceNumber(); System.out.println(send time= + n.getTimeStamp(); System.out.println(message= + n.getMessage(); if (handback != null) if (handback instanceof Hello) Hello hello = (Hello) handback; hello.printHello(n.getMessage(); 4、修改 HelloAgent 如下: java 代碼 import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import m.HtmlAdaptorServer; public class HelloAgent public static void main(String args) throws Exception MBeanServer server = MBeanServerFactory.createMBeanServer(); ObjectName helloName = new ObjectName(chengang:name=HelloWorld); Hello hello=new Hello(); server.registerMBean(hello, helloName); ObjectName adapterName = new ObjectName(HelloAgent:name=htmladapter,port=8082); HtmlAdaptorServer adapter = new HtmlAdaptorServer(); server.registerMBean(adapter, adapterName); Jack jack = new Jack(); /重點(diǎn) server.registerMBean(jack, new ObjectName(HelloAgent:name=jack); /重點(diǎn) jack.addNotificationListener(new HelloListener(), null, hello); /重點(diǎn) adapter.start(); System.out.println(start.); 三、運(yùn)行 1、先運(yùn)行 HelloAgent 啟動(dòng)服務(wù),再打開(kāi)瀏覽器輸入網(wǎng)址: http:/localhost:8082/ 2、 進(jìn)入 “name=jack”項(xiàng),然后單擊 “hi”按鈕來(lái)執(zhí)行它。 四、總結(jié) Notification 和 Java 的事件模型是一樣的,另外如果你買(mǎi)了 Eclipse 從入門(mén)到精通,你會(huì)發(fā)現(xiàn)第 22.4節(jié)也使用了和 Notification 和 Java 的事件模型相同的設(shè)計(jì)方式。 Notification 在我們的實(shí)際項(xiàng)目中也用到了,象我們現(xiàn)在的給移動(dòng)做的項(xiàng)目中(基于 JMX 實(shí)現(xiàn) ),分散在各地方的工作站的日志,就是通過(guò) Notification方式,把每條產(chǎn)生的日志封裝在 Notification 中實(shí)時(shí)發(fā)回主控服務(wù)器的。有機(jī)會(huì)我會(huì)發(fā)這一系統(tǒng)的 關(guān)于日志的設(shè)計(jì)方案寫(xiě)一下,它實(shí)現(xiàn)了對(duì)各地工作站的集中的、實(shí)時(shí)的監(jiān)控,非常實(shí)用。 4、動(dòng)態(tài) MBean: DynamicMBean 一、前言 動(dòng)態(tài) MBean 是在運(yùn)行期才定義它的屬性和方法,也就是說(shuō)它有什么屬性和方法是可以動(dòng)態(tài)改變的。動(dòng)態(tài) MBean 主要利用一些輔助類(lèi)(構(gòu)造函數(shù)類(lèi) MBeanConstructorInfo、屬性類(lèi) MBeanAttributeInfo、方法類(lèi) MBeanOperationInfo)來(lái)完成這個(gè)功能,所有的動(dòng)態(tài) MBean 必須實(shí)現(xiàn) DynamicMBean 接口。DynamicMBean 寫(xiě)好后,使用方法和第一篇文章中普通的 MBean 一樣。 給出一個(gè)動(dòng)態(tài) MBean 的實(shí)例,這個(gè)實(shí)例最初動(dòng)態(tài)構(gòu)了一個(gè) Name 屬性及一個(gè) print 方法,當(dāng)我們執(zhí)行它的 print 方法之后,又給此 MBean 新增了一個(gè) print1方法。實(shí)例的代碼如下: 二、實(shí)例 1、 HelloDynamic 類(lèi) java 代碼 import java.lang.reflect.Constructor; import java.util.Iterator; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.DynamicMBean; import javax.management.MBeanAttributeInfo; import javax.management.MBeanConstructorInfo; import javax.management.MBeanException; import javax.management.MBeanInfo; import javax.management.MBeanNotificationInfo; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; import javax.management.ReflectionException; /* * author Sunny Peng * author change by Chen.Gang, add a feature for dynamic add operation * version 1.0 */ public class HelloDynamic implements DynamicMBean /這是我們的屬性名稱(chēng) private String name; private MBeanInfo mBeanInfo = null; private String className; private String description; private MBeanAttributeInfo attributes; private MBeanConstructorInfo constructors; private MBeanOperationInfo operations; MBeanNotificationInfo mBeanNotificationInfoArray; public HelloDynamic() init(); buildDynamicMBean(); private void init() className = this.getClass().getName(); description = Simple implementation of a dynamic MBean.; attributes = new MBeanAttributeInfo1; constructors = new MBeanConstructorInfo1; operations = new MBeanOperationInfo1; mBeanNotificationInfoArray = new MBeanNotificationInfo0; private void buildDynamicMBean() /設(shè)定構(gòu)造函數(shù) Constructor thisconstructors = this.getClass().getConstructors(); constructors0 = new MBeanConstructorInfo(HelloDynamic(): Constructs a HelloDynamic object, thisconstructors0); /設(shè)定一個(gè)屬性 attributes0 = new MBeanAttributeInfo(Name, java.lang.String, Name: name string., true, true, false); /operate method 我們的操作方法是 print MBeanParameterInfo params = null;/無(wú)參數(shù) operations0 = new MBeanOperationInfo(print, print(): print the name, params, void, MBeanOperationInfo.INFO); mBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations, mBeanNotificationInfoArray); /動(dòng)態(tài)增加一個(gè) print1方法 private void dynamicAddOperation() init(); operations = new MBeanOperationInfo2;/設(shè)定數(shù)組為兩個(gè) buildDynamicMBean(); operations1 = new MBeanOperationInfo(print1, print1(): print the name, null, void, MBeanOperationInfo.INFO); mBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations, mBeanNotificationInfoArray); public Object getAttribute(String attribute_name) if (attribute_name != null) return null; if (attribute_name.equals(Name) return name; return null; public void setAttribute(Attribute attribute) if (attribute = null) return; String Name = attribute.getName(); Object value = attribute.getValue(); try if (Name.equals(Name) / if null value, try and see if the setter returns any exception if (value = null) name = null; / if non null value, make sure it is assignable to the attribute else if (Class.forName(java.lang.String).isAssignableFrom(value.getClass() name = (String) value; catch (Exception e) e.printStackTrace(); public AttributeList getAttributes(String attributeNames) if (attributeNames = null) return null; AttributeList resultList = new AttributeList(); / if attributeNames is empty, return an empty result list if (attributeNames.length = 0) return resultList; for (int i = 0; i attributeNames.length; i+) try Object value = getAttribute(attributeNamesi); resultList.add(new Attribute(attributeNamesi, value); catch (Exception e) e.printStackTrace(); return resultList; public AttributeList setAttributes(AttributeList attributes) if (attributes = null) return null; AttributeList resultList = new AttributeList(); / if attributeNames is empty, nothing more to do if (attributes.isEmpty() return resultList; / for each attribute, try to set it and add to the result list if successfull for (Iterator i = attributes.iterator(); i.hasNext();) Attribute attr = (Attribute) i.next(); try setAttribute(attr); String name = attr.getName(); Object value = getAttribute(name); resultList.add(new Attribute(name, value); catch (Exception e) e.printStackTrace(); return resultList; public Object invoke(String operationName, Object params, String signature) throws MBeanException, ReflectionException / Check for a recognized operation name and call the corresponding operation if (operationName.equals(print) /具體實(shí)現(xiàn)我們的操作方法 print System.out.println(Hello, + name + , this is HellDynamic!); dynamicAddOperation(); return null; else if (operationName.equals(print1) System.out.println(這是動(dòng)態(tài)增加的一方法 print1); return null; else / unrecognized operation name: throw new ReflectionException(new NoSuchMethodException(operationName), Cannot find the operation + operationName + in + className); public MBeanInfo getMBeanInfo() return mBeanInfo; 說(shuō)明: 實(shí)現(xiàn)于接口 DynamicMBean 借助于各種輔助類(lèi)完成一個(gè)類(lèi)的構(gòu)造。構(gòu)造函數(shù)類(lèi) MBeanConstructorInfo、屬性類(lèi)MBeanAttributeInfo、方法類(lèi) MBeanOperationInfo 這里所有 public 方法是實(shí)現(xiàn)于 DynamicMBean 的。主要提供: setAttribute 設(shè)置屬性、 getAttribute取得屬性、 setAttributes 設(shè)置一組屬性、 getAttributes 取得一組屬性、 invoke 方法調(diào)用、 getMBeanInfo MBeanServer 由這個(gè)方法得到關(guān)鍵的 MBean 類(lèi)的構(gòu)造信息。 2、 HelloAgent 類(lèi) 前面說(shuō)了 HelloDynamic 和普通 MBean的使用方法是一樣的,因此 HelloAgent 和第一篇的 HelloAgent基本一樣,就是把 Hello 改成 HelloDynamic 而已。為了實(shí)例完整,也一并帖出來(lái)吧。 java 代碼 import javax.management.MBeanServerFactory; import javax.management.ObjectName; import m.HtmlAdaptorServer; public class HelloAgent public static void main(String args) throws Exception MBeanServer server = MBeanServerFactory.createMBeanServer(); ObjectName helloName = new ObjectName(chengang:name=HelloDynamic); HelloDynamic hello = new HelloDynamic(); server.registerMBean(hello, helloName); ObjectName adapterName = new ObjectName(HelloAgent:name=htmladapter,port=8082); HtmlAdaptorServer adapter = new HtmlAdaptorServer(); server.registerMBean(adapter, adapterName); adapter.start(); System.out.println(start.); 3、運(yùn)行 先運(yùn)行 HelloAgent。再打開(kāi)瀏覽器,輸入網(wǎng)址: http:/localhost:8082/。單擊進(jìn)入 “name=HelloDynamic ”項(xiàng),執(zhí)行 print 方法后再回到上一頁(yè)面你會(huì)發(fā)現(xiàn)又多了一個(gè) print1方法。 4、總結(jié) 動(dòng)態(tài) MBean 的代碼稍顯復(fù)雜,但對(duì)于一些特殊需求的情況,它將顯示出強(qiáng)大威力。而且它還是模型MBeans( Model MBeans)的基礎(chǔ)。不過(guò)在一般的項(xiàng)目中,動(dòng)態(tài) MBean 還是用得比較少,所謂利器深藏之而不用,非常時(shí)方現(xiàn)光芒。 5、用 Apache的 commons-modeler來(lái)輔助開(kāi)發(fā) JMX 一、前言 每一個(gè) MBean 都要有一個(gè)接口,比如前面的 Hello 要有一個(gè) HelloMBean 接口。要多維護(hù)一個(gè)接口,的確是件麻煩的事。 Apache 的 commons-modeler 利用 JMX 中的動(dòng)態(tài) MBean 原理很好的解決了這一問(wèn)題, commons-modeler使用得我們可以只寫(xiě) Hello,而不用寫(xiě) HelloMBean這個(gè)接口。不過(guò)這是有代價(jià)的,它要求我們寫(xiě)一個(gè) mbean 的 xml 描述文件(唉,少了一件事,卻又多出另一件事來(lái))。但 commons-modeler 還是有優(yōu)點(diǎn)的,就是它讓 mbean 的裝配更加靈活,把多個(gè) mbean 的裝配都集中在一個(gè) XML 文件里來(lái)了。 開(kāi)始實(shí)例之前,你需要先去 apache 網(wǎng)站下載 commons-modeler,以及 modeler 的依賴(lài)項(xiàng)目 commons-logging。下載網(wǎng)址為:/site/downloads/downloads_commons.html,下載的文件是 ZIP 壓縮包,解壓后找到 commons-logging.jar 和 commons-modeler.jar。如果在 DOS 下用命令行開(kāi)發(fā),則把這兩個(gè) JAR 包加入到 classpath 系統(tǒng)變量中。如果你用 Eclipse 開(kāi)發(fā),則把 JAR 包加入到項(xiàng)目屬性的 Libratries(庫(kù))引用中。 二、 HelloWorld 實(shí)例 我們以本系統(tǒng)的第一篇 “1、 JMX 的 Hello World”為例,來(lái)重新實(shí)現(xiàn)一次。 1、 Hello.java 的代碼不變(注:為了在 Eclipse 上和原來(lái)的 Hello 文件放在不同的地方,我把新Hello 放到了 mbean.modelbean 包),如下: java 代碼 package mbean.modelbean; import mbean.standard.HelloMBean; public class Hello implements HelloMBean private String name; public String getName() return name; public void setName(String name) = name; public void printHello() System.out.println(Hello World, + name); public void printHello(String whoName) System.out.println(Hello , + whoName); 2、 MBean不用寫(xiě)了,但需要寫(xiě)一個(gè) XML描述文件。文件名任取,這里取名為: mbeans-descriptors xml 代碼 這里只對(duì) 標(biāo)簽做一下說(shuō)明: * name mbean在 xml中的唯一標(biāo)識(shí),不一定要和類(lèi)同名 * description mbean的注釋說(shuō)明信息 * domain mbean所屬域 * group mbean所屬組 * type mbean的類(lèi)全名(包名類(lèi)名) * classname 指定實(shí)現(xiàn)代理功能的 ModelMbean的全名,如果不指定則默認(rèn)為 BaseModelMBean 3、接下來(lái)改寫(xiě) HelloAgent java 代碼 package mbean.modelbean; import java.io.InputStream; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.modelmbean.ModelMBean; import mons.modeler.ManagedBean; import mons.modeler.Registry; import m.HtmlAdaptorServer; public class HelloAgent public static void main(String args) throws Exception /基于 xml中的信息構(gòu)建一個(gè) Registry Registry registry = Registry.getRegistry(null, null); InputStream stream = HelloAgent.class.getResourceAsStream(Mbeans-descriptors.xml); registry.loadMetadata(stream); stream.close(); /由 Registry得到一個(gè) MBeanServer MBeanServer server = registry.getMBeanServer(); /得到 Hello在描述文件中的信息類(lèi),對(duì)應(yīng)于 xml文件 標(biāo)簽的name屬性。 ManagedBean managed = registry.findManagedBean(Hello); /創(chuàng)建 ObjectName ObjectName helloName = new ObjectName(managed.getDomain() + :name=HelloWorld); /得到 ModelMBean ModelMBean hello = managed.createMBean(new Hello(); /注冊(cè) MBean server.registerMBean(hello, helloName); ObjectName adapterName = new ObjectName(HelloAgent:name=htmladapter,port=8082); HtmlAdaptorServer adapter = new HtmlAdaptorServer(); server.registerMBean(adapter, adapterName); adapter.start(); System.out.println(start.); HelloAgent是效復(fù)雜的地方,我們來(lái)和以前的 HelloAgent逐步比較一下,前后有什么不同: ( 1)首先,新的 HelloAgent需要將 xml信息讀入到 Registry對(duì)象中,這是舊 HelloAgent所沒(méi)有的。 Registry registry = Registry.getRegistry(null, null); InputStream stream = HelloAgent.class.getResourceAsStream(Mbeans-descriptors.xml); registry.loadMetadata(stream); stream.close(); ( 2)接著創(chuàng)建 MBeanServer的方式也不同了 現(xiàn)在: MBeanServer server = registry.getMBeanServer(); 以前 : MBeanServer server = MBeanServerFactory.createMBeanServer(); ( 3) Hello相應(yīng)的 ObjectName創(chuàng)建也略不相同。主要是域名在 XML描述文件里設(shè)置好了。 現(xiàn)在: ManagedBean managed = registry.findManagedBean(Hello); ObjectName helloName = new ObjectName(managed.getDomain() + :name=HelloWorld); 以前: ObjectName helloName = new ObjectName(chengang:name=HelloWorld) ( 4)得到 MBean的方式也不同,這里就是關(guān)鍵的不同點(diǎn) 現(xiàn)在: ModelMBean hello = managed.createMBean(new Hello(); 以前: Hello hello = new Hello(); 注意:為什么現(xiàn)在要比以前多一個(gè) createMbean步驟呢,就是因?yàn)楝F(xiàn)在的寫(xiě)法并沒(méi)有寫(xiě) Mbean,所以需要?jiǎng)討B(tài)才需要生成一個(gè)。而以前就直接把 new Hello()注冊(cè)到 mbean server就可以了, server會(huì)自動(dòng)找到它的 HelloMBean接口文件。 也就上面四點(diǎn)區(qū)別,其他代碼完全一樣。測(cè)試和查看效果的方法和以前一樣,在此不累述了。 commons Modeler為 Hello動(dòng)態(tài)生成了一個(gè) MBean接口: BaseModelBean 參考資料 用 Commons Modeler 開(kāi)發(fā) JMX應(yīng)用 6、模型 Bean: Model Bean 在上一節(jié)是用 apache 的 commons-modeler 來(lái)開(kāi)發(fā)的一個(gè) model,只不過(guò) commons-modeler 幫助我們實(shí)現(xiàn)了很多的代碼,而我們只需要寫(xiě)描述 XML 文件就行了。這一節(jié),來(lái)一個(gè)實(shí)打?qū)嵉?Model Bean,不借助任何第三方工具 包。例子還是沿用 Hello 這個(gè)類(lèi),以便于和以前的實(shí)現(xiàn)相比較。 一、 Model MBean 實(shí)例 1、 Hello.java 還是和以前的一樣。這里它沒(méi)有再加上一個(gè) MBean 接口了,只是一個(gè)很普通的類(lèi)。 java 代碼 public class Hello private String name; public String getName() return name; public void setName(String name) = name; public void printHello() System.out.println(Hello World, + name); public void printHello(String whoName) System.out.println(Hello , + whoName); 2、接下來(lái)是 HelloAgent的寫(xiě)法,和以前就差一句:把 “new Hello()”這一句刪除了,加上了ModelMbeanUtils.createModlerMbean(); java 代碼 import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import javax.management.modelmbean.RequiredModelMBean; import m.HtmlAdaptorServer; public class HelloAgent public static void main(String args) throws Exception MBeanServer server = MBeanServerFactory.createMBeanServer(); ObjectName helloName = new ObjectName(chengang:name=HelloWorld); /Hello hello = new Hello(); RequiredModelMBean hello = ModelMBeanUtils.createModlerMBean(); server.registerMBean(hello, helloName); ObjectName adapterName = new ObjectName(HelloAgent:name=htmladapter,port=8082); HtmlAdaptorServer adapter = new HtmlAdaptorServer(); server.registerMBean(adapter, adapterName); adapter.start(); System.out.println(start.); 3、 ModelMbeanUtils這個(gè)類(lèi)是要我們自己來(lái)實(shí)現(xiàn)的,也是寫(xiě) model Bean最麻煩的地方,它主要是返回一個(gè) RequiredModelMBean類(lèi),此類(lèi)主要包括了一個(gè) ModelMBeanInfo類(lèi)的信息。在 ModelMBeanInfo中定義了所有對(duì)需要管理的屬性和方法的描述。具體代碼如下: java 代碼 import javax.management.MBeanParameterInfo; 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 ModelMBeanUtils private static final boolean READABLE = true; private static final boolean WRITABLE = true; private static final boolean BOOLEAN = true; private static final String STRING_CLASS = java.lang.String; public static RequiredModelMBean createModlerMBean() RequiredModelMBean model = null; try model = new RequiredModelMBean(); model.setManagedResource(new Hello(), ObjectReference); ModelMBeanInfo info = createModelMBeanInfo(); model.setModelMBeanInfo(info); catch (Exception e) e.printStackTrace(); return model; private static ModelMBeanInfo createModelMBeanInfo() / / 屬性 / / / 構(gòu)造 name屬性信息 ModelMBeanAttributeInfo nameAttrInfo = new ModelMBeanAttributeInfo(/ Name, / 屬性名 STRING_CLASS, /屬性類(lèi)型 people name, / 描述文字 READABLE, WRITABLE, !BOOLEAN, / 讀寫(xiě) null / 屬性描述子 ); / / 方法 / / /構(gòu)造 printHello()操作的信息 ModelMBeanOperationInfo print1Info = new ModelMBeanOperationInfo(/ printHello, / null, / null, / void, / MBeanOperationInfo.INFO, / null / ); / 構(gòu)造 printHello(String whoName)操作信息 ModelMBeanOperationInfo print2Info; MBeanParameterInfo param2 = new MBeanParameterInfo1; param20 = new MBeanParameterInfo(whoName, STRING_CLASS, say hello to who); print2Info = new ModelMBeanOperationInfo(/ printHello, / null,/ param2,/ void, / MBeanOperationInfo.INFO, / null/ ); / / 最后總合 / / / create ModelMBeanInfo ModelMBeanInfo mbeanInfo = new ModelMBeanInfoSupport(/ RequiredModelMBean.class.getName(), / MBean類(lèi) null, / 描述文字 new ModelMBeanAttributeInfo / 所有的屬性信息(數(shù)組) nameAttrInfo ,/只有一個(gè)屬性 null, / 所有的構(gòu)造函數(shù)信息 new ModelMBeanOperationInfo / 所有的操作信息(數(shù)組) print1Info, print2Info ,/ null, / 所有的通知信息 (本例無(wú) ) null/MBean描述子 ); return mbeanInfo; 4、看效果的方法和以前一樣,運(yùn)行 HelloAgent,用瀏覽器打開(kāi): http:/localhost:8082 。效果圖和standard mbean一樣,就不再帖出來(lái)了,去第一篇去看吧 二、總結(jié) 我們發(fā)現(xiàn)模型 Mbean(Model MBean)要比標(biāo)準(zhǔn) MBean(standard mbean)復(fù)雜多了,那有什么理由讓我們選擇使用模型 MBean嗎?我認(rèn)為,最大的理由就是模型 MBean可以動(dòng)態(tài)配置。試想一下這個(gè)應(yīng)用場(chǎng)景:由于安全或其他原因,系統(tǒng)要把某個(gè) MBean公開(kāi)的可管理方法隱藏起 來(lái)。這時(shí),如果你是用標(biāo)準(zhǔn) MBean,這需要修改接口類(lèi),然后重新編譯發(fā)布;如果用 Apache commons-modeler來(lái)寫(xiě)的模型 MBean,則只需要修改 XML文件就行了,不需要重新編譯發(fā)布(可能要重啟一下系統(tǒng))。這就是模型 Mbean 優(yōu)勢(shì)之所在了。 細(xì)心的人會(huì)發(fā)現(xiàn)動(dòng)態(tài) MBean和這一節(jié)的模型 Mbean非常相似,但它們還是有很大不同的:動(dòng)態(tài) MBean沒(méi)有 Hello類(lèi),它要自己實(shí)現(xiàn) Hello類(lèi)中的方法邏輯。 7、用 JDK5.0的 JConsole來(lái)連接 MBean 前面所有看效果都是通過(guò) Html 網(wǎng)頁(yè)來(lái)看的。 JDK5.0自帶了一個(gè) jmx 客戶(hù)端,叫 jconsole,位于c:jdkbinjconsole.exe。我們來(lái)用用這個(gè)客戶(hù)端來(lái)連接 Mbean Server。 一、 vm 參數(shù)方式 1、還是用第一篇的那個(gè) HelloAgent,修改 HelloAgent,將第一句: MBeanServer server = MBeanServerFactory.createMBeanServer(); 改為: MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 注: ManagementFactory 的全路徑為: java.lang.management.ManagementFactory 2、修改 Eclipse 的 run 選項(xiàng),把 “-Dcom.sun.management.jmxremote=HelloAgent”這一句加入到 run 選項(xiàng)中 3、運(yùn)行 HelloAgent,然后在 Dos 窗口輸入 “jconsole”來(lái)啟到 JConsole 4、單 擊 “連接 ” 二、 RMI 方式 還是用 jconsole,但方式變了。這里不需要象上面那樣修改 Eclipse run 的 vm 選項(xiàng)。 1、還是用第一篇的 HelloAgent,加上一段代碼,啟動(dòng)一個(gè) JMXConnectorServer 服務(wù) java 代碼 import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; import m.HtmlAdaptorServer; public class HelloAgent public static void main(String args) throws Exception MBeanServer server = MBeanServerFactory.createMBeanServer(); ObjectName helloName = new ObjectName(chengang:name=HelloWorld); Hello hello = new Hello(); server.registerMBean(hello, helloName); ObjectName adapterName = new ObjectName(HelloAgent:name=htmladapter,port=8082); HtmlAdaptorServer adapter = new HtmlAdaptorServer(); server.registerMBean(adapter, adapterName); adapter.start(); System.out.println(start.); / Create an RMI connector and start it JMXServiceURL url = new JMXServiceURL(service:jmx:rmi:/jndi/rmi:/localhost:9999/server); JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server); cs.start(); System.out.println(rmi start.); 2、在 Dos運(yùn)行一個(gè)命令: rmiregistry 9999 3、運(yùn)行 HelloAgent,然后再在 dos下運(yùn)行命令 jconsole 輸入 service:jmx:rmi:/jndi/rmi:/localhost:9999/server 三、總結(jié) 連接 MBeanServer的方式除了 Html、 JConsole,還有一些第三方的客戶(hù)端,比較有名的是 MC4j,通過(guò)這些客戶(hù)端我們可以很容易去訪(fǎng)問(wèn) MBean。這也就是我們?yōu)槭裁匆?JMX的其中一個(gè)原因:試想如果我自己搞一套標(biāo)準(zhǔn),勢(shì)必要自己開(kāi)發(fā)一個(gè)客戶(hù)端,那會(huì)是一個(gè)不小的工作量。 8、編寫(xiě)程序來(lái)連接 MBean 前面用 Html、 jconsole 等方 法連接上了 MBeanServer,并能夠通過(guò)這些界面來(lái)操縱 MBean。但有時(shí)我們需要不借助這些客戶(hù)端,而是在自己的程序來(lái)操縱這些 MBean,這就要求我們知道如何在代碼里連接 MBean。 基于上一篇為 jconsole 而修改的例子,給出一個(gè)示例的客戶(hù)端程序,基本的操作都有了: java 代碼 import java.util.Iterator; import java.util.Set; import javax.management.Attribute; import javax.management.MBeanInfo; import javax.management.MBeanServerConnection; import javax.management.MBeanServerInvocationHandler; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; public class Client public static void main(String args) throws Exception JMXServiceURL url = new JMXServiceURL(service:jmx:rmi:/jndi/rmi:/localhost:9999/server); JMXConnector jmxc = JMXConnectorFactory.connect(url, null); MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); ObjectName mbeanName = new ObjectName(chengang:name=HelloWorld); / 把所有 Domain都打印出來(lái) System.out.println(Domains:-); String domains = mbsc.getDomains(); for (int i = 0; i domains.length; i+) System.out.println(tDomain + i + = + domainsi); / MBean的總數(shù) System.out.println(MBean count = + mbsc.getMBeanCount(); / 對(duì) name屬性的操作(屬性名的第一個(gè)字母要大寫(xiě)) mbsc.setAttribute(mbeanName, new Attribute(Name, PANDA);/ 設(shè)值 System.out.println(Name = + mbsc.getAttribute(mbeanName, Name);/ 取值 / 得到 proxy代理后直接調(diào)用的方式 HelloMBean proxy = (HelloMBean) MBeanServerInvocationHandler.newProxyInstance(mbsc, mbeanName, HelloMBean.class, false); proxy.printHello(); proxy.printHello(Raymend); / 遠(yuǎn)程調(diào)用的方式 mbsc.invoke(mbeanName, printHello, null, null); mbsc.invoke(mbeanName, printHello, new Object 熊貓燒香 , new String String.class.getName() ); / 得 mbean的信息 MBeanInfo info = mbsc.getMBeanInfo(mbeanName); System.out.println(Hello Class: + info.getClassName(); System.out.println(Hello Attriber : + info.getAttributes()0.getName(); System.out.println(Hello Operation : + info.getOperations()0.getName(); / 得到所有的 MBean的 ObjectName System.out.println(all ObjectName: -); Set set = mbsc.queryMBeans(null, null); for (Iterator it = set.iterator(); it.hasNext();) ObjectInstance oi = (ObjectInstance) it.next(); System.out.println(t + oi.getObjectName(); / 注銷(xiāo) / mbsc.unregisterMBean(mbeanName); / 關(guān)閉 MBeanServer連接 jmxc.close(); 運(yùn)行后的效果如下: Domains:- Domain0 = HelloAgent Domain1 = JMImplementation Domain2 = chengang MBean count = 3 Name = Chen.Gang Hello Class: mbean.connector.Hello Hello Attriber: Name Hello Operation: printHello all ObjectName: - chengang:name=HelloWorld JMImplementation:type=MBeanServerDelegate HelloAgent:name=htmladapter,port=8082 它有兩個(gè) Console 輸出,這里是另一個(gè) Hello World, PANDA Hello , 熊貓 Hello World, PANDA Hello , 熊貓燒香 9、基于 JBoss 來(lái)寫(xiě) MBean 前面都是用 JDK 自帶的 JMX 實(shí)現(xiàn)來(lái)寫(xiě)的 MBean, JMX 的實(shí)現(xiàn)不獨(dú) SUN 一家, JBOSS 也有自己的 JMX實(shí)現(xiàn)。如果你使用 JBOSS 來(lái)做 WEB 服務(wù)器,那么基于 JBOSS 的實(shí)現(xiàn)來(lái)寫(xiě) MBean,是一個(gè)不錯(cuò)的選擇。象我們公司就是用 JBOSS 的,因此所有 MBean 都是基于 JBoss 來(lái)寫(xiě) 的?;?JBoss 的 MBean 和基于SUN 的 MBean 有什么不同嗎?有一些不同之外,但絕大部份都一樣。 下面是我最早發(fā)的一篇關(guān)于 JMX 的文章,是我對(duì)公司所做項(xiàng)目的筆記,它上面的 JMX 例子就是基于JBOSS 的。博客搬了幾次家,文章刪的刪丟的丟,但這篇文章還保留著,簡(jiǎn)單修改一下,再帖上吧。 一、 HelloWorld 實(shí)例 1、準(zhǔn)備工作 JBOSS 實(shí)現(xiàn)了 JMX 規(guī)范,這個(gè)實(shí)例是基于 JBOSS 來(lái)實(shí)現(xiàn)的。請(qǐng)先去下載一個(gè) JBOSS,我是 jboss-3.2.6,下載地址: /downloads/index#as。這個(gè)實(shí)例需要 JBOSS的兩個(gè) JAR 包的支持: jboss-system-3.2.6.jar、 jboss-jmx-3.2.6.jar,如果你和我一樣用 Eclipse來(lái)開(kāi)發(fā)(推薦),那么把這個(gè)兩個(gè)包加入到項(xiàng)目的庫(kù)引用中(加入到庫(kù)引用的方法參考前面兩章)。 2、程序代碼 假設(shè)我們有一個(gè)叫 message 的屬性要需要經(jīng)常進(jìn)行改動(dòng)配置的,那么我們就把它寫(xiě)成一個(gè)MBean。 1、 HelloWorldServiceMBe

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論