JMX(Java Management Extensions)是一个为应用程序植入管理功能的框架。JMX是一套标准的代理和服务,实际上,用户可以在任何Java应用程序中使用这些代理和服务实现管理。
应用场景有很多,其中就有配置管理,其他的应用场景可以自行百度,别的什么概念就不多说了。
下面程序一列就知道JMX是个什么东西了。
撸代码:
一:基于JConsole管理
项目所需建的类有一下怎么几个:
需要用到的jar包可以在这下载,只需引入jdmkrt.jar
1.首先新建的是一个接口PersonMBean,该接口命名有严格的要求,也就是要暴露出去的实现类名+MBean:
package com.cwh.jmx.mbean;
public interface PersonMBean {
public String getName();
public void setName(String name);
public int getAge();
public void setAge(int age);
public void helloWorld(String str);
}
package com.cwh.jmx.mbean;
//监控的类和MBean接口必需在同一包下
public class Person implements PersonMBean {
private String name;
private int age;
public String getName() {
System.out.println("get name:"+this.name);
return this.name;
}
public void setName(String name) {
this.name=name;
System.out.println("set name:"+name);
}
public void helloWorld(String str) {
System.out.println("helloworld:"+str);
}
public void setAge(int age) {
this.age=age;
System.out.println("set age:"+age);
}
public int getAge() {
System.out.println("get age:"+this.age);
return this.age;
}
}
package com.cwh.jmx.agent;
import java.lang.management.ManagementFactory;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import com.cwh.jmx.mbean.Person;
import com.sun.jdmk.comm.HtmlAdaptorServer;
public class PersonAgent {
public static void main(String[] args) throws JMException, Exception{
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName personName = new ObjectName("jmxBean:name=Person");
//create mbean and register mbean
server.registerMBean(new Person(), personName);
Thread.sleep(60*60*1000);
}
}
说明:ObjectName的命名规则是自定义的,但需遵循***:name=***,这样的命名规则
jconsole这个jar具体位置在jdk下的bin文件夹下,点击运行它:
说明:这里我们可以看到本地进程中我们看到了一个进程名为:com.cwh.jmx.agent.PersonAgent,这个也就是我们暴露出来的,选择然后点击链接即可打开管理页面;
5.进入到jconsole管理页面
5.1点击MBean可以看到我们上面编写的jmxBean:name=Person,这里的jmxBean也就是我们定义的,接着点击它可以看到以下内容:
5.2这里可以看到下面有Person这么个东西,这个Person也就是对应我们上面编写的jmxBean:name=Person,下面的属性及操作都是我们暴露出来的
点击属性Name:
在值得区域中输入我们的值,比如cwh回车,后台可以看到:
点击操作helloworld:
在String区域中输入比如cwh回车,后台可以打印:
二:基于HTML工具页管理
上面也就是JMX的一个基本例子,基于jconsole来管理的,那如果在实际生产环境中,生产环境不给提供远程连接,那么该怎么办呢?
这里我们可以采用基于HTML控制台来管理
1.实现很简单,修改PersonAgent即可:
package com.cwh.jmx.agent;
import java.lang.management.ManagementFactory;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import com.cwh.jmx.mbean.Person;
import com.sun.jdmk.comm.HtmlAdaptorServer;
public class PersonAgent {
public static void main(String[] args) throws JMException, Exception{
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName personName = new ObjectName("jmxBean:name=Person");
//create mbean and register mbean
server.registerMBean(new Person(), personName);
//Thread.sleep(60*60*1000);
ObjectName adapterName = new ObjectName("PersonAgent:name=htmladapter");
HtmlAdaptorServer adapter = new HtmlAdaptorServer();
adapter.setPort(8082);
server.registerMBean(adapter, adapterName);
adapter.start();
}
}
3.从上面图可以看到,点击name=Person进入管理:
4.查看后台打印:
三:基于spring实现JMX
这里我们来实现一个基于spring+JMX来实现一个配置管理的demo
1.新建ConfigMBean
package com.cwh.jmx.mbean;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;
@Component
@ManagedResource(objectName= "ConfigJmx:type=JMX,name=ConfigMBean",
description= "Config Properties Managed Bean" )
public class ConfigMBean {
public static final Logger log = LoggerFactory.getLogger(ConfigMBean.class);
private static PropertiesConfiguration propConfig;
private static boolean autoSave = true;
public ConfigMBean(){
try {
propConfig = new PropertiesConfiguration("config.properties");
//自动重新加载
FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
strategy.setRefreshDelay(1);//自动更新加载1秒
propConfig.setReloadingStrategy(strategy);
//自动保存
propConfig.setAutoSave(autoSave);
log.debug("Now set property values to MBean instance.");
setDatasourceUsername((String) propConfig.getProperty("datasource.username"));
setDatasourcePassword((String) propConfig.getProperty("datasource.password"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private String datasourceUsername;
private String datasourcePassword;
@ManagedAttribute
public String getDatasourceUsername() {
return datasourceUsername;
}
@ManagedAttribute
public void setDatasourceUsername(String datasourceUsername) throws Exception {
this.datasourceUsername = datasourceUsername;
propConfig.setProperty("datasource.username", this.datasourceUsername);
}
@ManagedAttribute
public String getDatasourcePassword() {
return datasourcePassword;
}
@ManagedAttribute
public void setDatasourcePassword(String datasourcePassword) throws Exception {
this.datasourcePassword = datasourcePassword;
propConfig.setProperty("datasource.password", this.datasourcePassword);
}
}
说明:这里我们暴露出去的就是一个修改数据源的用户及密码的一个接口
2.在applicationContext.xml添加如下内容:
<context:component-scan base-package="com.cwh.jmx.mbean" />
<context:mbean-export/>
3.1这里需要注意下,启动tomcat前需要修改tomcat下的catalina.bat文件,修改内容如下:
rem ---- Added by Allen for JMX MBeans discovered by JConsole
set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8855 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
添加位置如下:
3.2还有需要注意的是启动tomcat不要在eclipse下启动,直接在cmd的中运行startup.bat来启动
4.打开JConsole,管理
说明:这里的端口对应上面我们在catalina.bat填写的端口8855,ip请用真实ip
4.1这里可以看到我们所暴露出来的一些操作:
4.2测试:
把密码改了:设置为空,打开tomcat下项目的classpath下的config.properties文件,发现确实修改成功:
5.如果不想用jconsole管理,想用页面管理,配置很简单,和上面的第二大点配置差不多:
在我们第三点配置的基础上,我们的构造函数中添加如下代码即可,同时需引入jdmkrt.jar:
HtmlAdaptorServer html = new HtmlAdaptorServer();
ObjectName adapterName = new ObjectName("ConfigAgent:name=htmladapter");
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
html.setPort(8088);
server.registerMBean(html, adapterName);
html.start();//启动页面管理