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

下載本文檔

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

文檔簡介

JMX 一步步來 1、 JMX的 Hello World 一、 JMX 簡介 什么是 JMX?在一篇網(wǎng)文中是這樣說的: JMX(Java Management Extensions)是一個為應(yīng)用程序植入管理功能的框架。 JMX 是一套標準的代理和服務(wù),實際上,用戶可以在任何 Java 應(yīng)用程序中使用這些代理和服務(wù)實現(xiàn)管理 ,這句話我現(xiàn)在看著還是不知所云,云里霧里。 我們還是從 JMX 能給我們提供什么好處入手來理解吧。舉一個應(yīng)用實例:在一個系統(tǒng)中常常會有一些配置信息,比如服務(wù)的 IP 地址,端口號什么的,那么如何來寫這些代碼 呢? 程序初哥一般是寫死在程序里,到要改變時就去改程序,然后再編譯發(fā)布; 程序熟手則一般把這些信息寫在一個配置文件里( JAVA 一般都是 *.properties 文件),到要改變時只要改配置文件,但還是重新啟動系統(tǒng),以便讀取配置文件里的新值; 程序好手則會寫一個段代碼,把配置值緩存起來,系統(tǒng)在讀值的時候,先看看配置文件有沒有更動。如有更改則重讀一遍,否則從緩存里讀取值 程序高手則懂得取物為我所用,用 JMX!把配置屬性集中在一個類,然后寫一個叫MBean 的東東,再配置一下就輕松搞定了。而且 JMX 自動提供了一個 WEB 頁面來給你來改變這些配置信息。 二、準備工作 JMX 是一份規(guī)范, SUN 依據(jù)這個規(guī)范在 JDK( 1.3、 1.4、 5.0)提供了 JMX 接口。而根據(jù)這個接口的實現(xiàn)則有很多種,比如 Weblogic 的 JMX 實現(xiàn)、 MX4J、 JBoss 的 JMX 實現(xiàn)。在 SUN 自己也實現(xiàn)了一份,不過在 JDK1.4之前,這件 JMX 實現(xiàn)(一些 JAR 包)是可選的,你得去它的網(wǎng)站上下載。 JDK5.0則內(nèi)嵌了進來,安裝 JDK5.0就可以開發(fā)基于 JMX 的代碼了。 但 JDK5.0并非包含所有 SUN 的關(guān)于 JMX 的代碼,有一些工具類是排除在 JDK5.0之外的。下面根據(jù)所使用的 JDK 版本情況,談一談開發(fā)環(huán)境的準備。 1、 JDK1.3、 1.4 去 SUN 網(wǎng)站下載 SUN 的 JMX 實現(xiàn),共兩個 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 下用命令行開發(fā),則把這五個 JAR 包加入到 classpath 系統(tǒng)變量中。如果你用 Eclipse 開發(fā),則把 JAR 包加入到項目屬性的 Libratries(庫)引用中。 2、 JDK5.0 JDK5.0的 jrelibrt.jar 已經(jīng)包含了 jmxri.jar、 jmxremote.jar、 rmissl.jar 三個包的代碼。如果你用到j(luò)mxtools.jar、 jmxremote_optional.jar 的類,則需要將這兩個類加入到 classpath 或 Eclipse 的項目庫引用中。 3、我使用的開發(fā)環(huán)境: JDK5.0 Eclipse3.2。 注:因為用到 jmxtools.jar 中的 HtmlAdaptorServer 類,所以將此包加入到項目庫引用中。jmxremote_optional.jar 暫時不用到,不管它。 三、 HelloWorld 實例 1、 Hello 是一個需要被管理的類(普通 類) 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)建一個相應(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); 說明:包含在 MBean 中方 法都將是可以被管理的。 MBean 起名是有規(guī)范的,就是原類名后加上 MBean字樣。 3、創(chuàng)建一個 Agent 類 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.); 說明: 先創(chuàng)建了一個 MBeanServer,用來做 MBean 的容器 將 Hello 這個類注入到 MBeanServer 中,注入需要創(chuàng)建一個 ObjectName 類 創(chuàng)建一個 AdaptorServer,這個類將決定 MBean 的管理界面,這里用最普通的 Html 型界面。AdaptorServer 其實也是一個 MBean。 chengang:name=HelloWorld 的名字是有一定規(guī)則的,格式為: “域名 :name=MBean 名稱 ”,域名和 MBean 名稱都可以任意取。 4、運行 HelloAgent,然后打開網(wǎng)頁: http:/localhost:8082/,看效果 ! 五、總結(jié) 在實際系統(tǒng)中我們可以把 name 變成決定數(shù)庫鏈接池的變量,這樣我就可以對系統(tǒng)的運行參數(shù)進行實現(xiàn)的監(jiān)控和配置(管理)。而且也可以對一些方法(如 printHello)進行遠程調(diào)用了。 2、 JMX簡介 一、 JMX 簡介 JMX 是一種 JAVA 的正式規(guī)范,它主要目的是讓程序且有被管理的功能,那么怎么理解所謂的 “被管理 ”呢?試想你開發(fā)了一個軟件(如網(wǎng)站),它是在小時不簡斷運行的,那么你可能會想要 “監(jiān)控 ”這個軟件的運行情況,比如收到了多少數(shù)據(jù),有多少人登錄等等?;蛘?你又想 “配置 ”這個軟件,比如現(xiàn)在訪問人數(shù)比較多,你想把數(shù)據(jù)連接池設(shè)置得大一些。 當然,你也許會專門為這些管理來開發(fā)軟件,但如果你借助 JMX,則會發(fā)現(xiàn)創(chuàng)建這樣的管理程序是如此簡單。因為你無需為管理程序來開發(fā)界面,已經(jīng)有通用的 JMX 管理軟件,如 MC4J,或者是用一般都附帶提供的 HTML 網(wǎng)頁來管理,你要做的僅僅是將自己要被管理和監(jiān)控類的按照 JMX 規(guī)范修改一下即可。 中間件軟件 WebLogic 的管理頁面就是基于 JMX 開發(fā)的,而 JBoss 則整個系統(tǒng)都基于 JMX 構(gòu)架。下面將 JMX 的一些概念,從 JMX 規(guī)范轉(zhuǎn)帖如下 : 二、 JMX 構(gòu)架中的各層及相關(guān)的組件 工具層( Instrumentation Level) (a) MBeans(標準的,動態(tài)的,開放的和模型 MBeans) (b) 通知模型: Notification、 NotificationListener 等類 (c) MBean 元數(shù)據(jù)類: Attribute、 Opreator 等類 代理層( Agent Level) (a) MBean Server (b) 代理服務(wù)。如前一篇的 HtmlAdaptorServer 等。 MBean 中有 getter 和 setter 的就是屬性,如前一篇的 Hello 類中 Name。如果只有 getter 則表示該屬性只讀。一共有四種 MBean,如下: 標準 MBeans( Standard MBeans)設(shè)計和實現(xiàn)是最簡單的,這類 MBean 使用自己的方法名作為管理接口; 動態(tài) MBeans( Dynamic MBeans)必須實現(xiàn)一個指定的接口,由于動態(tài) MBeans在運行期間暴露它們的管理接口,因此更為靈活; 開放 MBeans( Open MBeans)屬于動態(tài) MBeans,這類 MBean 依靠基礎(chǔ)數(shù)據(jù)類型來實現(xiàn)通用管理, 并為友情用戶進行自我聲明; 模型 MBeans( Model MBeans)同樣也是動態(tài) MBeans,這類 MBeans 是完全可配置的,在運行期間進行自我聲明;它們?yōu)橘Y源動態(tài)工具提供一個一般性的,有默認行為的 MBeans 類。 在前一篇中的 Hello、 HelloMBean 就是一個標準 MBeans( Standard MBeans)。后面接下來的幾篇,我們會繼續(xù)介紹其他幾種 MBean。 3、 Notification的使用 一、簡介 Mbean 之間的通信是必不可少的, Notification 就起到了在 Mbean 之間溝通橋梁的作用。 JMX notification 由四部分組成: Notification 這個相當于一個信息包,封裝了需要傳遞的信息 Notification broadcaster 這相當于一個廣播器,把消息廣播出去 Notification listerner 這是一個監(jiān)聽器,用于監(jiān)聽廣播出來的 Notification 消息 Notification filter 這是一個過濾器,過濾掉不需要的 Notification 消息 Notification broadcaster 不需要我們實現(xiàn), JMX 的內(nèi)部已經(jīng)有了。 Notification filter 一般也很少用。下面的例子主要用到了 Notification、 Notification listerner。 二、實例 在第一篇的 Hello 中有一個 printHello(String whoName)方法,意思根據(jù)碰到的是誰來打招呼,比如: Jack 從對面走過來,說: “hi” 我們回之以禮,說: “Hello, jack” 首先這需要 Jack 先說一個 hi(相應(yīng)一個操作方法),然后他說的話封裝成聲波(相當 Notification 消息包)傳遞出去。然后我們還要給 Jakc 裝上一個監(jiān)聽器( Hello 的耳朵? _),這個監(jiān)聽器將捕捉到 Jack的聲波語音包,并進行相應(yīng)處理,即說 “Hello, jack”。 好,我們看看如何實現(xiàn)的: 1、 Jack 類及其相應(yīng)的 MBean 我們把 Jack 寫成一個 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)建一個信息包 jack.hi,/給這個 Notification起個名稱 this, /由誰發(fā)出的 Notification +seq,/一系列通知中的序列號 ,可以設(shè)任意數(shù)值 System.currentTimeMillis(),/發(fā)出時間 Jack);/發(fā)出的消息文本 /發(fā)出去 sendNotification(n); 說明: 必需繼承 NotificationBroadcasterSupport 此類只有一個 hi 方法,方法只有兩句:創(chuàng)建一個 Notification 消息包,然后將包發(fā)出去 如果你還要在消息包上附加其他數(shù)據(jù), Notification 還有一個 setUserData 方法可供使用 2、接下來是他的 MBean java 代碼 public interface JackMBean public void hi(); 3、 創(chuàng)建一個 Listener,監(jiān)聽到的 Notification 消息包將由此類負責處理。 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(); /重點 server.registerMBean(jack, new ObjectName(HelloAgent:name=jack); /重點 jack.addNotificationListener(new HelloListener(), null, hello); /重點 adapter.start(); System.out.println(start.); 三、運行 1、先運行 HelloAgent 啟動服務(wù),再打開瀏覽器輸入網(wǎng)址: http:/localhost:8082/ 2、 進入 “name=jack”項,然后單擊 “hi”按鈕來執(zhí)行它。 四、總結(jié) Notification 和 Java 的事件模型是一樣的,另外如果你買了 Eclipse 從入門到精通,你會發(fā)現(xiàn)第 22.4節(jié)也使用了和 Notification 和 Java 的事件模型相同的設(shè)計方式。 Notification 在我們的實際項目中也用到了,象我們現(xiàn)在的給移動做的項目中(基于 JMX 實現(xiàn) ),分散在各地方的工作站的日志,就是通過 Notification方式,把每條產(chǎn)生的日志封裝在 Notification 中實時發(fā)回主控服務(wù)器的。有機會我會發(fā)這一系統(tǒng)的 關(guān)于日志的設(shè)計方案寫一下,它實現(xiàn)了對各地工作站的集中的、實時的監(jiān)控,非常實用。 4、動態(tài) MBean: DynamicMBean 一、前言 動態(tài) MBean 是在運行期才定義它的屬性和方法,也就是說它有什么屬性和方法是可以動態(tài)改變的。動態(tài) MBean 主要利用一些輔助類(構(gòu)造函數(shù)類 MBeanConstructorInfo、屬性類 MBeanAttributeInfo、方法類 MBeanOperationInfo)來完成這個功能,所有的動態(tài) MBean 必須實現(xiàn) DynamicMBean 接口。DynamicMBean 寫好后,使用方法和第一篇文章中普通的 MBean 一樣。 給出一個動態(tài) MBean 的實例,這個實例最初動態(tài)構(gòu)了一個 Name 屬性及一個 print 方法,當我們執(zhí)行它的 print 方法之后,又給此 MBean 新增了一個 print1方法。實例的代碼如下: 二、實例 1、 HelloDynamic 類 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 /這是我們的屬性名稱 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è)定一個屬性 attributes0 = new MBeanAttributeInfo(Name, java.lang.String, Name: name string., true, true, false); /operate method 我們的操作方法是 print MBeanParameterInfo params = null;/無參數(shù) operations0 = new MBeanOperationInfo(print, print(): print the name, params, void, MBeanOperationInfo.INFO); mBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations, mBeanNotificationInfoArray); /動態(tài)增加一個 print1方法 private void dynamicAddOperation() init(); operations = new MBeanOperationInfo2;/設(shè)定數(shù)組為兩個 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) /具體實現(xiàn)我們的操作方法 print System.out.println(Hello, + name + , this is HellDynamic!); dynamicAddOperation(); return null; else if (operationName.equals(print1) System.out.println(這是動態(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; 說明: 實現(xiàn)于接口 DynamicMBean 借助于各種輔助類完成一個類的構(gòu)造。構(gòu)造函數(shù)類 MBeanConstructorInfo、屬性類MBeanAttributeInfo、方法類 MBeanOperationInfo 這里所有 public 方法是實現(xiàn)于 DynamicMBean 的。主要提供: setAttribute 設(shè)置屬性、 getAttribute取得屬性、 setAttributes 設(shè)置一組屬性、 getAttributes 取得一組屬性、 invoke 方法調(diào)用、 getMBeanInfo MBeanServer 由這個方法得到關(guān)鍵的 MBean 類的構(gòu)造信息。 2、 HelloAgent 類 前面說了 HelloDynamic 和普通 MBean的使用方法是一樣的,因此 HelloAgent 和第一篇的 HelloAgent基本一樣,就是把 Hello 改成 HelloDynamic 而已。為了實例完整,也一并帖出來吧。 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、運行 先運行 HelloAgent。再打開瀏覽器,輸入網(wǎng)址: http:/localhost:8082/。單擊進入 “name=HelloDynamic ”項,執(zhí)行 print 方法后再回到上一頁面你會發(fā)現(xiàn)又多了一個 print1方法。 4、總結(jié) 動態(tài) MBean 的代碼稍顯復雜,但對于一些特殊需求的情況,它將顯示出強大威力。而且它還是模型MBeans( Model MBeans)的基礎(chǔ)。不過在一般的項目中,動態(tài) MBean 還是用得比較少,所謂利器深藏之而不用,非常時方現(xiàn)光芒。 5、用 Apache的 commons-modeler來輔助開發(fā) JMX 一、前言 每一個 MBean 都要有一個接口,比如前面的 Hello 要有一個 HelloMBean 接口。要多維護一個接口,的確是件麻煩的事。 Apache 的 commons-modeler 利用 JMX 中的動態(tài) MBean 原理很好的解決了這一問題, commons-modeler使用得我們可以只寫 Hello,而不用寫 HelloMBean這個接口。不過這是有代價的,它要求我們寫一個 mbean 的 xml 描述文件(唉,少了一件事,卻又多出另一件事來)。但 commons-modeler 還是有優(yōu)點的,就是它讓 mbean 的裝配更加靈活,把多個 mbean 的裝配都集中在一個 XML 文件里來了。 開始實例之前,你需要先去 apache 網(wǎng)站下載 commons-modeler,以及 modeler 的依賴項目 commons-logging。下載網(wǎng)址為:/site/downloads/downloads_commons.html,下載的文件是 ZIP 壓縮包,解壓后找到 commons-logging.jar 和 commons-modeler.jar。如果在 DOS 下用命令行開發(fā),則把這兩個 JAR 包加入到 classpath 系統(tǒng)變量中。如果你用 Eclipse 開發(fā),則把 JAR 包加入到項目屬性的 Libratries(庫)引用中。 二、 HelloWorld 實例 我們以本系統(tǒng)的第一篇 “1、 JMX 的 Hello World”為例,來重新實現(xiàn)一次。 1、 Hello.java 的代碼不變(注:為了在 Eclipse 上和原來的 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不用寫了,但需要寫一個 XML描述文件。文件名任取,這里取名為: mbeans-descriptors xml 代碼 這里只對 標簽做一下說明: * name mbean在 xml中的唯一標識,不一定要和類同名 * description mbean的注釋說明信息 * domain mbean所屬域 * group mbean所屬組 * type mbean的類全名(包名類名) * classname 指定實現(xiàn)代理功能的 ModelMbean的全名,如果不指定則默認為 BaseModelMBean 3、接下來改寫 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)建一個 Registry Registry registry = Registry.getRegistry(null, null); InputStream stream = HelloAgent.class.getResourceAsStream(Mbeans-descriptors.xml); registry.loadMetadata(stream); stream.close(); /由 Registry得到一個 MBeanServer MBeanServer server = registry.getMBeanServer(); /得到 Hello在描述文件中的信息類,對應(yīng)于 xml文件 標簽的name屬性。 ManagedBean managed = registry.findManagedBean(Hello); /創(chuàng)建 ObjectName ObjectName helloName = new ObjectName(managed.getDomain() + :name=HelloWorld); /得到 ModelMBean ModelMBean hello = managed.createMBean(new Hello(); /注冊 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是效復雜的地方,我們來和以前的 HelloAgent逐步比較一下,前后有什么不同: ( 1)首先,新的 HelloAgent需要將 xml信息讀入到 Registry對象中,這是舊 HelloAgent所沒有的。 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)鍵的不同點 現(xiàn)在: ModelMBean hello = managed.createMBean(new Hello(); 以前: Hello hello = new Hello(); 注意:為什么現(xiàn)在要比以前多一個 createMbean步驟呢,就是因為現(xiàn)在的寫法并沒有寫 Mbean,所以需要動態(tài)才需要生成一個。而以前就直接把 new Hello()注冊到 mbean server就可以了, server會自動找到它的 HelloMBean接口文件。 也就上面四點區(qū)別,其他代碼完全一樣。測試和查看效果的方法和以前一樣,在此不累述了。 commons Modeler為 Hello動態(tài)生成了一個 MBean接口: BaseModelBean 參考資料 用 Commons Modeler 開發(fā) JMX應(yīng)用 6、模型 Bean: Model Bean 在上一節(jié)是用 apache 的 commons-modeler 來開發(fā)的一個 model,只不過 commons-modeler 幫助我們實現(xiàn)了很多的代碼,而我們只需要寫描述 XML 文件就行了。這一節(jié),來一個實打?qū)嵉?Model Bean,不借助任何第三方工具 包。例子還是沿用 Hello 這個類,以便于和以前的實現(xiàn)相比較。 一、 Model MBean 實例 1、 Hello.java 還是和以前的一樣。這里它沒有再加上一個 MBean 接口了,只是一個很普通的類。 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、接下來是 HelloAgent的寫法,和以前就差一句:把 “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這個類是要我們自己來實現(xiàn)的,也是寫 model Bean最麻煩的地方,它主要是返回一個 RequiredModelMBean類,此類主要包括了一個 ModelMBeanInfo類的信息。在 ModelMBeanInfo中定義了所有對需要管理的屬性和方法的描述。具體代碼如下: 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, /屬性類型 people name, / 描述文字 READABLE, WRITABLE, !BOOLEAN, / 讀寫 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類 null, / 描述文字 new ModelMBeanAttributeInfo / 所有的屬性信息(數(shù)組) nameAttrInfo ,/只有一個屬性 null, / 所有的構(gòu)造函數(shù)信息 new ModelMBeanOperationInfo / 所有的操作信息(數(shù)組) print1Info, print2Info ,/ null, / 所有的通知信息 (本例無 ) null/MBean描述子 ); return mbeanInfo; 4、看效果的方法和以前一樣,運行 HelloAgent,用瀏覽器打開: http:/localhost:8082 。效果圖和standard mbean一樣,就不再帖出來了,去第一篇去看吧 二、總結(jié) 我們發(fā)現(xiàn)模型 Mbean(Model MBean)要比標準 MBean(standard mbean)復雜多了,那有什么理由讓我們選擇使用模型 MBean嗎?我認為,最大的理由就是模型 MBean可以動態(tài)配置。試想一下這個應(yīng)用場景:由于安全或其他原因,系統(tǒng)要把某個 MBean公開的可管理方法隱藏起 來。這時,如果你是用標準 MBean,這需要修改接口類,然后重新編譯發(fā)布;如果用 Apache commons-modeler來寫的模型 MBean,則只需要修改 XML文件就行了,不需要重新編譯發(fā)布(可能要重啟一下系統(tǒng))。這就是模型 Mbean 優(yōu)勢之所在了。 細心的人會發(fā)現(xiàn)動態(tài) MBean和這一節(jié)的模型 Mbean非常相似,但它們還是有很大不同的:動態(tài) MBean沒有 Hello類,它要自己實現(xiàn) Hello類中的方法邏輯。 7、用 JDK5.0的 JConsole來連接 MBean 前面所有看效果都是通過 Html 網(wǎng)頁來看的。 JDK5.0自帶了一個 jmx 客戶端,叫 jconsole,位于c:jdkbinjconsole.exe。我們來用用這個客戶端來連接 Mbean Server。 一、 vm 參數(shù)方式 1、還是用第一篇的那個 HelloAgent,修改 HelloAgent,將第一句: MBeanServer server = MBeanServerFactory.createMBeanServer(); 改為: MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 注: ManagementFactory 的全路徑為: java.lang.management.ManagementFactory 2、修改 Eclipse 的 run 選項,把 “-Dcom.sun.management.jmxremote=HelloAgent”這一句加入到 run 選項中 3、運行 HelloAgent,然后在 Dos 窗口輸入 “jconsole”來啟到 JConsole 4、單 擊 “連接 ” 二、 RMI 方式 還是用 jconsole,但方式變了。這里不需要象上面那樣修改 Eclipse run 的 vm 選項。 1、還是用第一篇的 HelloAgent,加上一段代碼,啟動一個 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運行一個命令: rmiregistry 9999 3、運行 HelloAgent,然后再在 dos下運行命令 jconsole 輸入 service:jmx:rmi:/jndi/rmi:/localhost:9999/server 三、總結(jié) 連接 MBeanServer的方式除了 Html、 JConsole,還有一些第三方的客戶端,比較有名的是 MC4j,通過這些客戶端我們可以很容易去訪問 MBean。這也就是我們?yōu)槭裁匆?JMX的其中一個原因:試想如果我自己搞一套標準,勢必要自己開發(fā)一個客戶端,那會是一個不小的工作量。 8、編寫程序來連接 MBean 前面用 Html、 jconsole 等方 法連接上了 MBeanServer,并能夠通過這些界面來操縱 MBean。但有時我們需要不借助這些客戶端,而是在自己的程序來操縱這些 MBean,這就要求我們知道如何在代碼里連接 MBean。 基于上一篇為 jconsole 而修改的例子,給出一個示例的客戶端程序,基本的操作都有了: 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都打印出來 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(); / 對 name屬性的操作(屬性名的第一個字母要大寫) 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); / 遠程調(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(); / 注銷 / mbsc.unregisterMBean(mbeanName); / 關(guān)閉 MBeanServer連接 jmxc.close(); 運行后的效果如下: 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 它有兩個 Console 輸出,這里是另一個 Hello World, PANDA Hello , 熊貓 Hello World, PANDA Hello , 熊貓燒香 9、基于 JBoss 來寫 MBean 前面都是用 JDK 自帶的 JMX 實現(xiàn)來寫的 MBean, JMX 的實現(xiàn)不獨 SUN 一家, JBOSS 也有自己的 JMX實現(xiàn)。如果你使用 JBOSS 來做 WEB 服務(wù)器,那么基于 JBOSS 的實現(xiàn)來寫 MBean,是一個不錯的選擇。象我們公司就是用 JBOSS 的,因此所有 MBean 都是基于 JBoss 來寫 的?;?JBoss 的 MBean 和基于SUN 的 MBean 有什么不同嗎?有一些不同之外,但絕大部份都一樣。 下面是我最早發(fā)的一篇關(guān)于 JMX 的文章,是我對公司所做項目的筆記,它上面的 JMX 例子就是基于JBOSS 的。博客搬了幾次家,文章刪的刪丟的丟,但這篇文章還保留著,簡單修改一下,再帖上吧。 一、 HelloWorld 實例 1、準備工作 JBOSS 實現(xiàn)了 JMX 規(guī)范,這個實例是基于 JBOSS 來實現(xiàn)的。請先去下載一個 JBOSS,我是 jboss-3.2.6,下載地址: /downloads/index#as。這個實例需要 JBOSS的兩個 JAR 包的支持: jboss-system-3.2.6.jar、 jboss-jmx-3.2.6.jar,如果你和我一樣用 Eclipse來開發(fā)(推薦),那么把這個兩個包加入到項目的庫引用中(加入到庫引用的方法參考前面兩章)。 2、程序代碼 假設(shè)我們有一個叫 message 的屬性要需要經(jīng)常進行改動配置的,那么我們就把它寫成一個MBean。 1、 HelloWorldServiceMBe

溫馨提示

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

評論

0/150

提交評論