SpringBoot两个Controller间如何成功传递ArrayList数据
报错根因
你出现IndexOutOfBoundsException的核心原因有3个:
- 你在Spring MVC的Controller中直接
new PageController()创建实例时,只执行了类的初始化逻辑,从未调用mainProgram()方法执行命令、填充runtime列表,新创建实例的runtime属性就是个空的ArrayList,直接调用get(0)必然越界。 - 你的
PageController是独立的普通Java类,没有纳入Spring容器管理,和Web层的Controller没有任何数据共享机制,你写的main方法只有单独运行PageController类时才会执行,Web请求场景下根本不会触发。 - 现有代码还存在两个隐藏bug:一是
runCMD方法读到命令输出的第一行就直接return,拿不到完整执行结果;二是配置文件读取写死了src/main/resources路径,项目打成jar包部署后该路径不存在,会读不到配置。
修复方案
1. 改造PageController为Spring管理的组件
去掉没用的main方法,把命令执行、数据加载的逻辑放到Bean初始化完成后自动执行,修正配置读取和命令执行的逻辑,修改后代码如下:
package org.monitor; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.io.*; import java.util.*; @Component public class PageController { private Properties prop = new Properties(); private ArrayList<String> runtimeCommand = new ArrayList<>(); private ArrayList<String> runtime = new ArrayList<>(); // Bean初始化完成后自动执行配置加载、命令执行逻辑 @PostConstruct public void init() throws IOException { loadProperty(); mainProgram(); } public void mainProgram() throws IOException{ for (String cmd : runtimeCommand) { String output = runCMD(cmd); runtime.add(output); } } public String runCMD(String commandline) throws IOException { Process p; if(System.getProperty("os.name").toLowerCase().contains("windows")) { p = Runtime.getRuntime().exec("cmd.exe /C " + commandline); } else { p = Runtime.getRuntime().exec(commandline); } // 修正读逻辑,读完所有输出再返回,不要读一行就退出 StringBuilder outputBuilder = new StringBuilder(); try(BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream(), "GBK"))) { String line; while((line = reader.readLine()) != null) { outputBuilder.append(line).append(System.lineSeparator()); } } // 等待命令执行完成,避免产生僵尸进程 try { p.waitFor(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IOException("命令执行被中断", e); } return outputBuilder.toString().trim(); } public void loadProperty() throws IOException { // 用类路径读取资源,兼容jar包部署场景 try(InputStream input = PageController.class.getClassLoader().getResourceAsStream("properties/page.properties")) { if (input == null) { throw new FileNotFoundException("配置文件page.properties不存在"); } prop.load(input); String cmdConfig = prop.getProperty("runtime.cmd"); if (cmdConfig != null && !cmdConfig.isEmpty()) { runtimeCommand.addAll(Arrays.asList(cmdConfig.split(","))); } } } // 对外提供获取runtime列表的方法 public List<String> getRuntimeList() { return Collections.unmodifiableList(runtime); } }
2. 改造Web层Controller,注入PageController Bean
不要自己new PageController实例,直接通过Spring注入已经初始化完成、加载好数据的Bean,取数据前先判断非空,避免越界:
package org.boot; import org.monitor.PageController; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; import java.util.List; @RestController public class Controller { @Autowired private PageController pageController; @GetMapping("/web") public String index() { return "Greetings from Spring Boot Quartz!"; } @RequestMapping("/web/page") public ModelAndView page() { ModelAndView model = new ModelAndView("page"); List<String> runtimeList = pageController.getRuntimeList(); // 把完整列表传给JSP用于表格渲染 model.addObject("runtimeList", runtimeList); // 兼容原有${runtime}表达式,判断非空再传值 model.addObject("runtime", runtimeList.isEmpty() ? "" : runtimeList.get(0)); return model; } }
3. JSP侧适配(渲染全量表格)
如果要基于ArrayList渲染完整表格,在JSP中引入JSTL标签遍历列表即可,示例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>运行状态</title> </head> <body> <table border="1"> <tr> <th>命令执行结果</th> </tr> <c:forEach items="${runtimeList}" var="item"> <tr> <td>${item}</td> </tr> </c:forEach> </table> </body> </html>
注意事项
- 如果你需要每次请求都重新执行命令获取最新数据,就把
mainProgram()的调用从@PostConstruct方法移到Controller的page()方法里,不要在服务初始化时只执行一次。 - 执行系统命令时要做好参数校验,避免命令注入安全风险。
内容的提问来源于stack exchange,提问作者Mainaqisyah
相关产品推荐
相关产品推荐

