2.2 隐藏域
使用隐藏域来保持状态类似于URL
重写技术,但不是将值附加到URL
上,而是放到HTML
表单的隐藏域中。当表单提交时,隐藏域的值也同时提交到服务器端。隐藏域技术仅当网页有表单时有效。该技术相对于 URL
重写的优势在于:没有字符数限制,同时无须额外的编码。但该技术同URL
重写一样,不适合跨越多个界面。
清单2.3展示了如何通过隐藏域来更新客户信息。清单2.2的Customer类为客户对象模型。
清单2.2 Customer类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| package app02a.hiddenfields; public class Customer { private int id; private String name; private String city; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } }
|
清单2.3 CustomerServlet类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| package app02a.hiddenfields; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
@WebServlet( name = "CustomerServlet", urlPatterns = {"/customer", "/editCustomer", "/updateCustomer"} ) public class CustomerServlet extends HttpServlet { private static final long serialVersionUID = -20L; private List<Customer> customers = new ArrayList<Customer>(); @Override public void init() throws ServletException { Customer customer1 = new Customer(); customer1.setId(1); customer1.setName("Donald D."); customer1.setCity("Miami"); customers.add(customer1); Customer customer2 = new Customer(); customer2.setId(2); customer2.setName("Mickey M."); customer2.setCity("Orlando"); customers.add(customer2); } private void sendCustomerList(HttpServletResponse response) throws IOException { response.setContentType("text/html"); PrintWriter writer = response.getWriter(); writer.println("<html><head><title>Customers</title></head>" + "<body><h2>Customers </h2>"); writer.println("<ul>"); for (Customer customer : customers) { writer.println("<li>" + customer.getName() + "(" + customer.getCity() + ") (" + "<a href='editCustomer?id=" + customer.getId() + "'>edit</a>)"); } writer.println("</ul>"); writer.println("</body></html>"); } private Customer getCustomer(int customerId) { for (Customer customer : customers) { if (customer.getId() == customerId) { return customer; } } return null; } private void sendEditCustomerForm(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html"); PrintWriter writer = response.getWriter(); int customerId = 0; try { customerId = Integer.parseInt(request.getParameter("id")); } catch (NumberFormatException e) {} Customer customer = getCustomer(customerId); if (customer != null) { writer .println("<html><head>" + "<title>Edit Customer</title></head>" + "<body><h2>Edit Customer</h2>" + "<form method='post' " + "action='updateCustomer'>"); writer.println( "<input type='hidden' name='id' value='" + customerId + "'/>"); writer.println("<table>"); writer .println("<tr><td>Name:</td><td>" + "<input name='name' value='" + customer.getName().replaceAll("'", "'") + "'/></td></tr>"); writer .println("<tr><td>City:</td><td>" + "<input name='city' value='" + customer.getCity().replaceAll("'", "'") + "'/></td></tr>"); writer.println("<tr>" + "<td colspan='2' style='text-align:right'>" + "<input type='submit' value='Update'/></td>" + "</tr>"); writer.println("<tr><td colspan='2'>" + "<a href='customer'>Customer List</a>" + "</td></tr>"); writer.println("</table>"); writer.println("</form></body>"); } else { writer.println("No customer found"); } } @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String uri = request.getRequestURI(); if (uri.endsWith("/customer")) { sendCustomerList(response); } else if (uri.endsWith("/editCustomer")) { sendEditCustomerForm(request, response); } } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int customerId = 0; try { customerId = Integer.parseInt(request.getParameter("id")); } catch (NumberFormatException e) {} Customer customer = getCustomer(customerId); if (customer != null) { customer.setName(request.getParameter("name")); customer.setCity(request.getParameter("city")); } sendCustomerList(response); } }
|
CustomerServlet
类继承自HttpServlet
,其URL
映射分别为/customer
、/editCustomer
和 /updateCustomer
。前两个URL
会调用Servlet
的doGet
方法, 而/updateCustomer
会调用doPost
方法。
/customer
是本例的入口URL
。该URL
会列举出在 init
方法中所初始化的类级别的列表对象customers
(在 真实应用中,通常是从数据库中获取用户信息),如图下图所示。
如图上图所示,每个客户信息后都有一个edit
链接, 每个edit
链接的href
属性为 /editCustomer?id=customerId
。当通过/editCustomer
访问servlet
时, servlet
会返回一个编辑表单,如下图所示。
此时,servlet返回的表单如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| <form method="post" action="updateCustomer"> <input type="hidden" name="id" value="1"> <table> <tbody> <tr> <td>Name:</td> <td> <input name="name" value="Donald D."> </td> </tr> <tr> <td>City:</td> <td> <input name="city" value="Miami"> </td> </tr> <tr> <td colspan="2" style="text-align:right"> <input type="submit" value="Update"> </td> </tr> <tr> <td colspan="2"> <a href="customer">Customer List</a> </td> </tr> </tbody> </table> </form>
|
可以看到表达中的隐藏域为<input type="hidden" name="id" value="1">
.
该隐藏域保存了所编辑的客户id
,因为隐藏域包含在表单中,所以会随着表单一起提交给服务器,这样服务端就知道应更新哪个客户信息。
需要强调的是,表单是通过post
方式提交的,因此调用的是servlet
的doPost
方法。