将 servlet 用作控制器。这意味着,用户永远不会看到 .jsp 扩展名或 JSP 的任何其他映射 url。用户总是被发送到 servlet 的 URL。然后 servlet 根据需要转发到 JSP。实际上,您可能希望将您的 jsp 放在 WEB-INF 中,以使用户无法通过控制器(即 servlet)以外的任何其他方式到达那里。
这里的转发是在其正确的技术意义上使用的,这意味着它将执行传递给 JSP在后台,但 servlet 的 URL 保留在地址栏中(这与重定向非常不同)。这确保了如果用户点击刷新,servlet 仍然控制着执行流程。
好的。现在你的逻辑:
如果请求是 POST 并且验证成功,则 servlet 会处理它。
如果验证失败或请求为 GET,则 servlet 转发到 JSP。
您将不得不摆脱 jsp:useBean,因为它与 servlet 不兼容。见底部servlets info page。
至于代码重复,我猜你的意思是在servlet中调用request.getParameter(),然后将其移入request.setAttribute(),然后在转发之后读取JSP中的属性。好吧,如果您真的在使用 bean,您应该将所有参数放入 bean 并将 bean 设置为 request.setAttribute(),这样您就不会再从 JSP 中的同一个位置读取参数,因为您会寻找在bean不是请求参数....所以它不是代码重复。 (这也解释了您用什么替换过时的 jsp:useBean。)
因此,让我们从 servlet 的信息页面中获取这个示例。在 servlet 中:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Preprocess request: load list of products for display in JSP.
List<Product> products = productService.list();
request.setAttribute("products", products);
request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
}
在 JSP 中:
<c:forEach items="${products}" var="product">
<tr>
<td>${product.id}</td>
<td><c:out value="${product.name}" /></td>
<td><c:out value="${product.description}" /></td>
<td><fmt:formatNumber value="${product.price}" type="currency" /></td>
</tr>
</c:forEach>
看看 servlet 如何创建一个名为 products 的对象并将其放置在请求属性中?你会做同样的事情,但这里不是一个列表,而是你的 bean 的任何类型。在 JSP 中的 EL 中访问它时也是如此:您将以这种方式访问您的 bean:servlet 中的 request.setAttribute("myBean", beanObj); 和 JSP 中的 ${myBean.memberName}。