Spring 2.x jmx 及应用(3)client连接和通知

首先让别的程序连接到mbeanServer必须有个serverConnectior
只需在mbeanServer的配置文件中定义一个
[code]
<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean"/>
[/code]
即可完成对连接的监听
这样设定是使用默认的及jmxmp协议service:jmx:jmxmp://localhost:9875
你也可以通过使用其他jmx支持的协议RMI,IIOP, Burlap,Hessian,SOAP等,
只要设定objectName和serviceUrl及可
为了方便我们常用的还是jmxmp.

server配置好到client了。
client同样需要一个连接器
[code]
<bean id="clientConnector"
class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean">
<property name="serviceUrl"
value="service:jmx:jmxmp://localhost:9875" />
</bean>
[/code]
简单直观的配置没什么可以说的。

操作mbean.
无论你使用那种方式注册和描述mbean,访问和操作mbean的方式只有一种。就是通过interface创建的代理来访问。
[code]
<bean id="proxy"
class="org.springframework.jmx.access.MBeanProxyFactoryBean">
<property name="objectName" value="mbean:name=testBean" />
<property name="proxyInterface"
value="com.xmlasia.spring.test.jmx.ICommentMBeanManager" />
<property name="server" ref="clientConnector" />
</bean>
[/code]
同样简单直观,这里注意proxyInterface不是数组类型。你只能设定一个interface,无论server是不是用interface暴露的,只要client的interface于mbeanServer中的匹配就能正确访问


如果你不是使用interface暴露的mbean的方法,当你调用不匹配的method时会有
org.springframework.jmx.access.InvalidInvocationException: Operation 'publicMessage' is not exposed on the management interface从客户段抛出。所以在实际应用时最

好能使用interface配置mbean.

测试
[code]
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("/jmxClientContext.xml");
ICommentMBeanManager o = (ICommentMBeanManager)context.getBean("proxy");
o.pause("testid");
o.shutDown();

while(true){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

[/code]
同样client的连接是不阻塞主线程的,同样需要保持主线程的活着。
调用上述代码就能看到server有调用mbean的方法。

通知
jmx有一种机制和向容器通知属性改变,首先我们需要了解NotificationListener
[code]
package com.xmlasia.spring.test.jmx;

import javax.management.Notification;
import javax.management.NotificationListener;

public class TestNotificationListener implements NotificationListener {

@Override
public void handleNotification(Notification notification, Object obj) {
System.out.println(notification);
}

}
[/code]
实现一个NotificationListener,可以看到NotificationListener是标准的jmx接口
当属性值改变时handleNotification将会调用。

使用MBeanExporter的notificationListenerMappings属性将listener和mbean进行mapping
[code]
<bean id="mBeanExporter"
class="org.springframework.jmx.export.MBeanExporter">
<property name="server" ref="mbeanServer" />
<property name="assembler" ref="assembler" />
<property name="beans">
<!-- 将mbean注册到mBeanExporter -->
<map>
<entry key="mbean:name=testBean"
value-ref="mbeanManager" />
</map>
</property>
<property name="registrationBehaviorName"
value="REGISTRATION_REPLACE_EXISTING" />
<property name="notificationListenerMappings">
<map>
<!--将所有listener mapping到所有mbean-->
<entry key="*">
<bean class="com.xmlasia.spring.test.jmx.TestNotificationListener" />
</entry>
</map>
</property>
</bean>
[/code]
key是同配符,也可以指定到某一个mbean

当我们在client调用.setClientStatus是handleNotification收到的
notification = javax.management.AttributeChangeNotification[source=mbean:name=testBean][type=jmx.attribute.change][message=AttributeChangeDetected]
一般情况下这样的通知没有意义,我们要将他filter掉。
[code]
package com.xmlasia.spring.test.jmx;

import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;

public class TestNotificationListener implements NotificationListener,
NotificationFilter {

@Override
public void handleNotification(Notification notification, Object obj) {
System.out.println(notification);
}

@Override
public boolean isNotificationEnabled(Notification notification) {
if (notification instanceof javax.management.AttributeChangeNotification)
return false;
else
return true;
}
}
[/code]
同样实现标准的jmx接口NotificationFilter
我们通过判断他的类型进行过滤。
改变配置文件。不使用notificationListenerMappings属性,改用notificationListeners
[code]
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

<bean id="mbeanManager"
class="com.xmlasia.spring.test.jmx.MBeanManager" />

<bean id="mbeanServer"
class="org.springframework.jmx.support.MBeanServerFactoryBean">
</bean>

<bean id="assembler"
class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource" />
</bean>

<bean id="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" />

<bean id="mBeanExporter"
class="org.springframework.jmx.export.MBeanExporter">
<property name="server" ref="mbeanServer" />
<property name="assembler" ref="assembler" />
<property name="beans">
<map>
<entry key="mbean:name=testBean"
value-ref="mbeanManager" />
</map>
</property>
<property name="notificationListeners">
<list>
<bean
class="org.springframework.jmx.export.NotificationListenerBean">
<constructor-arg ref="testNotificationListener" />
<property name="mappedObjectNames">
<list>
<value>mbean:name=testBean</value>
</list>
</property>
<property name="notificationFilter"
ref="testNotificationListener" />
</bean>
</list>
</property>
</bean>

<bean id="testNotificationListener" class="com.xmlasia.spring.test.jmx.TestNotificationListener"/>

<bean id="serverConnector"
class="org.springframework.jmx.support.ConnectorServerFactoryBean" />
</beans>
[/code]
完整的配置
我们注入一个spring为我们封装好的NotificationListenerBean,可以将listener,filter,还有objectname方便组织在一起。
这里要特别说明下mappedObjectNames是String[]类的,spring reference中的例子是错误的。

下面我们要自己发布notification
[code]
package com.xmlasia.spring.test.jmx;

import javax.management.Notification;

import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedOperationParameter;
import org.springframework.jmx.export.annotation.ManagedOperationParameters;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.export.notification.NotificationPublisher;
import org.springframework.jmx.export.notification.NotificationPublisherAware;

@ManagedResource
public class MBeanManager implements NotificationPublisherAware {
private int clientStatus;

private NotificationPublisher publisher;


@ManagedOperation(description = "pause a single proccess")
@ManagedOperationParameters( { @ManagedOperationParameter(name = "Name of proccess instance", description = "Mandatory") })
public void pause(String n) {
System.out.println("pause proccess id :" + n);
}

@ManagedOperation(description = "shut down the proccess")
public void shutDown() {
System.out.println("shutting down...");
}

public void publicMessage() {
System.out.println("public Message to monitor server");
}

@ManagedAttribute(description = "client status")
public int getClientStatus() {
return clientStatus;
}

@ManagedAttribute(description = "client status")
public void setClientStatus(int clientStatus) {
this.clientStatus = clientStatus;
publisher.sendNotification(new Notification("set",this,0,"client Status changed"));
}

@Override
public void setNotificationPublisher(
NotificationPublisher notificationPublisher) {
publisher = notificationPublisher;
}
}
[/code]
我们只需要implements NotificationPublisherAware 的setNotificationPublisher方法就可以方便的使用
自己的publisher,提供有用的信息到listener中。
Spring会在exporter创建mbean时帮我们传入NotificationPublisher。

Spring对jmx的封装已经看完了。从中可以学到很多Spring的思想和技巧,希望大家能给点意见。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值