天天看點

springboot項目内部停止并關閉因業務需求,從内部停止并關閉springboot項目

因業務需求,從内部停止并關閉springboot項目

首先說下遇到的需求,在項目中甯願不執行也不能執行錯誤的需求時有發生,最近在做一個平台,在儲存收款賬戶時考慮安全問題,在啟動項目時作為必須校驗項進行,如果校驗不通過,阻止項目允許。

在百度上各種查,沒有此類操作,現在研究出來了發現超級簡單。寫這篇文章的目的主要是記錄下研究過程。心急的同學可以直接看的一部分,最終結果。

1、終于搞出來了

spring 的context(實作了ConfigurableApplicationContext的context)有一個close方法,在需要的地方執行context.close就好了。

2、我是怎麼搞出來的

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

剛開始我像往常一樣,期待網友們有一個成熟的解決方案。但是,經過幾個小時的查找和篩選,沒有找到我想要的。也不是一無所獲。網友們都很樂于奉獻,隻要搜springboot 啟動,關閉,終止的,都能查到兩種方法。

springboot項目内部停止并關閉因業務需求,從内部停止并關閉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請求的服務接口,沒辦法隻能列印日志慢慢找

springboot項目内部停止并關閉因業務需求,從内部停止并關閉springboot項目

找到這個入口後開始一步步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;
		}
		
	}
}
           
上一篇: 關于無線
下一篇: CDC,CClientDC