背景

公司项目的批处理微服务,一般是在晚上固定时段通过定时任务执行,但为了预防执行失败,我们定义了对应的应急接口,必要时可以通过运维在终端中进行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接口如何输出到终端的更多相关文章

  1. spring boot rest 接口集成 spring security(2) - JWT配置

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  2. spring boot rest 接口集成 spring security(1) - 最简配置

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  3. Spring boot启动成功后输出提示

    添加logback-spring.xml,将log输出到文件,控制台输出的level改为error因此只会出处banner src/main/resources/banner.txt的内容为 star ...

  4. Spring Boot 使用 Log4j2 & Logback 输出日志到 EKL

    文章目录 1.ELK 介绍 2.环境.软件准备 3.ELK 环境搭建 4.Spring Boot 配置示例 4.1.Log4j2 方式配置 4.2.Logback 方式配置 1.ELK 介绍 ELK ...

  5. Spring boot CommandLineRunner接口使用例子

    前言 Spring boot的CommandLineRunner接口主要用于实现在应用初始化后,去执行一段代码块逻辑,这段初始化代码在整个应用生命周期内只会执行一次. 如何使用CommandLineR ...

  6. spring boot: 设计接口站api的版本号,支持次版本号(spring boot 2.3.2)

    一,为什么接口站的api要使用版本号? 1,当服务端接口的功能发生改进后, 客户端如果不更新版本,    则服务端返回的功能可能不能使用,    所以在服务端功能升级后,     客户端也要相应的使用 ...

  7. 寻找写代码感觉(三)之使用 Spring Boot 编写接口

    一.前言 项目配置完之后,接着就是写接口了,那咱们就开始吧. 二.项目配置补充知识点 上篇文章写的是关于项目属性配置的一些知识,这里针对上次遗忘内容进行补充如下: 2.1.获取配置文件的值 在appl ...

  8. spring boot:给接口增加签名验证(spring boot 2.3.1)

    一,为什么要给接口做签名验证? 1,app客户端在与服务端通信时,通常都是以接口的形式实现, 这种形式的安全方面有可能出现以下问题: 被非法访问(例如:发短信的接口通常会被利用来垃圾短信) 被重复访问 ...

  9. spring boot:使接口返回统一的RESTful格式数据(spring boot 2.3.1)

    一,为什么要使用REST? 1,什么是REST? REST是软件架构的规范体系,它把资源的状态用URL进行资源定位, 以HTTP动作(GET/POST/DELETE/PUT)描述操作 2,REST的优 ...

  10. spring boot 统一接口异常返回值

    创建业务 Exception 一般在实际项目中,推荐创建自己的 Exception 类型,这样在后期会更容易处理,也比较方便统一,否则,可能每个人都抛出自己喜欢的异常类型,而造成代码混乱 Servic ...

随机推荐

  1. Hybrid 实验

    实验拓扑 实验需求 按图示给各 PC 配置 IP 地址 PC1属于 VLAN 10 : PC2 与 PC5 属于 VLAN 20:PC4属于 VLAN 30 实现全网互通 实验步骤 1.配置链路聚合 ...

  2. 【python基础】复杂数据类型-字典(增删改查)

    1.初识字典 字典,是另外一种复杂的数据类型,相较于列表,字典可以将相关信息关联起来.比如说一个人的信息有名字.年龄.性别等,如果用列表存储的话,不能表示他们之间是相关联的,而字典可以,字典是一个或多 ...

  3. CMake个人理解和使用

    前言 CMake是一个构建工具,通过它可以很容易创建跨平台的项目.通常使用它构建项目要分两步,通过源代码生成工程文件,通过工程文件构建目标产物(可能是动态库,静态库,也可能是可执行程序).使用CMak ...

  4. 怎么利用大厂的API将大段音频转成文本

    日常办公中,我们经常要开会和写会议纪要.传统模式下,我们需要非常认真地听会议中每一句话,记下自己认为的核心的话,并在会后经过多次修改形成会议纪要.现在,聪明人已 经不那么干了,借助几百块的讯飞录音笔, ...

  5. [ARM 汇编]高级部分—性能优化与调试—3.4.1 性能分析与优化策略

    性能优化是嵌入式系统开发中的一个重要环节,尤其是在资源受限的环境下.性能优化的目标是提高代码执行速度.降低功耗和减少内存占用.在本章节中,我们将讨论性能分析与优化策略,并通过实例来学习如何应用这些策略 ...

  6.  Python + unittest + ddt + HTMLTestRunner + log + excel + mysql + 企业微信通知, 接口自动化框架V2.0,支持多业务处理,仅需维护 excel 用例,无需要编写代码

    Python + unittest + ddt + HTMLTestRunner + log + excel + mysql + 企业微信通知 + Jenkins 实现的接口自动化框架. 项目介绍 接 ...

  7. 【技术积累】JavaScript中的基础语法【三】

    JavaScript的条件结构 JavaScript中的条件结构主要包括if语句.if-else语句.if-else if语句和switch语句.这些条件结构用于根据不同的条件执行不同的代码块. if ...

  8. 上班第一天 Android 环境配置

    其实是昨天把大概 回归Android开发第一天 学会查 然后等待 反正我是不希望以后再查了 写出来吧 去谷歌那边把android studio下载下来 更新jdk版本(与传统的java开发不同 高版本 ...

  9. Centos7中Jar快速启动脚本

    Centos7中Jar快速启动脚本 创建一个文本,将以下脚本内容复制到文本当中,重命名文本后缀为.sh 注意:根据自己的项目进行更改相关内容,对应注释已说明 #!/bin/sh APP_NAME=ma ...

  10. Diffusers 一岁啦 !

    十分高兴 Diffusers 迎来它的一岁生日!这是令人激动的一年,感谢社区和开源贡献者,我们对我们的工作感到十分骄傲和自豪.去年,文本到图像的模型,如 DALL-E 2, Imagen, 和 Sta ...