`

Spring整合JMX

    博客分类:
  • JMX
 
阅读更多
Spring整合JMX
一、优点

1、可以自动探测实现MBean接口的MBean对象,而且可以将一个普通的Spring Bean注册为MBean;

2、定制管理MBean的接口,根据需要暴露特定管理MBean的操作;

3、使用注解定义MBean管理接口;

4、可以实现对本地和远程MBean的代理。

二、实现方式
基于配置文件的实现
  • 标准MBEAN
  •     定义接口
       
    XXXMBean(接口名以MBean结尾,接口中暴露了对外的方法) 

        接口实现
       
    XXX(注意实现的名称和接口之间的关系)

        配置文件
       
        <?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.5.xsd">              
        <!--MBean Server初始化 -->
        <bean id="mbeanServer" class="org.springframework.jmx.export.MBeanExporter">
            <!--MBean的探测策略,这里是AUTODETECT_ALL自动探测,默认值为AUTODETECT_ALL,所以这里可以不用配置 -->
            <property name="autodetectModeName">
                <value>AUTODETECT_ALL</value>
            </property>
            <!-- 如果不使用自动探测 ,这里是手动注册的配置 -->
            <property name="beans">
                <map>
                    <entry key="MBEAN_NAME" value-ref="xxx"/>
                </map>
            </property>
        </bean>
        <!--MBean初始化 其中的name="mydomain:xxx=XxxMBean"可以根据需要自行定义-->
        <bean id="xxx" class="com.sinosoft.one.demo.jmx.Xxx"/>
        <bean name="testMBean:xxx=XxxMBean" class="com.sinosoft.one.demo.jmx.XXX">
            <!--实现类中一些需要初始化的属性 -->
            <property name="propertyOne" value="val1"/>
            <property name="propertyTwo" value="val2"/>
        </bean>
    </beans>
        


    对于探测模式autodetectModeName属性,Spring提供了4个取值:

    AUTODETECT_NONE 不启用自动探测,需要手动向MBean Server进行注册,即通过MBeanExporter的beans属性进入注册;
    AUTODETECT_MBEAN 在当前IOC容器中进行查找MBean组件;
    AUTODETECT_ASSEMBLER 设置根据MBeanInfoAssembler的策略进行探测;
    AUTODETECTALL 自动探测,是AUTODETECTMBEAN和AUTODETECT_ASSEMBLER的并集。
  • 普通Bean注册为MBean
  • Bean的实现方式没什么需要特别注意的,主要是配置文件中的配置。
          配置文件
          
    <?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.5.xsd">              
        <!--MBean Server初始化 -->
        <bean id="mbeanServer" class="org.springframework.jmx.export.MBeanExporter">
            <!--MBean的探测策略,这里是AUTODETECT_ALL自动探测,默认值为AUTODETECT_ALL,所以这里可以不用配置 -->
            <property name="autodetectModeName">
                <value>AUTODETECT_ALL</value>
            </property>
            <!-- 对于普通的Bean ,需要在这里手动注册 -->
            <property name="beans">
                <map>
                    <entry key="MBEAN_NAME" value-ref="xxx"/>
                </map>
            </property>
        </bean>
        <!--普通Spring Bean初始化-->
        <bean id="xxx" class="com.sinosoft.one.demo.jmx.Xxx"/>
    </beans> 
           

    因为普通的Bean没有对应的MBean接口,所以默认情况下,该类中public的成员都会暴露出来,通过MBean Server可以管理。实际上,系统中MBean的某些属性或方法可能不需要暴露给外部进行管理,为了克服这种缺点,Spring提供了基于方法列表和接口定制的功能,可以将你所感兴趣的属性或方法暴露给外部管理。

          管理暴露的方法
                方法一:配置方法列表
          
    <!-- 定义assembler -->    
    <bean id="assembler" class="org.springframework.jmx.export.
                assembler.MethodNameBasedMBeanInfoAssembler">
        <!--配置方法列表 -->
        <property name="managedMethods"  value="display" />
    </bean>     

                方法二:接口定制
          
    package com.sinosoft.one.demo.jmx.interface;
    /**
     *定制对外方法的接口 
     */
    public interface MethodManagerInterface {
        public String display(String arguments);
    }
    
    
    <!-- 定义assembler -->    
    <bean id="assembler" class="org.springframework.jmx.export.
            assembler.MethodNameBasedMBeanInfoAssembler">
        <!--配置方法列表 -->
        <property name="managedInterfaces" >
            <list>
                <value>
                    com.sinosoft.one.demo.MethodManagerInterface
                </value>    
            </list>
        </property> 
    </bean>
         

    最后,在bean mbeanServer中添加assembler属性
    <property name="assembler" ref="assembler" />
  • 基于注解的实现
  • 下边是一个实现例子
     package com.sinosoft.one.demo.jmx;
    
        import org.apache.log4j.Level;
        import org.apache.log4j.Logger;
        import org.slf4j.LoggerFactory;
        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;
    
        /**
         * JMX实现的动态控制日志级别
         * 
         * @author gwt
         */
        @ManagedResource(objectName = LoggerManager.MBEAN_NAME, description = "It's a program to manage log4j ")
        public class LoggerManager {
            /**
             * MBean Name
             */
            public static final String MBEAN_NAME = "log4j:logger=Log4j";
    
            /**
             * 用来记录日志信息
             */
            private static org.slf4j.Logger managerLogger = LoggerFactory
                    .getLogger(LoggerManager.class);
    
            /**
             * 获取日志的默认级别
             * 
             * @return
             */
            @ManagedAttribute
            public String getRootLoggerLevel() {
                Logger logger = Logger.getRootLogger();
                String rootLevel = logger.getEffectiveLevel().toString();
                managerLogger.info("Level of the root logger is {}", rootLevel);
                return logger.getEffectiveLevel().toString();
            }
    
            /**
             * 设置日志的默认级别
             * 
             * @param newLevel
             */
            @ManagedAttribute(description = "set rootlogger's level")
            public void setRootLoggerLevel(String newLevel) {
                Logger logger = Logger.getRootLogger();
                if (!newLevel.equals(logger.getEffectiveLevel().toString())) {
                    logger.setLevel(Level.toLevel(newLevel));
                }
                managerLogger.info("设置日志默认级别为{}", newLevel);
            }
    
            /**
             * 获取指定工程的日志级别
             * 
             * @return
             */
            @ManagedAttribute(description = "get project log level")
            @ManagedOperationParameters({ @ManagedOperationParameter(name = "projectName", description = "project name") })
            public String getProjectLoggerLevel(String projectName) {
                return getLoggerLevel(projectName);
            }
    
            /**
             * 获取Logger的日志级别.
             */
            @ManagedOperation(description = "get appoint logger name ")
            @ManagedOperationParameters({ @ManagedOperationParameter(name = "loggerName", description = "Logger name") })
            public String getLoggerLevel(String loggerName) {
                Logger logger = Logger.getLogger(loggerName);
                return logger.getEffectiveLevel().toString();
            }
    
            /**
             * 设置logger级别
             * 
             * @param loggerName    日志名称
             * @param newLevel      新的等级
             */
            @ManagedAttribute
            @ManagedOperationParameters({
                    @ManagedOperationParameter(name = "loggerName", description = "logger name"),
                    @ManagedOperationParameter(name = "newLevel", description = "the level want to set") })
            public void setLoggerLevel(String loggerName, String newLevel) {
                Logger logger = Logger.getLogger(loggerName);
                logger.setLevel(Level.toLevel(newLevel));
            }
    
            /**
             * 设置工程logger级别
             * 
             * @param ProjectName   工程名
             * @param newLevel      新的等级
             */
            @ManagedAttribute
            @ManagedOperationParameters({
                    @ManagedOperationParameter(name = "projectName", description = "logger name"),
                    @ManagedOperationParameter(name = "newLevel", description = "the level want to set") })
            public void setProjectLevel(String ProjectName, String newLevel) {
                setLoggerLevel(ProjectName, newLevel);
            }
        }
    


    上面@ManagedResource表示指定该类的实例作为MBean注册到MBean Server中,然后可以通过对属性和方法分别使用@ManagedAttribute和@ManagedOperation来指定暴露的属性和方法。有关这些注解的详细内容,可以查阅相关文档。
        配置文件
    <?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: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/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
        <description>JMX服务端配置</description>
        <!-- 配置MBean自动注册 -->
        <context:mbean-export default-domain="demo" registration="replaceExisting" />
        <!-- Log4j控制的 MBean -->
        <bean class="com.sinosoft.one.demo.jmx.Log4jManager">
            <property name="projectLoggerName" value="com.sinosoft.one.demo"/>
        </bean>
    </beans>
    


    三、使用HttpURLConnection进行JMX访问
    在web.xml中添加配置
    <servlet>
      <servlet-name>jolokia-agent</servlet-name>
      <servlet-class>org.jolokia.http.AgentServlet</servlet-class>
      <load-on-startup>3</load-on-startup>
    </servlet>
    <servlet-mapping>
      <servlet-name>jolokia-agent</servlet-name>
      <url-pattern>/jolokia/*</url-pattern>
    </servlet-mapping>
    

    HttpURLConnection访问的方法
    package com.sinosoft.one.demo.util;
    
    import java.io.BufferedReader;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.alibaba.fastjson.JSONObject;
    
    public class HttpConnectUtil {
        private Logger logger = LoggerFactory.getLogger(getClass());
        private String url;
        public String sendMessage() {
            url = "http://localhost:8080/demo/jolokia/";
            logger.info("=================开始获取信息,地址{}=================" , url);
            String responseMessage = "";
            StringBuffer resposne = new StringBuffer();
            HttpURLConnection httpConnection = null;
            DataOutputStream out = null;
            BufferedReader reader = null;
            try {
                URL urlPost = new URL(url);
                httpConnection = (HttpURLConnection) urlPost.openConnection();
                httpConnection.setDoOutput(true);
                httpConnection.setDoInput(true);
                // 参数长度太大,不能用get方式
                httpConnection.setRequestMethod("POST");
                // 不使用缓存
                httpConnection.setUseCaches(false);
                // URLConnection.setInstanceFollowRedirects是成员函数,仅作用于当前函数
                httpConnection.setInstanceFollowRedirects(true);
                // 配置本次连接的Content-type,配置为application/x-www-form-urlencoded的
                // 意思是正文是urlencoded编码过的form参数
                httpConnection.setRequestProperty("Content-Type",
                        "application/x-www-form-urlencoded");
                // 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成,
                // 要注意的是connection.getOutputStream会隐含的进行connect。
                // 实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。
                logger.debug("打开连接:" + url);
                httpConnection.connect();
                out = new DataOutputStream(httpConnection.getOutputStream());
                // The URL-encoded contend
                // 正文,正文内容其实跟get的URL中'?'后的参数字符串一致
                            List list=new ArrayList();
                list.add("com.sinosoft.one.demo");
                list.add("DEBUG");
                JSONObject jsonObject=new JSONObject();
                jsonObject.put("arguments", list);
                jsonObject.put("mbean", "log4j:logger=Log4j");
                jsonObject.put("type", "exec");
                jsonObject.put("operation", "setProjectLevel");
                System.out.println(jsonObject);
                // // DataOutputStream.writeBytes将字符串中的16位的unicode字符以8位的字符形式写道流里面
                out.writeBytes(jsonObject.toJSONString());
                // flush and close
                out.flush();
                reader = new BufferedReader(new InputStreamReader(
                        httpConnection.getInputStream()));
                while ((responseMessage = reader.readLine()) != null) {
                    resposne.append(responseMessage);
                }
                if (!"failure".equals(resposne.toString())) {
                    logger.info("success send to JMX");
                } else {
                    logger.debug("failure send to JMX");
                }
                // 将该url的配置信息缓存起来
                return resposne.toString();
            } catch (IOException e) {
                logger.error("连接失败,url={}" , url);
                return "failed";
            } finally {
                try {
                    if (null != out) {
                        out.close();
                    }
                    if (null != reader) {
                        reader.close();
                    }
                    if (null != httpConnection) {
                        httpConnection.disconnect();
                    }
                } catch (Exception e2) {
                    logger.error("http connection close error:{}", e2);
                }
            }
        }
    }
    


    使用httpUrlConnection来访问JMX需要用JSON格式定义一下参数
                      必选     类型及范围         说明
    mbean           true    string          MBean名称,取值为log:name=LogConfigs
    operation       true    string          操作方法名称,取值为addLogUrl
    arguments       false   array           参数列表,如果没有参数,可省略
    type            true    String          操作类型,取值为exec
    
    
    
    分享到:
    评论

    相关推荐

      JMX (三)--------spring整合JMX

      总之,Spring整合JMX提供了强大的服务管理和监控能力,而结合Spring Schedule和Quartz则让我们能够灵活地处理定时任务。通过JMX,开发者可以远程控制和监视应用,提升系统管理和维护的效率。在实际项目中,充分利用...

      基于Spring+JMX+Tomcat实现资源动态管理

      通过集成JMX,开发者可以远程访问和控制Tomcat的各项配置,以适应不断变化的需求。 集成Spring和JMX的过程主要包括以下步骤: 1. 创建MBean:定义一个Java类实现特定的管理功能,并通过实现`javax.management....

      spring框架下jmx入门例子

      在Spring中集成JMX(Java Management Extensions)技术,可以使我们能够远程管理和监控应用中的对象,比如动态修改服务端的属性,这对于调试和性能优化非常有帮助。本教程将引导你入门Spring框架下的JMX应用。 首先...

      Spring jmx

      ### Spring与JMX结合应用详解 #### 软件监控与管理的重要性 在现代软件开发过程中,对应用程序的监控与管理变得尤为重要。这不仅是为了确保应用程序的正常运行,更是为了提高其性能和效率。通常情况下,我们会关注...

      JMX与Spring 结合

      Spring 支持与JMX集成,使得应用的管理更加灵活和方便。 **JMX与Spring结合** 的主要目的是让Spring应用可以被远程管理和监控。下面我们将详细介绍几个关键点: 1. **JMX与Spring 结合实例**:在Spring应用中,...

      spring jmx

      通过Spring JMX,我们可以轻松地在Spring应用中集成JMX功能,实现对应用程序的远程监控和管理。 Spring JMX的核心概念包括MBean(Managed Bean)、MBeanServer和代理(MBeanProxy)。MBean是JMX中的基本管理单元,...

      jmx开发例子,包括与spring结合例子

      这个压缩包包含的是JMX开发的实例,特别提到了与Spring框架的集成。 Spring是一个广泛使用的Java企业级应用开发框架,它简化了配置、依赖注入以及事务管理等任务。Spring支持JMX,可以让你通过JMX接口管理Spring...

      JMX SPRING

      Spring提供了一套完整的JMX集成机制,使得在Spring应用中使用JMX变得简单。Spring通过`MBeanExporter`类将Spring Bean注册到MBean服务器,这些Bean可以是标准的JMX MBean,也可以是自动转换的Spring Bean。此外,...

      Axis2与Spring整合发布多个WebService

      **Axis2与Spring整合** 整合Axis2和Spring的主要目的是利用Spring的依赖注入(DI)和面向切面编程(AOP)特性,使得Web服务的创建和管理更加方便。以下是整合步骤: 1. **添加依赖**:在Maven项目中,需要在pom....

      JAVA JMX 学习资料

      Spring框架提供对JMX的全面支持,可以方便地注册MBeans,以及集成Spring的管理功能。 9. **安全性**: JMX支持安全管理,可以通过JMX Security API设置权限,限制客户端对MBeans的操作。 10. **JMX工具和库**: ...

      jmx所需的jar

      JMX RI是JMX规范的实现,它提供了API和实现,使得开发者能够在Java应用程序中集成JMX功能。这个版本的JMX包括了核心的MBean服务器、MBean接口定义、MBean代理、通知服务等组件。MBean(Managed Bean)是JMX中的核心...

      mx4j管理jmx的jar与spring结合使用

      在标题“mx4j管理jmx的jar与spring结合使用”中,我们关注的重点是MX4J如何与Spring协作来实现JMX的功能。MX4J提供的`mx4j-tools-2.1.1.jar`是MX4J的核心库,包含了用于JMX操作的各种工具和API。这个版本(2.1.1)...

      书籍JMX-IN-ACTION

      本书还深入讨论了JMX与其他技术的集成,如JMX与Spring框架的整合,以及JMX在分布式系统中的应用,包括集群管理和跨节点通信。此外,书中还涉及到了安全管理,包括JMX连接的安全策略和认证机制,以确保管理系统安全...

      WebService的CXF整合Spring

      将CXF与Spring整合的主要目的是利用Spring的管理能力来配置和控制CXF组件,例如服务端点、客户端代理等。这样可以实现更细粒度的控制,提高代码的可测试性和可维护性。 整合步骤如下: 1. **引入依赖**:首先,在...

      Spring攻略PDF版

      因为上传大小的限制,分为两部分上传,这是第二部分,第一部分会在评论中给出链接 绝对是spring攻略中文版第二版 ... 第18章 Spring对JMX、电子邮件和调度的支持   第19章 Spring中的脚本编程 

      Spring攻略中文版PDF

      因为上传大小的限制,分为两部分上传,这是第一部分,第二部分会在评论中给出链接 绝对是spring攻略中文版第二版 ... 第18章 Spring对JMX、电子邮件和调度的支持   第19章 Spring中的脚本编程 

      Java_Spring与Quartz的整合

      在Java Spring中整合Quartz,可以利用Spring的管理能力来控制Quartz的作业和触发器,使得整个系统更加灵活和易于维护。以下将详细介绍如何进行Spring与Quartz的整合。 1. **集成步骤** - 添加依赖:首先,确保在...

      JBPM4.4+spring+ext整合

      【JBPM4.4+Spring+EXT 整合详解】 JBPM(Java Business Process Management)是一个开源的工作流管理系统,主要用于处理业务流程自动化。版本4.4是JBPM的一个重要里程碑,它提供了强大的工作流设计、执行和监控能力...

      JMX.rar_jmx_osgi

      8. **JMX与Spring**:Spring框架集成了JMX,使得在Spring应用中使用JMX变得简单。Spring的`@ManagedResource`注解可以自动将bean暴露为MBean,而`@ManagedAttribute`和`@ManagedOperation`可以分别标记可管理的属性...

    Global site tag (gtag.js) - Google Analytics