Java Spring项目如何将循环执行结果实时展示到HTML页面
实时进度展示实现方案
你原有代码无法实现实时展示的核心原因是:HTTP请求默认是同步的,服务端会等待整个接口方法执行完毕后才会返回响应,循环过程中控制台的打印仅存在于服务端本地,不会实时推送给前端。你需要按以下步骤改造代码:
1 后端改造
1.1 开启Spring异步支持
在Spring Boot启动类上添加@EnableAsync注解,开启异步方法执行能力:
@EnableAsync @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
1.2 新增进度存储与异步任务逻辑
用线程安全的容器存储进度,把循环逻辑放到异步方法中执行:
// 进度存储工具类(单用户场景可用,多用户需绑定唯一任务ID) public class ProgressHolder { public static volatile String currentProgress = "0%"; } // 异步任务Service @Service public class ProgressService { @Async public void runProgressTask() { // 重置进度 ProgressHolder.currentProgress = "0%"; for (int i = 1; i <= 100; i++) { try { // 模拟业务处理耗时,实际场景可删除 Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } if(i==20){ ProgressHolder.currentProgress = "20%"; }else if (i==40){ ProgressHolder.currentProgress = "40%"; }else if (i==60){ ProgressHolder.currentProgress = "60%"; }else if (i==80){ ProgressHolder.currentProgress = "80%"; }else if (i==100){ ProgressHolder.currentProgress = "100%"; } } } }
1.3 改造Controller接口
新增触发任务和查询进度的两个接口:
@RestController public class ProgressController { @Autowired private ProgressService progressService; // 触发进度任务接口 @GetMapping("/startProgress") public void startProgress() { progressService.runProgressTask(); } // 查询当前进度接口 @GetMapping("/getProgress") public String getProgress() { return ProgressHolder.currentProgress; } // 返回进度展示页面 @GetMapping("/progressPage") public String progressPage() { return "progress"; } }
2 前端改造
在templates目录下新建progress.html(Thymeleaf模板页面):
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>进度展示</title> </head> <body> <h3>当前执行进度:<span id="progressText">0%</span></h3> <button id="startBtn">开始执行任务</button> <script> const startBtn = document.getElementById('startBtn'); const progressText = document.getElementById('progressText'); let timer = null; startBtn.addEventListener('click', function() { // 先触发任务执行 fetch('/startProgress').then(() => { // 开启轮询查询进度 timer = setInterval(() => { fetch('/getProgress') .then(res => res.text()) .then(progress => { progressText.innerText = progress; // 进度到100%停止轮询 if (progress === '100%') { clearInterval(timer); } }) }, 200); // 每200ms查询一次,可按需调整 }); }) </script> </body> </html>
3 使用方式
启动项目后访问http://localhost:端口号/progressPage,点击「开始执行任务」按钮即可看到进度实时更新效果。
可选优化
- 多用户场景下每次触发任务生成唯一的
taskId,进度与taskId绑定,避免不同用户的进度冲突 - 可改用SSE(服务端推送事件)替代轮询,减少无效请求开销
- 任务执行完成后及时清理存储的进度数据,避免内存占用
内容的提问来源于stack exchange,提问作者Damazy Kowalski
相关产品推荐
相关产品推荐

