随Tomcat启动1个线程,并通过JMX不停服管理该线程起停

第1步,创建TaskProcess,代码如下

package cn.xxx.xxxx;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.context.ApplicationContext;

import java.util.HashMap;
import java.util.Map;

public class TaskProcess extends Thread {

    private static final Log logger = LogFactory.getLog(TaskProcess.class);

    // 获取应用程序上下文环境,用于获取注入bean
    private ApplicationContext appCon;

    // 线程执行期间内存map
    static Map<String,String> processMap = new HashMap<String,String>();

    public TaskProcess(ApplicationContext con) {
        this.appCon = con;
    }

    public void run() {
        logger.info("线程启动。");
        long n=1;
        while(true){
            logger.info("线程第"+n+"次运行");
            processPunction(n);
            n++;
            try {
                //30秒执行1次
                Thread.sleep(30000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void processPunction(long n) {
        try {
            //TODO
            //XXXMapper xxxMapper= (XXXMapper)appCon.getBean("xx.xx.xxxMapper");
            //List list = XXXMapper.select();
            //processMap.put(String.valueOf(n), list);
            logger.info("业务逻辑。。。。");
            processMap.put(String.valueOf(n),"线程第"+n+"次运行");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

第2步,创建 TaskManagerMBean,代码如下

package cn.xxx.xxxx;

public interface TaskManagerMBean{

    public void startNewProcess();

    public void restartProcess();

    public void showAliveProcess();
}

第3步,创建TaskManagerMBean的实现类TaskManager,代码如下

package cn.xxx.xxxx;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;

import java.util.Map;

/**
 * jmx监控TaskProcess
 */
public class TaskManager implements TaskManagerMBean{

    private static final Log logger = LogFactory.getLog(TaskManager.class);

    private ApplicationContext con;

    private TaskProcess process;

    public TaskManager(ApplicationContext con , TaskProcess process ){
        this.con = con;
        this.process=process;
    }

    //启动新的线程
    public void startNewProcess() {
        if(!process.isAlive()){
            logger.info("启动新的线程。");
            process = new TaskProcess(con);
            process.start();
            long processId = process.getId();
            logger.info("线程--"+processId+"已启动。");
        }else{
            logger.info("线程已存在,请先停止原有线程");
        }
    }

    //重启
    public void restartProcess() {
        logger.info("停止原有线程中。。。");
        long processId = process.getId();
        process.stop();
        logger.info("线程--"+processId+"已停止");
        logger.info("重新启动线程中。。。");
        process = new TaskProcess(con);
        process.start();
        processId = process.getId();
        logger.info("已重新启动线程--"+processId);
    }

    //查看活的线程以及业务逻辑中有什么
    public void showAliveProcess(){
        if(process.isAlive()){
            long processId = process.getId();
            logger.info("线程--"+processId+"正常。");
            Map<String, String> processMap = process.processMap;
            logger.info("processMap--"+processMap);
        }else{
            logger.info("线程不存在");
        }
    }
}

第4步,创建上下文TaskServletContextContext,代码参考如下

package cn.xxx.xxxx;

import javax.servlet.ServletContext;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class TaskServletContextContext implements ApplicationContextAware {
  
  private static ApplicationContext springContext;

  public static ApplicationContext getApplicationContext() {
    return springContext;
  }

  public void setServletContext(ServletContext servletContext) {
    springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
  }

  public static void setApplicationContext(WebApplicationContext context) {
    springContext = context;
  }

  public void setAttribute(String name, Object bean) {
    if ((springContext instanceof WebApplicationContext))
      ((WebApplicationContext)springContext).getServletContext().setAttribute(name, bean);
  }

  public void destroy() throws Exception {
    springContext = null;
  }

  public void setApplicationContext(ApplicationContext arg0)
    throws BeansException {
    springContext = arg0;
  }
}

第6步,创建随服务启动的Listener,代码参考如下

package cn.xxx.xxxx;

import javax.management.*;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;


import java.lang.management.ManagementFactory;


public class TaskServletContextListener implements ServletContextListener{
	private static final Log logger = LogFactory.getLog(TaskServletContextListener.class);

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		TaskServletContextContext tscc = new TaskServletContextContext();
		tscc.setServletContext(sce.getServletContext());
		ApplicationContext con = TaskServletContextContext.getApplicationContext();
		TaskProcess process = new TaskProcess (con);
		process.start();
		//启动jmx监控此线程
		startJmx(con,process);

	}

	public void startJmx(ApplicationContext con ,TaskProcess process){
		MBeanServer server = ManagementFactory.getPlatformMBeanServer();
		try {
			ObjectName name = new ObjectName("taskJmx:name=taskJmx");
			server.registerMBean(new TaskManager(con, process), name);
		} catch (MalformedObjectNameException e) {
			e.printStackTrace();
		} catch (NotCompliantMBeanException e) {
			e.printStackTrace();
		} catch (InstanceAlreadyExistsException e) {
			e.printStackTrace();
		} catch (MBeanRegistrationException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		// TODO Auto-generated method stub
		
	}

}

第7步,web项目中web.xml的<web-app>节点增加如下配置上面的listener

<listener>
       <listener-class>cn.xx.xxxx.TaskServletContextListener</listener-class>
</listener>

第8步,启动tomcat,Tomcat版本:apache-tomcat-7.0.103

第9步,执行java安装目录下的jconsole.exe

C:\Java\jdk1.8.0_20\bin\jconsole.exe

第10步,查看mbean,连接到tomcart,可能提示不安全,点"不安全连接"即可

随Tomcat启动1个线程,并通过JMX不停服管理该线程起停

 第11步,选择MBean页签,找到第6步代码中的name,展开有操作,点击操作,右边显示按钮。点击方法即可

随Tomcat启动1个线程,并通过JMX不停服管理该线程起停

后台打印log: 

2021/09/29 19:53:23 [RMI TCP Connection(10)-127.0.0.1] INFO  cn.xxx.xxxx.TaskManager -线程--92正常。
2021/09/29 19:53:23 [RMI TCP Connection(10)-127.0.0.1] INFO  cn.xxx.xxxx.TaskManager -processMap--{1=线程第1次运行, 2=线程第2次运行, 3=线程第3次运行, 4=线程第4次运行, 5=线程第5次运行}

上一篇:Kafka集群监控方案--Kafka(JMX)+JMXtrans+InfluxDB+Grafana


下一篇:Jmeter:非GUI模式运行.jmx脚本并生成测试html报告