首页 > 解决方案 > 为什么 java.io.File 对象集合的数据不会显示在 JSP forEach 标记中?

问题描述

我遇到了 JSP 不显示数据的常见问题。但是,我正在关注文档,并且还尝试了针对该站点上提出的许多问题的解决方案,但均未成功。

如何在 JSP 中显示 java.io.File 数据?如果我这样做正确,是否需要任何其他配置?

我有一个使用 java.io.File 的 File[],它是在 javax.servlet.http.HttpServlet 中创建的。然后我获取 File[] 并将其作为属性添加到我的 HttpSession。然后将其转发到 JSP 文件,传递到 forEach 标记,并填充到表中。(见这篇文章

这是我的 java servlet:

public class LogManagement extends HttpServlet {

    private static final Logger logger = LoggerFactory.getLogger(LogManagement.class);

    
    private static final String BASE_DIRECTORY = System.getProperty("catalina.base");
    private static final File CURRENT_LOGS_FOLDER = new File(BASE_DIRECTORY + "/logs");
    private static final File CAPTURED_LOGS_FOLDER = new File(BASE_DIRECTORY + "/logs/captured");

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        logger.info("GET called on LogManagement servlet");
        try {
            getLogs(request);
            getServletContext().getRequestDispatcher("/LogManagement.jsp").forward(request, response);
        } catch (Exception e) {
            logger.info("ERROR unable to GET log data");
            logger.info(e.getMessage());
        }
    }

    private void getLogs(HttpServletRequest request) {
        logger.info("Getting logs");
        File[] currentLogs = CURRENT_LOGS_FOLDER.listFiles();
        File[] capturedLogs = CAPTURED_LOGS_FOLDER.listFiles();

        HttpSession session = request.getSession();
        session.setAttribute("currentLogs", currentLogs);
        session.setAttribute("capturedLogs", capturedLogs);
        logger.info("Got logs");
    }
}

这是我从这里这里尝试的两个解决方案的 jsp (是的,我知道它使用了一些不推荐使用的标签属性,但我无法更改这些属性)

解决方案1:

        <table style="margin-top: 5px; width: 600px;" align="left">
            <tr>
                <td align="left">
                    Current Logs:
                </td>
            </tr>
            <tr>
                <td>
                    <div class="file-viewer">
                        <table>
                            <c:forEach var="file" items="${currentLogs}">
                                <tr>
                                    <td><c:out value="${file.name}"/></td>
                                    <td><c:out value="${file.length}"/></td>
                                    <td><c:out value="${file.lastModified}"/></td>
                                </tr>
                            </c:forEach>
                        </table>
                    </div>
                </td>
            </tr>
        </table>

解决方案2:

        <table style="margin-top: 5px; width: 600px;" align="left">
            <tr>
                <td align="left">
                    Captured Logs:
                </td>
            </tr>
            <tr>
                <td>
                    <div class="file-viewer">
                        <table>
                            <c:forEach var="file" items="${capturedLogs}">
                                <tr>
                                    <td>${file.name}</td>
                                    <td>${file.length}</td>
                                    <td>${file.lastModified}</td>
                                </tr>
                            </c:forEach>
                        </table>
                    </div>
                </td>
            </tr>
        </table>

这是我在文档和各种 SO 答案中看到的两种解决方案。我也尝试<% out.print(file.getName()); %>在 td 标记内部但没有运气(请参阅无法在表中显示 jsp 数据

这是我得到的例外:

在第 [51]__48 行处理 [/LogManagement.jsp] 时发生异常:________ c:forEach var= file items= ${currentLogs} 49: _____ tr__50: ___________td__c:out value= ${file.name} / /td__51: ___________td__c:out value= ${file.length} / /td__52: _________ td__c:out value= ${file.lastModified} / /td__53: __________/tr__54: _________/c:forEach____Stacktrace:

如果我用虚拟数据替换我正在寻找的数据,我会打印出每个项目。

<td>fileName</td>
<td>fileSize</td>
<td>lastEdited</td>

给出一个表,其行数等于我正在查看的文件数:

"fileName fileSize lastEdited"

这表明我的 forEach 正在工作,但对特定数据的引用却没有。

标签: javajspservlets

解决方案


问题是 JSTL 期望在搜索对象的属性时找到 getter 函数。具体来说,它意味着有一些方法以“get”作为方法名称的前三个字符。

由于 java.io.File 有一个名为“getName()”的方法,因此在示例<td>${file.name}</td>中可以自行工作。但是,length 和 lastModified 都没有“get”作为前缀(.length() 和 .lastModified()),尽管它们只是检索一个值。

有很多方法可以解决这个问题(扩展对象、添加“get”方法等),但我认为最简单的方法是为新对象使用类。

我在上述 .java 文件的末尾添加了一个类,并使用它代替了 java.io.File 对象。它工作得很好:

新班级:

public class LogFile {
    private String name;
    private long length;
    private String lastModified;

    public LogFile(File file) {
        this.name = file.getName();
        this.length = file.length() / 1024;
        this.lastModified = timeStampFormat.format(file.lastModified());
    }

    public String getName() {
        return this.name;
    }

    public long getLength() {
        return this.length;
    }

    public String getLastModified() {
        return this.lastModified;
    }
}

使用对象:

    File[] currentLogFiles = CURRENT_LOGS_FOLDER.listFiles();
    File[] capturedLogFiles = CAPTURED_LOGS_FOLDER.listFiles();
    List<LogFile> currentLogs = new ArrayList<>();
    List<LogFile> capturedLogs = new ArrayList<>();

    if (currentLogFiles != null) {
        for (File file : currentLogFiles) {
            currentLogs.add(new LogFile(file));
        }
    }
    if (capturedLogFiles != null) {
        for (File file : capturedLogFiles) {
            currentLogs.add(new LogFile(file));
        }
    }

    HttpSession session = request.getSession();
    session.setAttribute("currentLogs", currentLogs);
    session.setAttribute("capturedLogs", capturedLogs);

附带说明:据我所知,两者都在 jst 中工作${file.name}<c:out value="${file.name}" />


推荐阅读