利用
JBossMX
開發標準
MBean
原文(http://www.ebook520.com/showbooktext.asp?id=2090&backcolor=E7F4FE&backsize=15)
???JBoss
服務器是建立在
JBoss
的
JMX
實現工具(
JBossMX
)基礎上的,訪問
JBoss
網站(
http://www.jboss.org
)可以下載到獨立的
JBoss JMX
實現工具軟件包
。將下載到的
jbossmx-1.1.2.zip
壓縮包解壓之后,把下列
jar
文件添加到
CLASSPATH
中:
jbossmx-1.1.2/jbossmx-1.1.2/lib/jboss-jmx.jar
jbossmx-1.1.2/jbossmx-1.1.2/lib/jboss-jmx-core.jar
JBOSS_HOME/client/gnu-regexp.jar
JBOSS_HOME/client/jbossall-client.jar
標準
MBean
在
JBoss
中使用范圍最廣,
JBoss
中的許多組件都是利用標準
MBean
開發的。
1
.計數器
MBean
下面是一個計數器
MBean
的開發示例。
(
1
)確定
MBean
的接口。
分析計數器的功能,確定了兩個方法,
即
add()
和
get()
,
add()
負責加數,
get()
負
責加數并取回總數:
package
com.liuyang.jmx.mbeans.counter;
public interface
CounterMBean {
??? public void add(int num);
??? public int get(int num);???
}
從代碼中可以看到,開發標準
MBean
的
MBean
接口和開發普通接口除了需要在
MBean
類名稱后面加上“
MBean
”之外,沒有其他區別。
(
2
)實現
MBean
接口。
CounterMBean
是一個標準
MBean
,所以
MBean
實現類的名稱必須和
MBean
接口
之間遵守標準
MBean
的命名規范,所以
CounterMBean
的實現類
Counter
比
CounterMBean
少了尾部的
MBean
部分,下面是
Counter
的實現代碼:
package
com.liuyang.jmx.mbeans.counter;
public
class Counter implements CounterMBean {
????????????????????int
sum = 0;
public
void add(int num) {
sum+=num;
}
public
int get(int num) {
sum+=num;
return
sum;
}
}
從代碼中也可以看到,標準
MBean
實現類與普通的
Java
程序也沒什么區別。
(
3
)利用
JMX API
編寫調用
CounterMBean
的程序。
JMX API
是
Sun
公司為
JMX
技術所設計的一套用來開發
JMX
應用的編程接口,通過
JMX API
可以管理和控制前面開發的
CounterMBean
資源。下面是利用
JMX API
編寫調用
CounterMBean
的程序代碼:
package
com.liuyang.jmx.mbeans.counter;
import
javax.management.MBeanServer;
import
javax.management.MBeanServerFactory;
import
javax.management.ObjectName;
public
class CounterServer {
???? public
static
void main(String[] args) throws Exception {
MBeanServer server = MBeanServerFactory.createMBeanServer();
ObjectName name = new ObjectName("book.liuyang:service=Counter");
server.registerMBean(new Counter(), name);???
String[] sig1 = {"int"};
Object[] opArgs1 = {new Integer(3)};
Object result1 = server.invoke(name, "add", opArgs1, sig1);
System.out.println(result1);?????
?
String[] sig2 = {"int"};
Object[] opArgs2 = {new Integer(0)};
Object result2 = server.invoke(name, "get", opArgs2, sig2);
System.out.println(result2);?????????????
}
}
2
.
ObjectName
ObjectName
代表一個
MBean
對象的名,創建一個
ObjectName
需要符合
MBean
的命名規范,例如:
ObjectName name = new ObjectName("book.liuyang:service=Counter");
3
.
MBeanServer
在
CounterServer
程序中,首先創建的
MBeanServer
這個對象代表前文中介紹的
MBean
服務器,它負責管理
MBean
資源,每個
MBean
資源可以被注冊到
MBeanServer
之中:
server.registerMBean(new Counter(), name);
通過
MBeanServer
的
invoke
方法還可以調用一個
MBean
,在調用時需要傳遞一些與調用有關的參數:
Object result1 = server.invoke(name, "add", opArgs1, sig1);
其中:
name
是被調用對象的對象名。
"add"
要求
調用被調對象的方法名稱。
opArgs1
是一個數組,包含著的每個數據將被作為參數傳遞到被調方法。
sig1
是
一個數組,包含著將被作為參數傳遞的每個數據的數據類型。
調用之后返回的對象包含著執行的結果。
4
.
MBeanServerFactory
MBeanServerFactory
是產生
MBeanServer
的工廠類,使用的
JMX
實現工具不同,通過
MBeanServerFactory
創建的
MBeanServer
實現對象也不同。如果
MBeanServer
已經被創建了,那么可以通過下面的方法獲取:
MBeanServer server = MBeanServerFactory.newMBeanServer();
通過這個實例,可以了解到使用
MBeanServer
來控制
MBean
的基本方法,下面的
用戶查詢
MBean
將進一步介紹通過
MBeanServer
對
MBean
的屬性進行查詢的方法。
5
.用戶查詢
MBean
首先,確定
MBean
的接口。
用戶查詢
MBean
中的用戶是這個
MBean
所代表的對象,這個設計的用戶包括名稱和角色,在這個例子中將對這兩個屬性進行監控,這是
JMX
為開發者提供的一種機制,所有被管理的
MBean
都在
MBeanServer
的控制之中,這個控制不僅包括上個計數器實例中所演示的方法調用功能,也包含對這些
MBean
的相關信息進行考察的功能。
package
com.liuyang.jmx.mbeans.user;
public
interface UserMBean {
??? public String getName();
??? publicvoid setName(String name);
??? public
String getRole();
????public
void setRole(String string);
}
UserMBean
中被設定了兩個屬性:
name
和
role
,并遵照
Java Bean
的規則為它們提供了
get()
和
set()
方法。通過這兩個方法可以設定
UserMBean
的兩個屬性。
package
com.liuyang.jmx.mbeans.user;
public
class User implements UserMBean? {
??? private
String name = "";
??? private String password? = "";
??? private
String role? = "";
??? public String getName() {
??? return name;
??? }
??? publicvoid setName(String name) {
??????? this.name = name;
??? }
public
String getRole() {
return
role;
}
public
void setRole(String string) {
role = string;
}
}
User
這個類只是以最簡單的方式實現了
UserMBean
接口。
下
面
的
UserQueries
演示了
通過
MBeanServer
對
MBean
的屬性進行查詢的方法,代碼如下:
package
com.liuyang.jmx.mbeans.user;
import
java.util.Iterator;
import
java.util.Set;
import
javax.management.Attribute;
import
javax.management.MBeanServer;
import
javax.management.MBeanServerFactory;
import
javax.management.ObjectName;
import
javax.management.Query;
import
javax.management.QueryExp;
public
class UserQueries {
? publicstaticvoid main(String[] args) throws Exception {
??? MBeanServer server = MBeanServerFactory.createMBeanServer();
????ObjectName user1 = new ObjectName("book.liuyang:Name=user1");
??? ObjectName user2 = new ObjectName("book.liuyang:Name=user2");
??? server.createMBean("com.liuyang.jmx.mbeans.user.User", user1);
??? server.createMBean("com.liuyang.jmx.mbeans.user.User", user2);
??? server.setAttribute(user1, new Attribute("Name", "user1"));
??? server.setAttribute(user2, new Attribute("Name", "user2"));
??? server.setAttribute(user1, new Attribute("Role", "code"));
??? server.setAttribute(user2, new Attribute("Role", "test"));
QueryExp exp = Query.match(Query.attr("Name"),Query.value("user1"));
ObjectName scope = new ObjectName("book.liuyang:*");???
Set set????? = server.queryNames(scope, exp);???
Iterator it? = set.iterator();
System.out.println("
下列
MBean
的名字是:
user1");
while
(it.hasNext()) {
? System.out.println(it.next());???
}
scope = new ObjectName("book.liuyang:*");???
exp = Query.initialSubString(Query.attr("Role"),Query.value("t"));
set?? = server.queryNames(scope, exp);???
it??? = set.iterator();
System.out.println("
下列
MBean
的角色是:
test");
while
(it.hasNext()) {
? System.out.println(it.next());
}
}
}
在
UserQueries
中創建了兩個
MBean
對象:
server.createMBean("com.liuyang.jmx.mbeans.user.User", user1);
這是
MBeanServer
通過
MBean
類的名稱創建
MBean
實例的方法。
然后分別設置它們的屬性:
server.setAttribute(user1, new Attribute("Name", "user1"));
一個
Attribute
對象代表一個屬性。
JMX API
為查詢服務建立標準的接口方法,第一步是建立查詢表達式:
QueryExp exp = Query.match(Query.attr("Name"),Query.value("user1"));
這個查詢表達式是以全匹配的方式進行的,
JMX
還支持部分模糊查詢的功能:
exp = Query.initialSubString(Query.attr("Role"),Query.value("t"));
initialSubString
建立的查詢方法只會匹配名稱的開始部分,在這里只要以“
t
”開頭的值都會被匹配。
然后,通過一個
MBean
名稱對象來代表查詢范圍:
ObjectName scope = new ObjectName("book.liuyang:*");
最后,通過
MBeanServer
執行查詢表達式的操作,得到結果:
Set set = server.queryNames(scope, exp);??
運行
UserQueries
可以得到查詢結果。