项目中,我们经常使用配置文件,但是里面的某些属性经常变化,特别是测试的时候,某些值不稳定。虽然可以直接停掉服务器,修改该值,然后重启(不需要编译),总归是比较麻烦。所以最好能在不停服务器的情况下,即时修改然后自动更新内存里面的值。所以我这里使用了JMX,之所以还是使用Spring,是因为我的项目使用MAVEN管理,而JMX的jar包,几乎没有仓库有这个包。
我的Spring注解的MBean:
package com.cpinec.integration.jmx;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Properties;
@Component
@ManagedResource(objectName= "com.cpinec.integration.jmx:type=JMX,name=integrationConfigMBean",
description= "Integration Properties Managed Bean" )
public class IntegrationConfigMBean {
public static final Logger log = LoggerFactory.getLogger(IntegrationConfigMBean.class);
public IntegrationConfigMBean(){
Resource resource = new ClassPathResource("/integration.properties");
try {
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
log.debug("Now set property values to MBean instance.");
setJiraWorkflowIssueUrl(properties.getProperty("jira.workflow.issue.url"));
setJiraWorkflowProject(properties.getProperty("jira.workflow.project"));
setJiraServerUsername(properties.getProperty("jira.server.username"));
} catch (IOException e) {
log.debug("MBean Constructor has error " + e.getMessage());
e.printStackTrace();
}
}
public String jiraWorkflowProject;
public String jiraWorkflowIssueUrl;
public String jiraServerUsername;
@ManagedAttribute
public void setJiraWorkflowProject(String project){
this.jiraWorkflowProject = project;
}
@ManagedAttribute(description="Jira workflow project name")
public String getJiraWorkflowProject(){
return jiraWorkflowProject;
}
@ManagedAttribute(description="Jira workflow issue creation RESTful URL")
public String getJiraWorkflowIssueUrl() {
return jiraWorkflowIssueUrl;
}
@ManagedAttribute
public void setJiraWorkflowIssueUrl(String jiraWorkflowIssueUrl) {
this.jiraWorkflowIssueUrl = jiraWorkflowIssueUrl;
}
@ManagedAttribute(description="Jira admin user name")
public String getJiraServerUsername() {
return jiraServerUsername;
}
@ManagedAttribute
public void setJiraServerUsername(String jiraServerUsername) {
this.jiraServerUsername = jiraServerUsername;
}
}
Spring配置文件,component-scan需要扫描Spring JMX的annotations注解过的包,<context:mbean-export/> 是注册这个MBean到JMX Server:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- Detects annotations like @Component, @Service, @Controller, @Repository, @Configuration -->
<context:component-scan base-package="com.cpinec.integration.jmx, com.cpinec.integration.service" />
<context:mbean-export/>
</beans>
其他需要使用这个MBean的代码:
@Service
public class JiraAction extends Action {
public static final Logger log = LoggerFactory.getLogger(JiraAction.class);
@Autowired
private IntegrationConfigMBean mBean;
public JiraIssue createIssue(JiraIssue issue){
StringBuffer sb = new StringBuffer(mBean.getJiraWorkflowIssueUrl());
sb.append("/").append(mBean.getJiraWorkflowProject()).append(".json");
return execute(issue, sb.toString());
}
}
然后编译打包工程,由于我使用的是内置在IntelliJ IDEA里面的Tomcat,尽管服务起来了,并能看到起运行在8080端口(如下图所示),直接打开JDK下面的JConsole,是看不到MBean里面的属性的。
为了能看到,必须将这个包拷贝出来,放到 Tomcat 的 webapps 文件夹下面,然后打开 catalina.bat 文件,修改 JAVA_OPTS 值,如下:
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
这里我们的认证方面的参数都是 false,方便测试。启动 tomcat, 然后打开DOS窗口,进入 JConsole 目录,打开它:
然后输入 localhost:8855, 端口号必须和 tomcat 的catalina.bat里面的 JAVA_OPTS 的 port 值相同。
点击连接按钮后,出现询问窗口,直接点击“不安全”按钮:
最后点击 “MBean” 页签,可以看到下面这些被监控的属性: