二、JMX自定义MBean

发布时间 2023-06-03 17:56:30作者: shigp1

一、自定义MBean

public interface HelloMBean {

     String getName();
     void setName(String name);


     String print();
}

HelloMBean必须以MBean结尾。

@Slf4j
public class Hello implements HelloMBean {

    private String name;
    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String print() {
        log.info(name);
        return name;
    }
}

@Slf4j是lombok注解。HelloMBean的名称去除MBean后必须是Hello,不能是其他名称。这里的资源是Hello,MBean的接口是必须是HelloMBean

在启动类注册MBean:

@SpringBootApplication
@MapperScan("com.example.mytest.mapper")
public class MyTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyTestApplication.class, args);

        MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();

        Hello hello = new Hello();
        hello.setName("张三");
        try {
            // ObjectName规范是包名:type=接口名,name=MBean名
            ObjectName objectName = new ObjectName("com.example.mytest.mbean:type=HelloMBean,name=hello");
            platformMBeanServer.registerMBean(hello, objectName);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

启动程序后,再启动jconsole:
 

 

 

点击属性后,将属性修改为李四,点击下面的刷新。在点击hello MBean的操作:
 

 

属性已经修改为李四。查看控制台:

2023-06-03 16:37:19.095  INFO 71617 --- [on(7)-127.0.0.1] com.example.mytest.mbean.Hello           : 李四

在web访问

如果要在web发布,可以使用HtmlAdaptorServer适配器,先引入依赖:

    <dependency>
        <groupId>org.glassfish.external</groupId>
        <artifactId>opendmk_jdmkrt_jar</artifactId>
        <version>1.0-b01-ea</version>
    </dependency>

将启动类修改为:

@SpringBootApplication
@MapperScan("com.example.mytest.mapper")
public class MyTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyTestApplication.class, args);

        MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();

        Hello hello = new Hello();
        hello.setName("张三");
        try {
            ObjectName objectName = new ObjectName("com.example.mytest.mbean:type=HelloMBean,name=hello");
            platformMBeanServer.registerMBean(hello, objectName);

            HtmlAdaptorServer html = new HtmlAdaptorServer();
            ObjectName adaptorName = new ObjectName("adapator:name=HtmlAdaptor");
            html.setPort(9097);
            MBeanServer platformMBeanServer1 = ManagementFactory.getPlatformMBeanServer();
            platformMBeanServer1.registerMBean(html, adaptorName);
            html.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

访问http://localhost:9097/,看到:
 

 
点击type=HelloMBean,name=hello:
 

 

可以看到中文乱码了。

 

开放远程访问

如果要开放端口,可以添加JVM参数:

-Dcom.sun.management.jmxremote.port=19999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

第一个参数表示在19999端口监听JMX连接,第二个和第三个参数表示无需验证,不使用SSL连接,在开发测试阶段比较方便,生产环境必须指定验证方式并启用SSL。

 

启动后,在jconsole中输入:
 

 

二、自定义MXBean

public interface MyHelloExampleMXBean {

     String getName();

     void setName(String name) ;

    String print();
}

public class MyHello implements MyHelloExampleMXBean{

    private String name;

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String print() {
        return name;
    }
}

修改启动类:

@SpringBootApplication
@MapperScan("com.example.mytest.mapper")
public class MyTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyTestApplication.class, args);

        MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();

        Hello hello = new Hello();
        hello.setName("张三");

        MyHello myHello = new MyHello();
        myHello.setName("李四");
        try {
            ObjectName objectName = new ObjectName("com.example.mytest.mbean:type=HelloMBean,name=hello");
            platformMBeanServer.registerMBean(hello, objectName);

            platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
            objectName = new ObjectName("com.example.mytest.mbean:type=MyHelloExampleMXBean,name=myHello");
            platformMBeanServer.registerMBean(myHello, objectName);

            HtmlAdaptorServer html = new HtmlAdaptorServer();
            ObjectName adaptorName = new ObjectName("adapator:name=HtmlAdaptor");
            html.setPort(9097);
            MBeanServer platformMBeanServer1 = ManagementFactory.getPlatformMBeanServer();
            platformMBeanServer1.registerMBean(html, adaptorName);
            html.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

可以看到MyHelloExampleMXBean只要以MXBean结尾就可以随便命名。

三、在Spring中定义MBean

MyController:

@Value("${my.value}")
private String myValue;

private Set<String> set = new HashSet<>();

public void add(String s) {
    set.add(s);
}


public Set<String> getSet() {
    return set;
}

MyControllerMXBean

@Slf4j
@Component
@ManagedResource(objectName = "controller:name=myControllerMXBean", description = "MyController Attribute")
public class MyControllerMXBean {

    @Autowired
    private MyController myController;

    @ManagedAttribute(description = "Get Configuration")
    public String getMyValue() {
        String myValue = myController.myValue();
        log.info(myValue);
        return myValue;
    }

    @ManagedAttribute(description = "Get Set")
    public String getSet() {
        Set<String> set = myController.getSet();
        return set.stream().collect(Collectors.joining());
    }

    @ManagedOperation
    @ManagedOperationParameter(name = "s", description = "Add Set Element")
    public void addSet(String s) {
        myController.add(s);
    }
}

@ManagedResource配置ObjectName,@ManagedOperation指示这是个操作。@ManagedAttribute用在方法上,指示这是个属性(必须符合JAVA Bean的规范,即有get,set方法), @ManagedOperationParameter绑定参数。

 

用jconsole连接后:
 

 
调用addSet后再调用getSet查看添加的数据。getMyValue方法是为了演示可以调用到Spring Bean中的方法获取配置。