Spring Boot RestController接口如何输出到终端

spring,boot,restcontroller,接口,如何,输出,终端 · 浏览次数 : 8

小编点评

**代码功能:** 该代码实现了一个应急接口,用于在执行 Spring Boot REST接口的过程中,实时输出一些信息并给运维人员知道当前命令执行的状态。 **主要方法:** * `test()`:处理 HTTP 请求,并使用 `HttpServletResponse` 输出响应内容。 * `createPrintWriter()`:创建和初始化 `PrintWriter` 对象。 * `output()`:向控制台打印输出内容。 **坑点:** * 如果接口方法返回 `null`,则会让 Spring Boot以为重复调用了 `response.getWriter()` 函数,导致错误。 * `response.getWriter()` 函数只能用于输出纯文本内容,如果需要输出其他格式的内容,则需要使用其他方法。 **代码示例:** ```java @GetMapping("/test") public void test(HttpServletResponse response) throws IOException { response.setContentType("text/plain;charset=utf-8"); try { boolean result = testService.emergencyOperation(response); response.getWriter().println(CommonResult.success(null, "应急任务处理成功!\").toString()); } catch (IOException e) { log.error("应急任务处理失败!", e); response.getWriter().println(CommonResult.fail(null, "应急任务处理失败!\").toString()); } } private PrintWriter createPrintWriter(boolean output, HttpServletResponse response) throws IOException { if (output) { response.setCharacterEncoding("UTF-8"); response.setContentType("text/plain;charset=utf-8"); return response.getWriter(); } return null; } ``` **使用说明:** 1. 启动 Spring Boot 应用。 2. 在项目生成目录下运行 `run.sh` 或 `run.bat` 等命令启动控制台。 3. 在控制台中运行 `curl http://localhost:8080/test`,可以看到控制台输出响应内容。 4. 运行 Spring Boot 应用,等 5 分钟,可以看到定时任务成功执行。

正文

今天在公司项目的代码上实践了一下,发现这种方法对业务代码侵入性太大,大量的业务方法需要增加传入参数,使得业务方法和HttpServletResponse类耦合度太高,需要将业务和输出解耦,具体实现请看下一篇文章 使用HttpServletResponse实现curl接口时控制台输出(续)

背景

公司项目的批处理微服务,一般是在晚上固定时段通过定时任务执行,但为了预防执行失败,我们定义了对应的应急接口,必要时可以通过运维在终端中进行curl操作。然而,部分任务耗时较长,curl命令执行后长时间没有输出,如果不查看日志,无法知道系统当前的状态,因此有必要研究一下如何在curl命令调用接口时,在终端输出部分信息,已告知运维人员当前命令的执行状态。

原理

使用 HttpServletResponse 类,可以自定义输出,也就是模拟网页输出的效果,只不过我们输出的内容是纯文本。

代码

  1. 新建一个Spring Boot项目,建立一个 TestController,作为我们的应急接口。
@RestController
@Slf4j
public class EmergencyController {
    @Resource
    private TestService testService;

    @GetMapping("/test")
    public void test(HttpServletResponse response) throws IOException {
        response.setContentType("text/plain;charset=utf-8");
        try {
            boolean result = testService.emergencyOperation(response);
            response.getWriter().println(CommonResult.success(null, "应急任务处理成功!").toString());
        } catch (IOException e) {
            log.error("应急任务处理失败!", e);
            response.getWriter().println(CommonResult.fail(null, "应急任务处理失败!").toString());
        }
    }
}

这里的一个坑是:如果使用了这种方法输出,那么接口方法不能再有任何返回值,不然会让Spring Boot以为重复调用了 response.getWriter() 函数,于是报错。需要将原本的输出内容(如通用返回体CommonResult类,或字符串String)也放入 response.getWriter() 进行输出。

其中 TestService 是我们的批处理业务接口,无论是应急接口还是定时任务,都需要使用该接口进行实际的业务操作。其实现类 TestServiceImpl 代码如下:

/**
 * 模拟应急操作方法
 */
@Override
public boolean emergencyOperation(HttpServletResponse response) throws IOException {
    // 如果是定时任务,则该参数传入null,不在终端输出
    boolean canOutput = response != null;
    PrintWriter writer = createPrintWriter(canOutput, response);
    log.info("开始执行应急操作任务");
    output(canOutput, writer, "开始执行应急操作任务");
    for (int i = 0; i < 20; i++) {
        output(canOutput, writer, "完成第" + (i+1) + "批次");
        log.info("完成第 {} 批次", i+1);
        try {
            Thread.sleep(500L);
        } catch (InterruptedException e) {
            log.warn("应急操作任务失败");
            output(canOutput, writer, "应急操作任务失败");
            return false;
        }
    }
    log.info("完成应急操作任务");
    output(canOutput, writer, "应急操作任务完成");
    return true;
}

其中 createPrintWriter() 方法设置 HttpServletResponse 对象的 ContentType 属性,我们输出的是纯文本,因此需要设置为 text/plain;charset=utf-8,具体代码如下:

