我的应用程序有一个作为单独服务运行的 SpringBoot 进程。当这个进程完成监听后,我想优雅地关闭它。为了实现这一目标,我实现了以下端点,我发现 here .
@RestController
public class ShutdownController implements ApplicationContextAware {
private ApplicationContext context;
@PostMapping("/shutdown")
public void shutdownContext() {
((ConfigurableApplicationContext) context).close();
}
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
this.context = ctx;
}
}
当我尝试从我的应用程序向端点发送请求时,问题就出现了。这是我正在运行的代码:
new RestTemplate().postForLocation(shutdownUri, null);
抛出:
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:8083/shutdown": Unexpected end of file from server; nested exception is java.net.SocketException: Unexpected end of file from server
我认为这个异常背后的原因是 Spring 关闭并且仍然无法发送正确的响应,如果我错了,请纠正我。 我知道我可以捕获此异常并且 Spring 会正确关闭,但我想知道是否有更干净的方法来使用端点。
最佳答案
Spring Boot 应用程序无法响应请求,因为它已关闭。因此,您可以创建一个以异步方式处理关闭过程的服务,您可以等待客户端通知应用程序已成功收到关闭请求,然后关闭应用程序。
创建服务类:
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class ShutdownService implements ApplicationContextAware {
private ApplicationContext context;
@Async
public void shutDown() {
try {
Thread.sleep(5_000);
((ConfigurableApplicationContext) context).close();
} catch (InterruptedException e) {
//
}
}
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
this.context = ctx;
}
}
要使其正常工作,请将您的应用程序类标记为:
@EnableAsync
您还可以根据您的需求调整Executor
设置。
按如下方式创建 Controller :
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ShutdownController {
private final ShutdownService shutdownService;
public ShutdownController(ShutdownService shutdownService) {
this.shutdownService = shutdownService;
}
@PostMapping("/shutdown")
public ResponseEntity<String> shutdownContext() {
shutdownService.shutDown();
return ResponseEntity.ok().body("Shutdown request is successfully received.");
}
}
您可能需要仔细检查关闭过程中是否发生了错误。
关于java - 使用 Spring 关闭端点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61483232/