日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JMX一步步来

發布時間:2024/4/17 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JMX一步步来 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://www.quanlei.com/tag/jmx

http://www.blogjava.net/chengang/category/8015.html

[JMX一步步來] 1、JMX的Hello World

文/陳剛 from www.chengang.com.cn at 2005-12-3

一、JMX簡介

  什么是JMX?在一篇網文中是這樣說的:"JMX(Java Management Extensions)是一個為應用程序植入管理功能的框架。JMX是一套標準的代理和服務,實際上,用戶可以在任何Java應用程序中使用這些代理和服務實現管理",這句話我現在看著還是不知所云,云里霧里。
  我們還是從JMX能給我們提供什么好處入手來理解吧。舉一個應用實例:在一個系統中常常會有一些配置信息,比如服務的IP地址,端口號什么的,那么如何來寫這些代碼呢?
  • 程序初哥一般是寫死在程序里,到要改變時就去改程序,然后再編譯發布;
  • 程序熟手則一般把這些信息寫在一個配置文件里(JAVA一般都是*.properties文件),到要改變時只要改配置文件,但還是重新啟動系統,以便讀取配置文件里的新值;
  • 程序好手則會寫一個段代碼,把配置值緩存起來,系統在讀值的時候,先看看配置文件有沒有更動。如有更改則重讀一遍,否則從緩存里讀取值
  • 程序高手則懂得取物為我所用,用JMX!把配置屬性集中在一個類,然后寫一個叫MBean的東東,再配置一下就輕松搞定了。而且JMX自動提供了一個WEB頁面來給你來改變這些配置信息。
  • 二、準備工作


      JMX是一份規范,SUN依據這個規范在JDK(1.3、1.4、5.0)提供了JMX接口。而根據這個接口的實現則有很多種,比如Weblogic的JMX實現、MX4J、JBoss的JMX實現。在SUN自己也實現了一份,不過在JDK1.4之前,這件JMX實現(一些JAR包)是可選的,你得去它的網站上下載。JDK5.0則內嵌了進來,安裝JDK5.0就可以開發基于JMX的代碼了。

    但JDK5.0并非包含所有SUN的關于JMX的代碼,有一些工具類是排除在JDK5.0之外的。下面根據所使用的JDK版本情況,談一談開發環境的準備。 1、JDK1.3、1.4 去SUN網站下載SUN的JMX實現,共兩個ZIP文件,下載網址:http://java.sun.com/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下用命令行開發,則把這五個JAR包加入到classpath系統變量中。如果你用Eclipse開發,則把JAR包加入到項目屬性的Libratries(庫)引用中。 2、JDK5.0 JDK5.0的jre\lib\rt.jar已經包含了jmxri.jar、jmxremote.jar、rmissl.jar三個包的代碼。如果你用到jmxtools.jar、jmxremote_optional.jar的類,則需要將這兩個類加入到classpath或Eclipse的項目庫引用中。 3、我使用的開發環境:JDK5.0 + Eclipse3.2。 注:因為用到jmxtools.jar中的HtmlAdaptorServer類,所以將此包加入到項目庫引用中。jmxremote_optional.jar暫時不用到,不管它。

    三、HelloWorld實例 1、Hello是一個需要被管理的類(普通類)
    /*** @author ChenGang 2005-12-3*/ public class Hello implements HelloMBean {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public void printHello() {System.out.println("Hello World, " + name);}public void printHello(String whoName) {System.out.println("Hello , " + whoName);} } 2、要管理Hello則必須創建一個相應MBean,如下: /*** @author ChenGang 2005-12-3*/ public interface HelloMBean {public String getName();public void setName(String name);public void printHello();public void printHello(String whoName); } 說明:包含在MBean中方法都將是可以被管理的。MBean起名是有規范的,就是原類名后加上MBean字樣。 3、創建一個Agent類 import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import com.sun.jdmk.comm.HtmlAdaptorServer; public class HelloAgent { public static void main(String[] args) throws Exception {MBeanServer server = MBeanServerFactory.createMBeanServer(); 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.....");} } 說明:
    • 先創建了一個MBeanServer,用來做MBean的容器
    • 將Hello這個類注入到MBeanServer中,注入需要創建一個ObjectName類
    • 創建一個AdaptorServer,這個類將決定MBean的管理界面,這里用最普通的Html型界面。AdaptorServer其實也是一個MBean。
    • chengang:name=HelloWorld的名字是有一定規則的,格式為:“域名:name=MBean名稱”,域名和MBean名稱都可以任意取。
    4、運行HelloAgent,然后打開網頁:http://localhost:8082/,效果圖如下: 單擊“name=HelloWorld”鏈接進入,出現如下頁面

    依照下面紅線的步驟操作之后,在控制臺(我用Eclipse就是console視圖)得到如下輸出:

    五、總結

      在實際系統中我們可以把name變成決定數庫鏈接池的變量,這樣我就可以對系統的運行參數進行實現的監控和配置(管理)。而且也可以對一些方法(如printHello)進行遠程調用了。

      預告:下一篇將對JMX進行一些介紹,借助本篇的HelloWorld實例來灌輸一些概念。

    作者簡介

    陳剛,廣西桂林人,著作有《Eclipse從入門到精通》
    您可以通過其博客了解更多信息和文章:http://www.chenGang.com.cn

    ?

    [JMX一步步來] 2、JMX簡介

    文/陳剛 from www.chengang.com.cn at 2005-12-4

    一、JMX簡介

      JMX是一種JAVA的正式規范,它主要目的是讓程序且有被管理的功能,那么怎么理解所謂的“被管理”呢?試想你開發了一個軟件(如WEB網站),它是在24小時不簡斷運行的,那么你可能會想要“監控”這個軟件的運行情況,比如收到了多少數據,有多少人登錄等等。或者你又想“配置”這個軟件,比如現在訪問人數比較多,你想把數據連接池設置得大一些。

      當然,你也許會專門為這些管理來開發軟件,但如果你借助JMX,則會發現創建這樣的管理程序是如此簡單。因為你無需為管理程序來開發界面,已經有通用的JMX管理軟件,如MC4J,或者是用一般都附帶提供的HTML網頁來管理,你要做的僅僅是將自己要被管理和監控類的按照JMX規范修改一下即可。

      中間件軟件WebLogic的管理頁面就是基于JMX開發的,而JBoss則整個系統都基于JMX構架。下面將JMX的一些概念,從JMX規范轉帖如下:

    二、JMX構架中的各層及相關的組件

  • 工具層(Instrumentation Level)
    ????(a) MBeans(標準的,動態的,開放的和模型MBeans)
    ????(b) 通知模型:Notification、NotificationListener等類
    ????(c) MBean元數據類:Attribute、Opreator等類
  • 代理層(Agent Level)
    ????(a) MBean Server
    ????(b) 代理服務。如前一篇的HtmlAdaptorServer等。
  • 以下是從網上找到的兩個圖:

    (圖1)

    (圖2)

      MBean中有getter和setter的就是屬性,如前一篇的Hello類中Name。如果只有getter則表示該屬性只讀。一共有四種MBean,如下:

  • 標準MBeans(Standard MBeans)設計和實現是最簡單的,這類MBean使用自己的方法名作為管理接口;
  • 動態MBeans(Dynamic MBeans)必須實現一個指定的接口,由于動態MBeans在運行期間暴露它們的管理接口,因此更為靈活;
  • 開放MBeans(Open MBeans)屬于動態MBeans,這類MBean依靠基礎數據類型來實現通用管理,并為友情用戶進行自我聲明;
  • 模型MBeans(Model MBeans)同樣也是動態MBeans,這類MBeans是完全可配置的,在運行期間進行自我聲明;它們為資源動態工具提供一個一般性的,有默認行為的MBeans類。
  • [JMX一步步來] 3、Notification的使用

    文/陳剛 from www.chengang.com.cn at 2005-12-4 一、簡介 Mbean之間的通信是必不可少的,Notification就起到了在Mbean之間溝通橋梁的作用。JMX notification 由四部分組成:
    • Notification 這個相當于一個信息包,封裝了需要傳遞的信息
    • Notification broadcaster 這相當于一個廣播器,把消息廣播出去
    • Notification listerner 這是一個監聽器,用于監聽廣播出來的Notification消息
    • Notification filter 這是一個過濾器,過濾掉不需要的Notification消息
    Notification broadcaster不需要我們實現,JMX的內部已經有了。Notification filter一般也很少用。下面的例子主要用到了Notification、Notification listerner。
    二、實例 在第一篇的Hello中有一個printHello(String whoName)方法,意思根據碰到的是誰來打招呼,比如: Jack從對面走過來,說:“hi” 我們回之以禮,說:“Hello, jack” 首先這需要Jack先說一個hi(相應一個操作方法),然后他說的話封裝成聲波(相當Notification消息包)傳遞出去。然后我們還要給Jakc裝上一個監聽器(Hello的耳朵??^_^),這個監聽器將捕捉到Jack的聲波語音包,并進行相應處理,即說“Hello, jack”。 好,我們看看如何實現的: 1、Jack類及其相應的MBean 我們把Jack寫成一個MBean,如下:? 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(//創建一個信息包"jack.hi",//給這個Notification起個名稱this, //由誰發出的Notification++seq,//一系列通知中的序列號,可以設任意數值System.currentTimeMillis(),//發出時間"Jack");//發出的消息文本//發出去sendNotification(n);} } 說明:
    • 必需繼承NotificationBroadcasterSupport
    • 此類只有一個hi方法,方法只有兩句:創建一個Notification消息包,然后將包發出去
    • 如果你還要在消息包上附加其他數據,Notification還有一個setUserData方法可供使用
    2、接下來是他的MBean? public interface JackMBean {public void hi(); } 3、創建一個Listener,監聽到的Notification消息包將由此類負責處理。 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如下(加上了紅色的三句): import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import com.sun.jdmk.comm.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啟動服務,再打開瀏覽器輸入網址:http://localhost:8082/,出現如下界面。 2、 進入“name=jack”項,然后單擊“hi”按鈕來執行它。這時Eclipse的console視圖顯示如下:

    四、總結

      Notification和Java的事件模型是一樣的,另外如果你買了《Eclipse從入門到精通》,你會發現第22.4節也使用了和Notification和Java的事件模型相同的設計方式。Notification在我們的實際項目中也用到了,象我們現在的給移動做的項目中(基于JMX實現),分散在各地方的工作站的日志,就是通過Notification方式,把每條產生的日志封裝在Notification中實時發回主控服務器的。有機會我會發這一系統的關于日志的設計方案寫一下,它實現了對各地工作站的集中的、實時的監控,非常實用。

    作者簡介

    陳剛,廣西桂林人,著作有《Eclipse從入門到精通》
    您可以通過其博客了解更多信息和文章:http://www.chenGang.com.cn

    [JMX一步步來] 4、動態MBean:DynamicMBean

    文/陳剛? from www.chengang.com.cn at 2005-12-4 一、前言 動態MBean是在運行期才定義它的屬性和方法,也就是說它有什么屬性和方法是可以動態改變的。動態MBean主要利用一些輔助類(構造函數類MBeanConstructorInfo、屬性類MBeanAttributeInfo、方法類MBeanOperationInfo)來完成這個功能,所有的動態MBean必須實現DynamicMBean接口。DynamicMBean寫好后,使用方法和第一篇文章中普通的MBean一樣。 給出一個動態MBean的實例,這個實例最初動態構了一個Name屬性及一個print方法,當我們執行它的print方法之后,又給此MBean新增了一個print1方法。實例的代碼如下: 二、實例 1、HelloDynamic類 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 MBeanAttributeInfo[1];constructors = new MBeanConstructorInfo[1];operations = new MBeanOperationInfo[1];mBeanNotificationInfoArray = new MBeanNotificationInfo[0];} ??? private void buildDynamicMBean() {//設定構造函數Constructor[] thisconstructors = this.getClass().getConstructors();constructors[0] = new MBeanConstructorInfo("HelloDynamic(): Constructs a HelloDynamic object", thisconstructors[0]);//設定一個屬性attributes[0] = new MBeanAttributeInfo("Name", "java.lang.String", "Name: name string.", true, true, false);//operate method 我們的操作方法是printMBeanParameterInfo[] params = null;//無參數operations[0] = new MBeanOperationInfo("print", "print(): print the name", params, "void", MBeanOperationInfo.INFO);mBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations, mBeanNotificationInfoArray);} ??? //動態增加一個print1方法private void dynamicAddOperation() {init();operations = new MBeanOperationInfo[2];//設定數組為兩個buildDynamicMBean();operations[1] = 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 exceptionif (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 listif (attributeNames.length == 0)return resultList;for (int i = 0; i < attributeNames.length; i++) {try {Object value = getAttribute(attributeNames[i]);resultList.add(new Attribute(attributeNames[i], 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 doif (attributes.isEmpty())return resultList;// for each attribute, try to set it and add to the result list if successfullfor (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 operationif (operationName.equals("print")) {//具體實現我們的操作方法print System.out.println("Hello, " + name + ", this is HellDynamic!");dynamicAddOperation();return null;} else if (operationName.equals("print1")) {System.out.println("這是動態增加的一方法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;} } 說明:
    • 實現于接口DynamicMBean
    • 借助于各種輔助類完成一個類的構造。構造函數類MBeanConstructorInfo、屬性類MBeanAttributeInfo、方法類MBeanOperationInfo
    • 這里所有public方法是實現于DynamicMBean的。主要提供:setAttribute設置屬性、getAttribute取得屬性、setAttributes設置一組屬性、getAttributes取得一組屬性、invoke方法調用、getMBeanInfo MBeanServer由這個方法得到關鍵的MBean類的構造信息。
    2、HelloAgent類 前面說了HelloDynamic和普通MBean的使用方法是一樣的,因此HelloAgent和第一篇的HelloAgent基本一樣,就是把Hello改成HelloDynamic而已。為了實例完整,也一并帖出來吧。 import javax.management.MBeanServerFactory; import javax.management.ObjectName; import com.sun.jdmk.comm.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。再打開瀏覽器,輸入網址:http://localhost:8082/。單擊進入“name=HelloDynamic ”項,執行print方法后再回到上一頁面你會發現又多了一個print1方法。 4、總結   動態MBean的代碼稍顯復雜,但對于一些特殊需求的情況,它將顯示出強大威力。而且它還是模型MBeans(Model MBeans)的基礎。不過在一般的項目中,動態MBean還是用得比較少,所謂利器深藏之而不用,非常時方現光芒。

    ?

    ?

    [JMX一步步來] 5、用Apache的commons-modeler來輔助開發JMX

    文/陳剛? from www.chengang.com.cn at 2005-12-13 一、前言 每一個MBean都要有一個接口,比如前面的Hello要有一個HelloMBean接口。要多維護一個接口,的確是件麻煩的事。Apache的commons-modeler利用JMX中的動態MBean原理很好的解決了這一問題,commons-modeler使用得我們可以只寫Hello,而不用寫HelloMBean這個接口。不過這是有代價的,它要求我們寫一個mbean的xml描述文件(唉,少了一件事,卻又多出另一件事來)。但commons-modeler還是有優點的,就是它讓mbean的裝配更加靈活,把多個mbean的裝配都集中在一個XML文件里來了。 開始實例之前,你需要先去apache網站下載commons-modeler,以及modeler的依賴項目commons-logging。下載網址為:http://jakarta.apache.org/site/downloads/downloads_commons.html,下載的文件是ZIP壓縮包,解壓后找到commons-logging.jar和commons-modeler.jar。如果在DOS下用命令行開發,則把這兩個JAR包加入到classpath系統變量中。如果你用Eclipse開發,則把JAR包加入到項目屬性的Libratries(庫)引用中。
    二、HelloWorld實例 我們以本系統的第一篇“1、JMX的Hello World”為例,來重新實現一次。 1、Hello.java的代碼不變(注:為了在Eclipse上和原來的Hello文件放在不同的地方,我把新Hello放到了mbean.modelbean包),如下: 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) {this.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 version="1.0"?> <mbeans-descriptors><mbean name="Hello" description="the hello bean" domain="chengang" group="helloGroup" type="mbean.modelbean.Hello"><attribute name="name" description="a name attribute" type="java.lang.String" writeable="true"/><operation name="printHello" description="a operation to print hello" impact="INFO" returnType="String"/></mbean> </mbeans-descriptors>? 這里只對<mbean>標簽做一下說明:
    • name mbean在xml中的唯一標識,不一定要和類同名
    • description mbean的注釋說明信息
    • domain mbean所屬域
    • group mbean所屬組
    • type mbean的類全名(包名+類名)
    • classname 指定實現代理功能的ModelMbean的全名,如果不指定則默認為BaseModelMBean?
    3、接下來改寫HelloAgent package mbean.modelbean; import java.io.InputStream; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.modelmbean.ModelMBean; import org.apache.commons.modeler.ManagedBean; import org.apache.commons.modeler.Registry; import com.sun.jdmk.comm.HtmlAdaptorServer; public class HelloAgent {public static void main(String[] args) throws Exception {//基于xml中的信息構建一個RegistryRegistry registry = Registry.getRegistry(null, null);InputStream stream = HelloAgent.class.getResourceAsStream("Mbeans-descriptors.xml");registry.loadMetadata(stream);stream.close();//由Registry得到一個MBeanServerMBeanServer server = registry.getMBeanServer(); ??????? //得到Hello在描述文件中的信息類,對應于xml文件<mbean>標簽的name屬性。ManagedBean managed = registry.findManagedBean("Hello");//創建ObjectNameObjectName helloName = new ObjectName(managed.getDomain() + ":name=HelloWorld");//得到ModelMBeanModelMBean hello = managed.createMBean(new Hello());//注冊MBeanserver.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)接著創建MBeanServer的方式也不同了 現在:MBeanServer server = registry.getMBeanServer(); 以前: MBeanServer server = MBeanServerFactory.createMBeanServer(); (3)Hello相應的ObjectName創建也略不相同。主要是域名在XML描述文件里設置好了。 現在:ManagedBean managed = registry.findManagedBean("Hello");
    ???? ObjectName helloName = new ObjectName(managed.getDomain() + ":name=HelloWorld");
    以前:ObjectName helloName = new ObjectName("chengang:name=HelloWorld") (4)得到MBean的方式也不同,這里就是關鍵的不同點 現在:ModelMBean hello = managed.createMBean(new Hello()); 以前:Hello hello = new Hello(); 注意:為什么現在要比以前多一個createMbean步驟呢,就是因為現在的寫法并沒有寫Mbean,所以需要動態才需要生成一個。而以前就直接把new Hello()注冊到mbean server就可以了,server會自動找到它的HelloMBean接口文件。 也就上面四點區別,其他代碼完全一樣。測試和查看效果的方法和以前一樣,在此不累述了。我們來看看界面情況有那些變化(紅圈部份)。

     由圖可見commons Modeler為Hello動態生成了一個MBean接口:BaseModelBean

    [JMX一步步來] 6、模型Bean:Model Bean

    文/陳剛? from www.chengang.com.cn at 2005-12-26 在上一節是用apache的commons-modeler來開發的一個model,只不過commons-modeler幫助我們實現了很多的代碼,而我們只需要寫描述XML文件就行了。這一節,來一個實打實的Model Bean,不借助任何第三方工具包。例子還是沿用Hello這個類,以便于和以前的實現相比較。 一、Model MBean實例 1、Hello.java還是和以前的一樣。這里它沒有再加上一個MBean接口了,只是一個很普通的類。 public class Hello{private String name;public String getName() {return name;}public void setName(String name) {this.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(); import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import javax.management.modelmbean.RequiredModelMBean; import com.sun.jdmk.comm.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這個類是要我們自己來實現的,也是寫model Bean最麻煩的地方,它主要是返回一個RequiredModelMBean類,此類主要包括了一個ModelMBeanInfo類的信息。在ModelMBeanInfo中定義了所有對需要管理的屬性和方法的描述。具體代碼如下: 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() {
    ??????? //
    ??????? //??????????????????????? 屬性??????????????????????????????????????? //
    ??????? //
    ??????? // 構造name屬性信息
    ??????? ModelMBeanAttributeInfo nameAttrInfo = new ModelMBeanAttributeInfo(//
    ??????????????? "Name", // 屬性名???????
    ??????????????? STRING_CLASS, //屬性類型????
    ??????????????? "people name", // 描述文字??????
    ??????????????? READABLE, WRITABLE, !BOOLEAN, // 讀寫??????
    ??????????????? null // 屬性描述子
    ??????? ); //
    ??????? //??????????????????????? 方法??????????????????????????????????????? //
    ??????? //
    ??????? //構造 printHello()操作的信息???????
    ??????? ModelMBeanOperationInfo print1Info = new ModelMBeanOperationInfo(//
    ??????????????? "printHello", //
    ??????????????? null, //??
    ??????????????? null, //
    ??????????????? "void", //??
    ??????????????? MBeanOperationInfo.INFO, //????
    ??????????????? null //
    ??????? ); // 構造printHello(String whoName)操作信息?????
    ??????? ModelMBeanOperationInfo print2Info;
    ??????? MBeanParameterInfo[] param2 = new MBeanParameterInfo[1];
    ??????? param2[0] = 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[] { // 所有的屬性信息(數組)
    ??????????????? nameAttrInfo },//只有一個屬性
    ??????????????? null, // 所有的構造函數信息??
    ??????????????? new ModelMBeanOperationInfo[] { // 所有的操作信息(數組)
    ??????????????????????? print1Info,
    ??????????????????????? print2Info },//
    ??????????????? null, // 所有的通知信息(本例無)
    ??????????????? null//MBean描述子
    ??????? );
    ??????? return mbeanInfo;
    ??? }
    } 4、看效果的方法和以前一樣,運行HelloAgent,用瀏覽器打開:http://localhost:8082 。效果圖和standard mbean一樣,就不再帖出來了,去第一篇去看吧http://blog.sohu.com/members/somebody076/545896.html 二、總結 我們發現模型Mbean(Model MBean)要比標準MBean(standard mbean)復雜多了,那有什么理由讓我們選擇使用模型MBean嗎?我認為,最大的理由就是模型MBean可以動態配置。試想一下這個應用場景:由于安全或其他原因,系統要把某個MBean公開的可管理方法隱藏起來。這時,如果你是用標準MBean,這需要修改接口類,然后重新編譯發布;如果用Apache commons-modeler來寫的模型MBean,則只需要修改XML文件就行了,不需要重新編譯發布(可能要重啟一下系統)。這就是模型Mbean優勢之所在了。

     細心的人會發現動態MBean和這一節的模型Mbean非常相似,但它們還是有很大不同的:動態MBean沒有Hello類,它要自己實現Hello類中的方法邏輯。

    ?

    [JMX一步步來] 7、用JDK5.0的JConsole來連接MBean

    文/陳剛? from www.chengang.com.cn at 2005-12-26 前面所有看效果都是通過Html網頁來看的。JDK5.0自帶了一個jmx客戶端,叫jconsole,位于c:\jdk\bin\jconsole.exe。我們來用用這個客戶端來連接Mbean Server。 一、vm參數方式 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服務 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 com.sun.jdmk.comm.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 三、總結   連接MBeanServer的方式除了Html、JConsole,還有一些第三方的客戶端,比較有名的是MC4j,通過這些客戶端我們可以很容易去訪問MBean。這也就是我們為什么要用JMX的其中一個原因:試想如果我自己搞一套標準,勢必要自己開發一個客戶端,那會是一個不小的工作量。

    [JMX一步步來] 8、編寫程序來連接MBean

    文/陳剛? from www.chengang.com.cn at 2005-12-26 前面用Html、jconsole等方法連接上了MBeanServer,并能夠通過這些界面來操縱MBean。但有時我們需要不借助這些客戶端,而是在自己的程序來操縱這些MBean,這就要求我們知道如何在代碼里連接MBean。 基于上一篇為jconsole而修改的例子,給出一個示例的客戶端程序,基本的操作都有了: 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 + "] = " + domains[i]);} ??????? //MBean的總數System.out.println("MBean count = " + mbsc.getMBeanCount()); ??????? //對name屬性的操作(屬性名的第一個字母要大寫)mbsc.setAttribute(mbeanName, new Attribute("Name", "Chen.Gang"));//設值System.out.println("Name = " + mbsc.getAttribute(mbeanName, "Name"));//取值 ??????? //得到proxy代理后直接調用的方式HelloMBean proxy = (HelloMBean) MBeanServerInvocationHandler.newProxyInstance(mbsc, mbeanName, HelloMBean.class, false);proxy.printHello();proxy.printHello("陳剛"); ??????? //遠程調用的方式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的ObjectNameSystem.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);//關閉MBeanServer連接jmxc.close();} } 運行后的效果如下: Domains:---------------
    ?Domain[0] = HelloAgent
    ?Domain[1] = JMImplementation
    ?Domain[2] = 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, Chen.Gang
    Hello , 陳剛
    Hello World, Chen.Gang
    Hello , 子在川上曰

    [JMX一步步來] 9、基于JBoss來寫MBean

    文/陳剛? from www.chengang.com.cn at 2005-12-26 前面都是用JDK自帶的JMX實現來寫的MBean,JMX的實現不獨SUN一家,JBOSS也有自己的JMX實現。如果你使用JBOSS來做WEB服務器,那么基于JBOSS的實現來寫MBean,是一個不錯的選擇。象我們公司就是用JBOSS的,因此所有MBean都是基于JBoss來寫的。基于JBoss的MBean和基于SUN的MBean有什么不同嗎?有一些不同之外,但絕大部份都一樣。 下面是我最早發的一篇關于JMX的文章,是我對公司所做項目的筆記,它上面的JMX例子就是基于JBOSS的。博客搬了幾次家,文章刪的刪丟的丟,但這篇文章還保留著,簡單修改一下,再帖上吧。

    一、? HelloWorld實例

    1、準備工作

      JBOSS實現了JMX規范,這個實例是基于JBOSS來實現的。請先去下載一個JBOSS,我是jboss-3.2.6,下載地址:http://www.jboss.com/downloads/index#as。這個實例需要JBOSS的兩個JAR包的支持:jboss-system-3.2.6.jarjboss-jmx-3.2.6.jar,如果你和我一樣用Eclipse來開發(推薦),那么把這個兩個包加入到項目的庫引用中(加入到庫引用的方法參考前面兩章)。

    2、程序代碼

      假設我們有一個叫message的屬性要需要經常進行改動配置的,那么我們就把它寫成一個MBean

    1HelloWorldServiceMBean接口

      在寫MBean之前,我們先需要寫一個MBean接口,接口里的方法都是屬性的set/get方法。這個接口必須繼承接口ServiceMBean


    import org.jboss.system.ServiceMBean;
    public interface HelloWorldServiceMBean extends ServiceMBean {
    ??? String getMessage();
    ??? void setMessage(String message);
    }

    2、HelloWorldService實現類

      然后寫出HelloWorldServiceMBean接口的實現類HelloWorldService,這個實現類還必須繼承ServiceMBeanSupport類。這種類再簡單不過了,就是屬性和相應的set/get方法,EJB中叫實體類、Hibernate中叫POJO。

    import org.jboss.system.ServiceMBeanSupport;
    public class HelloWorldService extends ServiceMBeanSupport implements HelloWorldServiceMBean {
    ??? private String message;
    ??? public String getMessage() {
    ??????? System.out.println("getMessage()=" + message);
    ??????? return message;
    ??? }

    ??? public void setMessage(String message) {
    ??????? System.out.println("setMessage(" + message + ")");
    ??????? this.message = message;
    ??? }
    }

    3、配置文件jboss-service.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <server>
    ??? <mbean code="example.mbean.HelloWorldService" name="www.chengang.com.cn:service=HelloWorld">
    ??????? <attribute name="Message">Hello World</attribute>
    ??? </mbean>
    </server>

    說明:

    l?code項指向MBean的實現類HelloWorldService
    l?name項是一個名稱,格式一般是:[說明性文字]:service=[類名]
    l?attribute是為屬性設置初始值,這樣當JBOSS一加載HelloWorldService類時,message屬性就有了一個初始值Hello World。注意Message的第一個字母必須是大寫。

    二、將實例部署到JBOSS

      在jboss-3.2.6\server\default\deploy目錄下創建一個hello.sar目錄,然后創建如下目錄文件結構:

    hello.sar
    |----example
    |?????? ???? |----mbean
    |?????????????????? ?|----HelloWorldService.class? (注意:是*.class,不是*.java)
    |??????????????????? |----HelloWorldServiceMBean.class
    |----META-INF
    ???????????? |----jboss-service.xml

    其他說明:

    l?也可以將hello.sar目錄用zip格式壓縮成一個同名的hello.sar文件,放到jboss-3.2.6\server\default\deploy目錄下。
    l?JBOSS支持熱部署,也就是說你在布置這個目錄時并不需要重啟JBOSS

    三、MBean的效果 打開網址:http://127.0.0.1:8080/jmx-console/ ,出現下圖

    然后單擊“service=HelloWorld”項打開詳細頁面如下:

    將“HelloWorld”改成“Hello WorldChenGang”,再單擊“Apply Changes”應用修改,得到如下效果:

    四、其他類如何使用Messag屬性

      現在我們可以通過一個自動提供的WEB頁面來設置Message屬性了,接下來的問題是:“在其他類中應該如何得到Message的屬性值”。MBeanJBoss是只保留一個MBean的實例(單例模式?),也就是說問題轉成我們如何去取得這個唯一實例。例程如下:

    1、創建一個使用到Message屬性的類

    import org.jboss.mx.util.MBeanProxyExt;
    import org.jboss.mx.util.ObjectNameFactory;
    public class Client {
    ??? public void go() {
    ??????? HelloWorldServiceMBean mbean = (HelloWorldServiceMBean) MBeanProxyExt.create(HelloWorldServiceMBean.class, ObjectNameFactory.create(www.chengang.com.cn:service=HelloWorld));
    ????????String msg = mbean.getMessage();
    ??????? System.out.println("Client.go()=" + msg);
    ??? }
    }?

    注意:go方法里是三句。第一句比較長,它是根據jboss-service.xml文件中設置的MBean名稱,來取得此MBeanJBOSS中的實例。

    2、在Mbean中加一個相應的調用Client.go的方法

     在HelloWorldServiceMBean接口中加入一句:

    void callGo();

    HelloWorldService類中加入現實方法:

    ??? public void callGo() {
    ??????? new Client().go();
    ??? }

    3、更新布署

    ?? 將三個類的class文件:Clien.classHelloWorldServiceMBean.classHelloWorldService.class,更新到JBOSShello.sar\example\mbean目錄下。然后重啟JBOSS

    4、查看效果

    ?? 打開JBOSS提供的MBean設置頁面,如下,發現多了一個callGo

    單擊callGo項后的invoke按鈕,得到如下的DOS輸出:

    五、其他說明

    l?本實例僅演示了一個Message屬性,你當然可以在HelloWorldService中加入更多屬性,別忘了在HelloWorldServiceMBean接口也加入相應的set/get方法。
    l?本實例的message屬性是String類型的,但JMX也支持其他的類型,甚至是XML信息。對于jboss-service.xml中的XML信息,這時屬性類型要求是org.w3c.dom.ElementJMX將它封裝成了一個XMLDOM對象。
    l?回顧一下,JMX也是將配置信息寫在了一個文件(jboss-service.xml文件)里嘛,相對于將配置文件寫到*.properties文件的方式,它似乎也沒什么新鮮的地方。但通過本章實例我們可以看到JMX的一些好處:我們不用寫代碼去讀配置文件的信息,而且JMX支持的屬性類型是多種多樣的(如上面說的org.w3c.dom.Element)。更重要的是JMX還提供了一整套的屬性之前互相訪問、互相調用的功能,這個HelloWorld實例所反映的只是冰山一角而已。

    六、參考資料:http://www.huihoo.com/java/jmx/jmx_base.html 

    ?

    總結

    以上是生活随笔為你收集整理的JMX一步步来的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。