JSP中iframe嵌套标签页无法填充表格,触发空指针异常
搭建了一个简单Web应用,包含login.jsp与LoginServlet实现用户校验,校验通过后跳转至Main.jsp。Main.jsp设有两个标签页,第二个标签页通过iframe加载DocTab.jsp,该页面的表格需由MainServlet提供的dataList数据填充。
直接访问http://localhost:8080/MyWebApp/MainServlet时,DocTab.jsp能正常显示填充后的表格;但通过登录流程进入Main.jsp后,第二个标签页抛出异常:
org.apache.jasper.JasperException: java.lang.NullPointerException: Cannot invoke "java.util.List.size()" because "dataList" is null
相关代码
login.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html> <html> <head> <meta charset="ISO-8859-1"> <title>Login</title> </head> <body> <form action="LoginServlet" method="post"> Username: <input type="text" name="username"><br> Password: <input type="password" name="password"><br> <input type="submit" value="Login"> </form> </body> </html>
LoginServlet
package com.example.simplewebapp; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); if(username.equals("1") && password.equals("1")) { response.sendRedirect("Main.jsp"); } else { response.sendRedirect("login.jsp"); } } }
Main.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html> <html> <head> <meta charset="ISO-8859-1"> <title>Main</title> </head> <body> <h1>Welcome to the Main Page!</h1> <ul> <li><a href="#tab1">Tab 1</a></li> <li><a href="#tab2">Document Tab</a></li> </ul> <div id="tab1"> <p>Content for Tab 1.</p> </div> <div id="tab2"> <iframe src="DocTab.jsp"></iframe> </div> </body> </html>
MainServlet
package com.example.simplewebapp; import jakarta.servlet.*; import jakarta.servlet.http.*; import jakarta.servlet.annotation.*; import java.io.IOException; import java.util.ArrayList; import java.util.List; @WebServlet("/MainServlet") public class MainServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List<String> dataList = new ArrayList<String>(); dataList.add("Data 1"); dataList.add("Data 2"); dataList.add("Data 3"); dataList.add("Data 4"); dataList.add("Data 5"); request.setAttribute("dataList", dataList); request.getRequestDispatcher("DocTab.jsp").forward(request, response); } }
DocTab.jsp
<%@ page import="java.util.List" %> <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html> <html> <head> <meta charset="ISO-8859-1"> <title>Document Tab</title> </head> <body> <table border=1 > <tr><th>Column 1</th><th>Column 2</th></tr> <% List<String> dataList = (List<String>) request.getAttribute("dataList"); for(int i=0; i<dataList.size(); i++) { %> <tr><td><%=dataList.get(i)%></td><td>Row <%=i+1%>, Column 2</td></tr> <% } %> </table> </body> </html>
通过登录流程进入Main.jsp后,iframe直接请求DocTab.jsp,该请求未经过MainServlet处理,因此request对象中不存在dataList属性,导致DocTab.jsp调用dataList.size()时触发空指针异常。
而直接访问MainServlet时,Servlet会先创建dataList并放入request,再转发到DocTab.jsp,此时request中存在数据,页面能正常渲染。
方案1:修改iframe请求路径指向MainServlet
修改Main.jsp中iframe的src属性为MainServlet,让iframe请求先经过Servlet处理数据:
<div id="tab2"> <iframe src="MainServlet"></iframe> </div>
这样iframe加载时会触发MainServlet的doGet方法,生成dataList后转发到DocTab.jsp,页面即可正常获取数据。
方案2:给DocTab.jsp增加空值校验(可选,提升健壮性)
在DocTab.jsp中增加dataList的空判断,避免空指针异常,同时提示无数据的情况:
<table border=1 > <tr><th>Column 1</th><th>Column 2</th></tr> <% List<String> dataList = (List<String>) request.getAttribute("dataList"); if (dataList != null) { for(int i=0; i<dataList.size(); i++) { %> <tr><td><%=dataList.get(i)%></td><td>Row <%=i+1%>, Column 2</td></tr> <% } } else { %> <tr><td colspan="2">暂无数据</td></tr> <% } %> </table>
内容的提问来源于stack exchange,提问作者user9753394

