java - 使用 Spring 关闭端点

标签 java spring-boot rest http

我的应用程序有一个作为单独服务运行的 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/

相关文章:

rest - Nginx 更改请求从 PUT 到 POST

java - 对数组的每个元素进行并行递归函数调用(使用 ForkJoinPool)

java - 可以提取文件但无法删除文件

java - 在 Java 中加密和解密密码

mysql - 从 postman 发帖时,数据以匿名用户身份在数据库中发布

java - 多个微服务一个数据库

java - RESTful 应用程序 - 如何返回最后 10 个 REST 调用

java - 无法通过Java删除目录

java - JSON解析错误: Cannot construct instance of `com.example.greetapp.domain.User`

rest - 资源是否始终位于 REST 中的服务器上?