通过out.println生成的JSP按钮无法执行Java代码的问题
问题分析与解决方案
你遇到的核心问题是混淆了服务器端代码和客户端代码的执行时机:
- JSP里的
<% %>代码是在服务器渲染页面时执行的后端逻辑; - 按钮的
onclick是页面加载完成后,在浏览器中触发的客户端事件。
当你通过Java的out.println输出带<% %>的字符串时,服务器不会再解析这些标签,只会把它们当成普通文本输出到HTML里,所以绑定的Java代码根本不会被执行。直接在JSP里写按钮时,服务器会正常解析<% %>,所以代码能运行。
下面给出两种可行的解决方案:
方案一:使用表单提交(简单直接)
把每个按钮包装在一个表单里,点击按钮时提交表单到后端处理页面,传递菜品名称和数量参数。
修改getMenu方法:
public String getMenu(String Category) throws SQLException, IOException, ClassNotFoundException { Connection connection = Database.connectToDatabase(); // 替换成PreparedStatement避免SQL注入风险 String sql = "SELECT Name, Cost FROM MenuTable WHERE category = ?"; PreparedStatement st = connection.prepareStatement(sql); st.setString(1, Category); ResultSet rs = st.executeQuery(); String categoryMenu = ""; while (rs.next()) { String itemName = rs.getString(1); categoryMenu += "<div class=\"menu-item\">\n"+ "<div class=\"menu-item-text\">\n"+ "<h3 class=\"menu-item-heading\">\n"+ "<form action=\"addToCart.jsp\" method=\"post\" style=\"display: inline;\">"+ "<input type=\"hidden\" name=\"itemName\" value=\"" + itemName + "\">"+ "<input type=\"hidden\" name=\"quantity\" value=\"1\">"+ "<button type=\"submit\">"+ "<span class=\"menu-item-name\">"+itemName+"</span>\n"+ "<span class=\"menu-item-price\">£"+rs.getString(2)+"</span>\n"+ "</button>"+ "</form>"+ "</h3>\n"+ "</div>\n"+ "</div> \n"; } // 务必关闭数据库资源 rs.close(); st.close(); connection.close(); return categoryMenu; }
创建addToCart.jsp处理请求:
<%@ page import="Order" %> <% request.setCharacterEncoding("UTF-8"); String itemName = request.getParameter("itemName"); int quantity = Integer.parseInt(request.getParameter("quantity")); if (itemName != null && !itemName.isEmpty()) { Order.inputIntoCtable(itemName, quantity); // 重定向回原页面,避免重复提交 response.sendRedirect(request.getHeader("Referer")); } %>
方案二:使用AJAX异步请求(无刷新体验更好)
通过JavaScript发送异步请求到后端接口,点击按钮时不刷新页面就能完成添加操作。
修改getMenu方法:
public String getMenu(String Category) throws SQLException, IOException, ClassNotFoundException { Connection connection = Database.connectToDatabase(); PreparedStatement st = connection.prepareStatement("SELECT Name, Cost FROM MenuTable WHERE category = ?"); st.setString(1, Category); ResultSet rs = st.executeQuery(); String categoryMenu = ""; while (rs.next()) { String itemName = rs.getString(1); categoryMenu += "<div class=\"menu-item\">\n"+ "<div class=\"menu-item-text\">\n"+ "<h3 class=\"menu-item-heading\">\n"+ "<button onclick=\"addToCart('" + itemName + "', 1)\">"+ "<span class=\"menu-item-name\">"+itemName+"</span>\n"+ "<span class=\"menu-item-price\">£"+rs.getString(2)+"</span>\n"+ "</button>"+ "</h3>\n"+ "</div>\n"+ "</div> \n"; } // 添加AJAX处理函数 categoryMenu += "<script>\n"+ "function addToCart(itemName, quantity) {\n"+ "fetch('addToCartServlet', {\n"+ "method: 'POST',\n"+ "headers: {\n"+ "'Content-Type': 'application/x-www-form-urlencoded'\n"+ "},\n"+ "body: 'itemName=' + encodeURIComponent(itemName) + '&quantity=' + quantity\n"+ "})\n"+ ".then(response => response.text())\n"+ ".then(data => {\n"+ "console.log('添加成功:', data);\n"+ // 这里可以添加成功提示,比如弹出消息或更新购物车UI "})\n"+ ".catch(error => console.error('添加失败:', error));\n"+ "}\n"+ "</script>"; // 关闭数据库资源 rs.close(); st.close(); connection.close(); return categoryMenu; }
创建AddToCartServlet后端接口:
import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/addToCartServlet") public class AddToCartServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { request.setCharacterEncoding("UTF-8"); String itemName = request.getParameter("itemName"); int quantity = Integer.parseInt(request.getParameter("quantity")); try { Order.inputIntoCtable(itemName, quantity); response.setContentType("text/plain"); response.getWriter().write("添加成功"); } catch (Exception e) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.getWriter().write("添加失败: " + e.getMessage()); } } }
重要提醒
你原来的代码使用Statement拼接SQL字符串,存在严重的SQL注入风险,必须替换成PreparedStatement(上面的示例已经修改),这是Java数据库操作的基本规范。
内容的提问来源于stack exchange,提问作者Leo Nguyen
相关产品推荐
相关产品推荐

