首先流式输出的响应格式是:content-type: text/event-stream;charset=UTF-8,返回的内容自然是流式响应。
这里为了模拟打字机效果,我设置了睡眠时间来进行模拟
方式一:StreamingResponseBody
@GetMapping("/stream")
public StreamingResponseBody stream(HttpServletResponse response) {
// ";charset=UTF-8" 必须拼接,不然中文会乱码
response.setContentType(MediaType.TEXT_EVENT_STREAM_VALUE+";charset=UTF-8");
return outputStream -> {
// 将数据写入输出流
for (String s : "Hello, World!".split("")) {
try {
outputStream.write(s.getBytes());
outputStream.flush();
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
方式二:ResponseEntity<StreamingResponseBody>
@RequestMapping(value = "/stream")
public ResponseEntity<StreamingResponseBody> stream() {
String msg = " 什么是爱而不得? \n" +
"东边日出西边雨,道是无晴却有晴。\n" +
"他朝若是同淋雪,此生也算共白头。\n" +
"我本将心向明月,奈何明月照沟渠。\n" +
"此时相望不相闻,愿逐月华流照君。\n" +
"衣带渐宽终不悔,为伊消得人憔悴。\n" +
"此情可待成追忆,只是当时已惘然。\n" +
"人生若只如初见,何事西风悲画扇。\n" +
"曾经沧海难为水,除却巫山不是云。\n" +
"何当共剪西窗烛,却话巴山夜雨时。\n" +
"天长地久有时尽,此恨绵绵无绝期。\n" +
"\n";
return ResponseEntity.ok().header("content-type",MediaType.TEXT_EVENT_STREAM_VALUE+";charset=UTF-8").body(outputStream -> {
// 使用outputStream写入数据
for (String word : msg.replaceAll("","").split("")) {
try {
outputStream.write(word.getBytes());
outputStream.flush();
TimeUnit.MILLISECONDS.sleep(100);
} catch (Exception e) {
// 处理异常
e.printStackTrace();
}
}
});
}
方式三:HttpServletResponse
@GetMapping("/stream")
public void stream(HttpServletResponse res) throws Exception{
//log.info("【prompt内容】:{}", prompt);
String str = " 什么是爱而不得? \n" +
"东边日出西边雨,道是无晴却有晴。\n" +
"他朝若是同淋雪,此生也算共白头。\n" +
"我本将心向明月,奈何明月照沟渠。\n" +
"此时相望不相闻,愿逐月华流照君。\n" +
"衣带渐宽终不悔,为伊消得人憔悴。\n" +
"此情可待成追忆,只是当时已惘然。\n" +
"人生若只如初见,何事西风悲画扇。\n" +
"曾经沧海难为水,除却巫山不是云。\n" +
"何当共剪西窗烛,却话巴山夜雨时。\n" +
"天长地久有时尽,此恨绵绵无绝期。\n" +
"\n";
// 响应流
res.setHeader("Content-Type", "text/event-stream");
res.setContentType("text/event-stream");
res.setCharacterEncoding("UTF-8");
res.setHeader("Pragma", "no-cache");
ServletOutputStream out = null;
try {
out = res.getOutputStream();
for (int i = 0; i < str.length(); i++) {
out.write(String.valueOf(str.charAt(i)).getBytes());
// 更新数据流
out.flush();
Thread.sleep(100);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
然后前端的话,也需要sse来保持连接用于服务端推送内容。