方法一

public SseEmitter completion() {
        SseEmitter emitter = new SseEmitter(300_000L);

        emitter.onCompletion(() -> log.info("SSE完成"));
        emitter.onTimeout(() -> {
            log.info("SSE超时");
            emitter.complete();
        });
        emitter.onError(e -> log.error("SSE错误", e));

        JSONArray jsonArray = buildJsonArray();

        sseTaskExecutor.submit(() -> {
            try {
                emitter.send(SseEmitter.event().name("start").data("start"));
                for (Object o : jsonArray) {
                    emitter.send(SseEmitter.event().name("message").data(o));
                    Thread.sleep(500);
                }
                emitter.send(SseEmitter.event().name("end").data("end"));
                emitter.complete();
            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        });

        return emitter;
    }

    private JSONArray buildJsonArray() {
        JSONArray jsonArray = new JSONArray();
        JSONObject j1 = new JSONObject();
        j1.put("role", "user");
        j1.put("content", "我的t1");
        jsonArray.add(j1);

        JSONObject j2 = new JSONObject();
        j2.put("role", "assistant");
        j2.put("content", "你好2");
        jsonArray.add(j2);

        JSONObject j3 = new JSONObject();
        j3.put("role", "user");
        j3.put("content", "我的t3");
        jsonArray.add(j3);

        JSONObject j4 = new JSONObject();
        j4.put("role", "assistant");
        j4.put("content", "你好4");
        jsonArray.add(j4);
        return jsonArray;
    }

方法二

public void test(HttpServletResponse response) {
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("utf-8");

        try (final PrintWriter writer = response.getWriter()) {
            // 要推送的内容
            final String content = "你好,我的朋友,快过年了,提前祝你新年快乐!";
            int len = content.length();
            int endIndex = 0;
            // 每隔2个字符推送一次,模拟打字机效果
            while (endIndex < len) {
                endIndex = Math.min(endIndex + 2, len);
                final String subContent = content.substring(0, endIndex);
                // 将要推送的内容封装成JSON格式,模拟实际开发中的数据格式,非必须
                final JSONObject json = new JSONObject();
                json.put("data", subContent);
                json.put("code", HttpStatus.OK.value());
                // 最后一次推送时,type为finish,表示推送结束,其它情况为add
                final String type = endIndex == len
                        ? "finish"
                        : "add";
                json.put("type", type);
                // 组装成SSE格式的数据,发送给前端,这个格式(data: content\n\n)是固定的,content是自定义的推送内容
                writer.write(getSseContent(UUID.randomUUID().toString(), type, json.toJSONString()));
                writer.flush();
                // 稍微给点停顿,防止数据发送太快,浏览器接收不过来
                TimeUnit.MILLISECONDS.sleep(100);
            }
        } catch (Exception e) {
            Thread.currentThread().interrupt();
        }
    }

    private String getSseContent(String id, String event, String data) {
        return "id: " + id + "\n" +
                "event: " + event + "\n" +
                "data: " + data + "\n\n";
    }