如何通过单击JSP页面中的超链接或按钮将当前项传递给Java方法?

问题描述:

我有一个HTML表格,从该表格中显示的数据库中提取行。我希望用户能够通过单击除每行之外的删除超链接或按钮来删除一行。如何通过单击JSP页面中的超链接或按钮将当前项传递给Java方法?

如何在页面上调用JSP函数,当用户单击每个删除超链接或按钮时,以便我可以从数据库中删除该行的条目? <a><button>标签究竟应该调用JSP函数?

请注意,我需要调用一个JSP函数,而不是JavaScript函数。

最简单的方法:只让该链接指向一个JSP页面,并通过行ID作为参数:

<a href="delete.jsp?id=1">delete</a> 

而且在delete.jsp(我留下明显的请求参数检验/验证除外)

<% dao.delete(Long.valueOf(request.getParameter("id"))); %> 

但是,这是一个非常poor practice(即仍然是一个保守的),并有两个原因:

  1. 修改服务器端数据的HTTP请求不应该由GET完成,而是由POST完成。链接是隐式的GET。想象一下,当像googlebot这样的网络爬虫试图关注所有删除链接时会发生什么。您应该使用<form method="post"><button type="submit">作为删除操作。但是,您可以使用CSS将按钮设置为链接样式。编辑链接,只需预先加载项目以预先填写编辑表单即可安全地进行GET。

  2. 把业务逻辑使用小脚本(那些<% %>东西)气馁(功能你称呼它)在JSP。您应该使用一个Servlet来控制,预处理和后处理HTTP请求。

既然你没有告诉你的问题一个servlet的任何一句话,我怀疑你已经在使用小脚本从数据库加载数据,并在表中显示。这也应该由一个servlet完成。

下面是一个基本的启动示例,如何做到这一切。我不知道表格数据代表什么,所以我们以Product为例。

public class Product { 
    private Long id; 
    private String name; 
    private String description; 
    private BigDecimal price; 
    // Add/generate public getters and setters. 
} 

然后它使用JSTL JSP文件(刚落,在/WEB-INF/libjstl-1.2.jar进行安装)来显示产品表中的每一行中的编辑链接和删除按钮:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 
... 
<form action="products" method="post"> 
    <table> 
     <c:forEach items="${products}" var="product"> 
      <tr> 
       <td><c:out value="${fn:escapeXml(product.name)}" /></td> 
       <td><c:out value="${product.description}" /></td> 
       <td><fmt:formatNumber value="${product.price}" type="currency" currencyCode="USD" /></td> 
       <td><a href="${pageContext.request.contextPath}/product?edit=${product.id}">edit</a></td> 
       <td><button type="submit" name="delete" value="${product.id}">delete</button></td> 
      </tr> 
     </c:forEach> 
    </table> 
    <a href="${pageContext.request.contextPath}/product">add</a> 
</form> 

将其命名为products.jsp并将其放入/WEB-INF文件夹中,以便它不能通过URL直接访问(以便最终用户*为此调用servlet)。

下面是servlet的大致模样(验证略去了):

@WebServlet("/products") 
public class ProductsServlet extends HttpServlet { 

    private ProductDAO productDAO; // EJB, plain DAO, etc. 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     List<Product> products = productDAO.list(); 
     request.setAttribute("products", products); // Will be available as ${products} in JSP. 
     request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response); 
    } 

    @Override 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     String delete = request.getParameter("delete"); 

     if (delete != null) { // Is the delete button pressed? 
      productDAO.delete(Long.valueOf(delete)); 
     } 

     response.sendRedirect(request.getContextPath() + "/products"); // Refresh page with table. 
    } 

} 

下面介绍如何在/WEB-INF/product.jsp添加/编辑的形式可以是这样的:

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> 
... 
<form action="product" method="post"> 
    <label for="name">Name</label> 
    <input id="name" name="name" value="${fn:escapeXml(product.name)}" /> 
    <br/> 
    <label for="description">Description</label> 
    <input id="description" name="description" value="${fn:escapeXml(product.description)}" /> 
    <br/> 
    <label for="price">Price</label> 
    <input id="price" name="price" value="${fn:escapeXml(product.price)}" /> 
    <br/> 
    <button type="submit" name="save" value="${product.id}">save</button> 
</form> 

fn:escapeXml()就在那里当编辑数据重新显示时,为了防止XSS attacks,它的确与<c:out>完全相同,只是更适合用在属性中。

这里的product servlet可以看怎么样(略去了一遍,转换/验证):

@WebServlet("/product") 
public class ProductServlet extends HttpServlet { 

    private ProductDAO productDAO; // EJB, plain DAO, etc. 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     String edit = request.getParameter("edit"); 

     if (edit != null) { // Is the edit link clicked? 
      Product product = productDAO.find(Long.valueOf(delete)); 
      request.setAttribute("product", product); // Will be available as ${product} in JSP. 
     } 

     request.getRequestDispatcher("/WEB-INF/product.jsp").forward(request, response); 
    } 

    @Override 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     String save = request.getParameter("save"); 

     if (save != null) { // Is the save button pressed? (note: if empty then no product ID was supplied, which means that it's "add product". 
      Product product = (save.isEmpty()) ? new Product() : productDAO.find(Long.valueOf(save)); 
      product.setName(request.getParameter("name")); 
      product.setDescription(request.getParameter("description")); 
      product.setPrice(new BigDecimal(request.getParameter("price"))); 
      productDAO.save(product); 
     } 

     response.sendRedirect(request.getContextPath() + "/products"); // Go to page with table. 
    } 

} 

部署并运行它。您可以通过http://example.com/contextname/products打开表格。

参见:

+0

谢谢。我会尝试实现这一点,因为它更有意义。我现在的代码很混乱,需要重组来实现你提出的方法。并感谢参考链接。 – nilay 2010-06-20 17:40:53

+0

不客气。是的,将所有内容混淆在一个大的JSP文件中是相当混乱和难以维护:)祝你好运。 – BalusC 2010-06-20 17:54:29