背景

公司项目的批处理微服务,一般是在晚上固定时段通过定时任务执行,但为了预防执行失败,我们定义了对应的应急接口,必要时可以通过运维在终端中进行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. IAR学习笔记:将app和boot合并

    一.前言 最近用到了IAR编译调试软件,但是生成的app.bin和boot.bin是独立分开的,看了下IAR官方note和其他大佬的解释,找到了俩合并的方法: 参考: https://www.iar. ...

  2. Kubernetes(k8s)服务账号Service Accounts

    目录 一.系统环境 二.前言 三.服务账号Service Accounts简介 四.用户账号与服务账号区别 五.服务账号(Service Accounts) 5.1 创建服务账号(Service Ac ...

  3. Spring Boot 日志文件

    Spring Boot 日志文件 日志文件是用于记录系统操作事件的记录文件或文件集合,可分为事件日志和消息日志.具有处理历史数据.诊断问题的追踪以及理解系统的活动等重要作用. 事件日志记录系统的执行中 ...

  4. Vue基础技术之——数据绑定

    Vue数据大致绑定分为两类: 1.单向数据绑定(v-bind): 数据只能从data流向页面. 2.双向数据绑定(v-model):数据不仅能从data流向页面,还能从页面流向data. 话不多说,先 ...

  5. 3D降噪_时域降噪待补充

    视频去噪方法按照处理域的不同可分为空间域.频域.小波域.时域.时-空域去噪等,但是不同域之间的去噪方法会发生重叠现象,或者一种去噪方法会或涉及多个处理域.例如,在时域或时-空域去噪方法中也可使用频域的 ...

  6. 揭秘 .NET 中的 TimerQueue(上)

    前言 TimerQueue 是.NET中实现定时任务的核心组件,它是一个定时任务的管理器,负责存储和调度定时任务.它被用于实现很多 .NET 中的定时任务,比如 System.Threading.Ti ...

  7. 关于DVWA靶场高难度命令执行的代码审计

    需要的环境:dvwa 使用的工具:PHP手册 high难度源代码: <?php if( isset( $_POST[ 'Submit' ] ) ) { // Get input $target ...

  8. 【游记】NOIP2022 预备赛游记

    Day -2 \(NOIP\) 就要来了,\(CSYZ\) 斥巨资给我们在 \(NOIP\) 正式考点举办了一场 \(NOIP\) 预备赛,真是太感动了~~ \(cy\) 说明天要颁奖,激动激动! D ...

  9. 【Go blog】Govulncheck v1.0.0 发布了!

    我们很高兴地宣布,govulncheck v1.0.0 已经发布,同时也发布了用于集成扫描到其他工具的 API 的 v1.0.0 版本!Go 对漏洞管理的支持首次在去年九月宣布.从那时起,我们做了一些 ...

  10. npm install -g 错误集锦

    1.切换源安装:npm config set registry http://registry.cnpmjs.org,参考http://yijiebuyi.com/blog/b12eac891cdc5 ...