springboot项目内部停止并关闭

因业务需求,从内部停止并关闭springboot项目

首先说下遇到的需求,在项目中宁愿不执行也不能执行错误的需求时有发生,最近在做一个平台,在保存收款账户时考虑安全问题,在启动项目时作为必须校验项进行,如果校验不通过,阻止项目允许。
在百度上各种查,没有此类操作,现在研究出来了发现超级简单。写这篇文章的目的主要是记录下研究过程。心急的同学可以直接看的一部分,最终结果。

1、终于搞出来了

spring 的context(实现了ConfigurableApplicationContext的context)有一个close方法,在需要的地方执行context.close就好了。

2、我是怎么搞出来的

  • 一、内事不决问百度(主要是Google不了啊~~)

刚开始我像往常一样,期待网友们有一个成熟的解决方案。但是,经过几个小时的查找和筛选,没有找到我想要的。也不是一无所获。网友们都很乐于奉献,只要搜springboot 启动,关闭,终止的,都能查到两种方法。

这里写图片描述

对于这个结果刚开始我是很不开森的,因为只有这个结果,而且能搜到的都是这个结果,达到了一遇到这个结果就关页面的程度,最后实在找不到解决方案了。我愤怒了,既然没有人有研究,我就来贡献时间。

  • 二、Java程序员要想提升还是得看源码跟流程

既然spring官方提供了两种关闭服务的方法,说明可以做到,既然他们能做到,我也能!于是按照网友提供的步骤,下面引用网友提供的 通过http发送shutdown的方法 来研究

1.在pom.xml中引入actuator依赖
		<dependency>
		  <groupId>org.springframework.boot</groupId>
		  <artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
2.在application.properties文件开启shutdown endpoint,SpringBoot的endpoints.shutdown.enabled默认是关闭的。

    #启用shutdown 
    endpoints.shutdown.enabled=true 
    #禁用密码验证 
    endpoints.shutdown.sensitive=false

经过简单的两步就能实现远程调用关闭系统,但这不是我想要的,我要找的是在系统里直接调用某个方法就能实现自动关闭。
要查找这个方法必须从官方提供的远程调用入手,远程调用使用的HTTP请求,于是要查找HTTP请求的服务接口,没办法只能打印日志慢慢找

这里写图片描述

找到这个入口后开始一步步debug,很痛苦的,因为你不知道哪一步系统就关闭了,只能在关闭系统的方法上加断点再次启动系统,执行关闭,如此反复查找了好几次,终于让我发现了关闭服务的老巢,哈哈哈哈!!!
老巢,spring-boot-actuator-1.5.4RELEASE.jar包里的ShutdownEndpoint这个类,下面贴出来主要代码,这段代码主要是说能关闭系统时,返回说正在关闭,启动关闭线程,调用this.context.close()。我去,终于让我知道了你的秘密,使用context就能关闭。好像我spring有获取context的方法吧,我去查查(本人技术水平有限,只是知道有这个事儿,这是后面故事的开始)。

ShutdownEndpoint的主要代码

public ShutdownEndpoint() {
		super("shutdown", true, false);
	}
	@Override
	public Map<String, Object> invoke() {
		if (this.context == null) {
			return NO_CONTEXT_MESSAGE;
		}
		try {
			return SHUTDOWN_MESSAGE;
		}
		finally {
			Thread thread = new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						Thread.sleep(500L);
					}
					catch (InterruptedException ex) {
						Thread.currentThread().interrupt();
					}
					ShutdownEndpoint.this.context.close();
				}
			});
	thread.setContextClassLoader(getClass().getClassLoader());
			thread.start();
		}
	}
	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		if (context instanceof ConfigurableApplicationContext) {
			this.context = (ConfigurableApplicationContext) context;
		}
	}

spring有获取context的方法
中国网友就是给力,一搜一大把,都是一样的 —— 实现ApplicationContextAware接口
嗯,照着做,实现接口,东复制下,西复制下,怀着无比期待的心情执行测试……咦怎么没有关闭!!!!!
我去,debug,然后各种查,痛苦死了,下面给出错误代码(哪里错了自己看),希望网友们引以为戒

public class ShutdownContext implements ApplicationContextAware
{
	private ConfigurableApplicationContext context;
	
	public void showdown(){
		if (null != context){
			context.close();
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException{
		if (context instanceof ConfigurableApplicationContext) {
			this.context =  (ConfigurableApplicationContext) applicationContext;
		}
	}
}

————————————————美丽的分割线—————————————————————

有网友说使用我的代码运行不了,时隔好久也不记得哪里错了,对比了下代码才发现最后一个判断错误了,应该判断传入参数,判断了成员变量。下面是完整代码

import org.springframework.beans.BeansException;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix ="spring")
public class ShutdownContext implements ApplicationContextAware
{

	private ConfigurableApplicationContext context;
	
	public void showdown()
	{
		if (null != context)
		{
			context.close();
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
	{
		if (applicationContext instanceof ConfigurableApplicationContext) {
			this.context =  (ConfigurableApplicationContext) applicationContext;
		}
		
	}
}
  • 16
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值