private PrintWriter createPrintWriter(boolean output, HttpServletResponse response) throws IOException {
    if (output) {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/plain;charset=utf-8");
        return response.getWriter();
    }
    return null;
}

在需要使用的地方调用 output() 方法,向控制台打印输出内容:

private void output(boolean output, PrintWriter writer, String message) throws IOException {
    if (!output) {
        return;
    }
    writer.println(message);
    writer.flush();
}

测试

使用 Maven 构建项目,在项目生成目录下运行 jar 包启动程序,另外开一个控制台窗口,执行 curl http://localhost:8080/test,可以看到控制台输出如下:

同时在运行 Spring Boot 应用的窗口,也可以看到日志成功输出:

定时任务执行情况

我们定义定时任务 EmergencyTask 如下(不要忘了在应用启动类上增加 @EnableScheduling 注解)

@Component
@Slf4j
public class EmergencyTask {
    @Resource
    private TestService testService;

    @Scheduled(cron = "0 */5 22 * * MON-FRI")
    public void emergencyTask() throws IOException {
        testService.emergencyOperation(null);
    }
}

这里我们设置的是从22点后每隔5分钟执行一次,当然实际项目中需要根据需求来确定定时任务执行时间。
启动应用,等5分钟,可以看到定时任务成功执行。

再次运行 curl http://localhost:8080/test,可以看到控制台和日志均正常输出。

总结

使用 HttpServletResponse 类,可以在使用 curl 执行 Spring Boot REST接口的同时,在控制台输出一些信息,给运维人员知道当前命令执行的状态。

与Spring Boot RestController接口如何输出到终端相似的内容:

Spring Boot RestController接口如何输出到终端

背景 公司项目的批处理微服务,一般是在晚上固定时段通过定时任务执行,但为了预防执行失败,我们定义了对应的应急接口,必要时可以通过运维在终端中进行curl操作。然而,部分任务耗时较长,curl命令执行后长时间没有输出,如果不查看日志,无法知道系统当前的状态,因此有必要研究一下如何在curl命令调用接口

使用HttpServletResponse实现curl接口时控制台输出(续)

上一篇文章的问题 在上一篇文章 Spring Boot RestController接口如何输出到终端 中讨论了如何使用 HttpSerlvetResponse 写入输出流,使应急接口通过 curl 调用时可以在控制台输出信息,使运维人员知道命令执行情况。 但是上一篇文章的问题是,HttpServl

SpringBoot 接口并发限制(Semaphore)

可以使用 JMeter 辅助测试 https://blog.csdn.net/weixin_45014379/article/details/124190381 @RestController @RequestMapping({"/Test"}) public class test { Logger

盘点 Spring Boot 解决跨域请求的几种办法

熟悉 web 系统开发的同学,对下面这样的错误应该不会太陌生。 之所以会出现这个错误,是因为浏览器出于安全的考虑,采用同源策略的控制,防止当前站点恶意攻击 web 服务器盗取数据。 01、什么是跨域请求 同源策略,简单的说就是当浏览器访问 web 服务器资源时,只有源相同才能正常进行通信,即协议、域

Spring Boot应用中如何动态指定数据库,实现不同用户不同数据库的场景

当在 Spring Boot 应用程序中使用Spring Data JPA 进行数据库操作时,配置Schema名称是一种常见的做法。然而,在某些情况下,模式名称需要是动态的,可能会在应用程序运行时发生变化。比如:需要做数据隔离的SaaS应用。 所以,这篇博文将帮助您解决了在 Spring Boot

3分钟带你搞定Spring Boot中Schedule

一、背景介绍 在实际的业务开发过程中,我们经常会需要定时任务来帮助我们完成一些工作,例如每天早上 6 点生成销售报表、每晚 23 点清理脏数据等等。 如果你当前使用的是 SpringBoot 来开发项目,那么完成这些任务会非常容易! SpringBoot 默认已经帮我们完成了相关定时任务组件的配置,

手把手教你解决spring boot导入swagger2版本冲突问题,刘老师教编程

手把手教你解决spring boot导入swagger2版本冲突问题 本文仅为个人理解,欢迎大家批评指错 首先Spring Boot 3 和 Swagger 2 不兼容。在 Spring Boot 3 中,应该使用 Springdoc 或其他与 Spring Boot 3 兼容的 API 文档工具来

一文了解Spring Boot启动类SpringApplication

只有了解 Spring Boot 在启动时都做了些什么,我们才能在后续的实践的过程中更好地理解其运行机制,以便遇到问题能更快地定位和排查。

从零开始学Spring Boot系列-集成Spring Security实现用户认证与授权

在Web应用程序中,安全性是一个至关重要的方面。Spring Security是Spring框架的一个子项目,用于提供安全访问控制的功能。通过集成Spring Security,我们可以轻松实现用户认证、授权、加密、会话管理等安全功能。本篇文章将指导大家从零开始,在Spring Boot项目中集成S

如何在Spring Boot框架下实现高效的Excel服务端导入导出?

前言 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。今天我们就使用纯前对按表格控件带大家了解,如何在Spring Boot框架下实现Excel服务端导