Spring Boot如何将控制器Java对象经Thymeleaf传给JS绘制图表
问题根源排查
1. 注解冲突导致视图渲染完全失效
- 类上标注的
@RestController是Spring的组合注解,等价于@Controller+ 类下所有方法默认携带@ResponseBody,所有方法的返回值都会被直接序列化为JSON响应,完全绕过Thymeleaf视图解析流程。这就是你此前使用ModelAndView传值没有达到预期效果的核心原因。 - 修正逻辑:拆分Controller的职责,专门负责返回页面的类使用
@Controller注解;返回JSON的REST接口单独保留@RestController,两类逻辑不要混在同一个类中。
2. 视图路由与模板位置不匹配
- 当前测试方法配置的视图路径为
message/test,对应模板需要放置在resources/templates/message/test.html路径下,若你直接使用resources/templates/index.html作为可视化页面,视图名称与实际模板位置不匹配,会导致Thymeleaf无法找到对应模板。
3. 前端JS逻辑断层
- 内联脚本中调用了未定义的
buildChart()方法,实际图表初始化逻辑写在外部chart-action.js的window.onload事件中,存在函数作用域不连通、加载时机不匹配的问题,控制台会直接抛出buildChart is not defined的脚本错误,导致图表无法正常渲染。 - 现有代码将
coronaTest同时赋值给newConfirmed和totalConfirmed两个变量,数据逻辑存在冗余错误。
修正后的实现方案
1. 控制器代码调整
拆分控制器职责,避免注解冲突:
// 专门负责视图渲染的控制器,使用@Controller而非@RestController @Controller public class DashboardViewController { @Autowired private RestTemplate restTemplate; private final String urlCorona = "https://api.covid19api.com/"; // 映射到项目首页,返回index.html视图 @GetMapping("/dashboard") public ModelAndView getCoronaDashboard() { ModelAndView mav = new ModelAndView("index"); CoronaInformation coronaInfo = restTemplate.getForObject(urlCorona + "summary", CoronaInformation.class); // 传递完整的全球统计对象到视图层,不要只传递单个字段 mav.addObject("globalStats", coronaInfo.getGlobal()); return mav; } } // 原有的REST接口控制器,保留@RestController即可 @RestController @RequestMapping("/api") public class CoronaApiController { @Autowired private RestTemplate restTemplate; private final String urlCorona = "https://api.covid19api.com/"; @GetMapping("/corona/summary") public CoronaInformation getAllCoronaInformations() { return restTemplate.getForObject(urlCorona + "summary", CoronaInformation.class); } }
2. 前端代码调整
- 修改页面内联Thymeleaf脚本,将模型数据挂载到全局JS作用域,供外部图表逻辑读取,移除不存在的函数调用:
<!-- body开头的内联脚本 --> <script th:inline="javascript"> // 把Thymeleaf模型中的统计数据转为全局可访问的JS变量 window.coronaGlobalStats = /*[[${globalStats}]]*/ { newConfirmed: 0, totalConfirmed: 0, newDeaths: 0, totalDeaths: 0 }; </script>
- 修改
chart-action.js,读取全局变量完成图表初始化:
window.addEventListener('load', function () { const ctx = document.getElementById('coronaChart'); const stats = window.coronaGlobalStats; new Chart(ctx, { type: 'pie', data: { labels: [ '新增确诊', '累计确诊', '新增死亡', '累计死亡' ], datasets: [{ label: '全球疫情统计', data: [ stats.newConfirmed, stats.totalConfirmed, stats.newDeaths, stats.totalDeaths ], backgroundColor: [ 'rgb(255, 99, 132)', 'rgb(54, 162, 235)', 'rgb(255, 205, 86)', 'rgb(75, 192, 192)' ], hoverOffset: 4 }] }, options: { scales: { y: { beginAtZero: true } } } }); });
调试注意事项
- 检查项目
pom.xml中是否正确引入Thymeleaf启动依赖,确认视图解析器默认配置为模板路径classpath:/templates/、文件后缀.html。 - 访问页面时直接输入视图路由(如
http://localhost:8080/dashboard),不要与原有REST接口的路由定义混用。
内容的提问来源于stack exchange,提问作者Alcyl
相关产品推荐
相关产品推荐

