三、创建MBean
为了能够管理Web应用的资源,首先要使资源能够被管理,按照JMX规范的要求,我们将资源封装成MBean,实际上也就是为Web应用添加可管理性。
获得MBeanServer的实例以后,就可以编写自己的MBean了,根据JMX的规范,MBean有标准的和动态的两种主要类型,这里就不赘述了,具体可以参看JMX的规范(http://)。有两种用于特殊用途的动态 MBeans:模型MBean和开放MBean。模型 MBean (Modle MBean)提供了"现成的"MBean 实现,您可以使用它来快速地利用任何 JMX 可管理资源。它是预制的、通用的和动态的 MBean 类,并且提供了参考实现,已经包含了所有必要缺省行为的实现 - 允许您在运行时添加或覆盖需要定制的那些实现。这使得基于 Java 的、非工具化的资源能够在运行时提供保证兼容的 MBean 虚包,使它们能够通过 JMX 体系结构进行管理。
在Web应用中,资源是多元化,有运行实例,静态文件,甚至是设备或者是硬件状态,那么我们把这些资源可以分为两类,一些资源需要进行动态的管理监控(如登陆用户数,数据库连接监控,即时日志等),一些则是静态资源,只需要进行静态的管理(系统配置文件,日志级别等),要管理这些不同类型的资源,这就要求MBean一方面能够直接调用运行实例提供的接口进,另一方面又希望MBean自身能够提供静态资源的管理,模型MBean能够很好的满足这样的要求,并且对于新增需要管理的资源,提供了很好的灵活性和可扩展性,因此推荐模型MBean作为Web应用首选。当然具体采用何种类型的MBean,需要结合不同的应用,或者多种类型的MBean相结合使用。顺便提一点,采用不同类型的MBean,对于管理客户端是透明的,也就是说客户端使用一致的访问方法来访问MBean的属性和方法,这也是JMX的一个优点。
为了更好的观察如何实现对静态资源和动态资源的管理,本文编写了两个MBean,分别实现对数据库连接属性实现静态和动态的管理。静态管理的MBean的目的是实现对数据库配置文件修改,这样当Web应用重启后,会使用新的数据库配置,我们采用 MBean的提供对资源的直接操作进行实现。动态管理的MBean目的是对已经实例化的数据库连接对象的属性进行修改,这样在不重新启动Web应用的情况下,改变数据库连接。
1、实现管理配置文件的MBean。
JDBCConfig是一个Model MBean,它的作用是对config.properties文件封装成MBean,该MBean包括四个属性及其相关的getter和setter和一个save方法,其中save方法的作用是属性存入配置文件,从而实现了通过MBean直接对配置文件进行操作。这个例子中的MBean继承了 BaseModelMBean类,该类实现了javax.management.ModelMBean接口,我们可以在commons- modeler.jar中找到BaseModelMBean类,commons-modeler.jar是tomcat4.x中使用的一个开放源码的包。
import javax.management.MBeanException;
import javax.management.RuntimeOperationsException;
import org.apache.commons.modeler.BaseModelMBean;
import java.io.*;
import java.util.Properties;
public class JDBCConfigMBean extends BaseModelMBean {
private String driver;
private String username;
private String password;
private String dburl;
private static final String CONFIG_FILEPATH =
"c:\\myweb\\conf\\config.properties";
/////////////////////////////////////////////////////
//constructor
/////////////////////////////////////////////////////
public JDBCConfig()
throws MBeanException, RuntimeOperationsException {
super();
init();
}
private void init() {
InputStream in = null;
try {
Properties prop = new Properties();
in = new BufferedInputStream(
new FileInputStream(CONFIG_FILEPATH));
prop.load(in);
driver = prop.getProperty("driver");
dburl = prop.getProperty("dburl");
username = prop.getProperty("username");
password = prop.getProperty("password");
in.close();
} catch (Exception e) {
try {
if (in != null)
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
////////////////////////////////////////////////
//getter and setter
////////////////////////////////////////////////
////////////////////////////////////////////////
//public method
////////////////////////////////////////////////
public String save() {
OutputStream out = null;
try {
out = new BufferedOutputStream(new
FileOutputStream(CONFIG_FILEPATH));
Properties prop = new Properties();
prop.setProperty("driver", driver);
prop.setProperty("dburl", dburl);
prop.setProperty("username", username);
prop.setProperty("password", password);
prop.store(out, "---jdbc config---");
out.close();
return "save success!";
} catch (Exception e) {
try {
if (out != null)
out.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
return "save error!";
}
}
}
