我正在使用 Java Servlet 和 JSP 开发一个网页。我具有根据接收到的操作(动作)执行不同操作的功能。但是,我遇到了特定操作 (action4) 的问题,该操作应生成 PDF,然后将用户重定向到另一个页面。
问题:
我感谢您提供的任何帮助或建议。预先感谢!
以下是我的结构和我面临的问题。
Servlet:
if (action != null) {
switch (action) {
case "action1": // Add items to cart
if (carritoSQL.existeProducto(producto)) {
handleAddButton(request, response, producto, cantidad, carrito);
}
break;
case "action2": // Development-focused case
handleClearButton(request, response, session);
break;
case "action3": // Cancel purchase
handleClearButton(request, response, session);
redirect = "views/home.jsp";
break;
case "action4": // Complete purchase
handleCompletePurchaseButton(request, response, fecha, vendedor, distribuidor, carrito);
handleClearButton(request, response, session);
request.getRequestDispatcher("views/home.jsp").forward(request, response);
//redirect = "views/home.jsp";
break;
default:
// Default logic if necessary
defaultHandler(request, response);
redirect = "views/home.jsp";
break;
}
} else {
// Handle the case where no 'action' value is received
defaultHandler(request, response);
}
response.sendRedirect(redirect);
private void handleCompletePurchaseButton(HttpServletRequest request, HttpServletResponse response, String fecha, String vendedor, String distribuidor, ShoppingCart carrito) throws ServletException, IOException {
GeneralReceipt receipt = createReceipt(fecha, vendedor, distribuidor, carrito);
detailReceipt(receipt.getId(), fecha, vendedor, distribuidor, carrito);
String ticket = generateTicketString(vendedor, distribuidor, carrito, receipt);
generatePDF(response, ticket, distribuidor, fecha);
}
问题: action4 时会出现此问题。该操作正确生成 PDF,然后由用户下载,但不会重定向到该页面。我尝试了以下解决方案:
两种解决方案都会导致控制台出现以下错误:
28-Jun-2024 10:50:29.355 SEVERE [68] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [operacionesRemisionNH1] threw exception
java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed
at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:486)
at Servlets.operacionesRemisionNH1.generatePDF(operacionesRemisionNH1.java:354)
at Servlets.operacionesRemisionNH1.handleCompletePurchaseButton(operacionesRemisionNH1.java:153)
at Servlets.operacionesRemisionNH1.doPost(operacionesRemisionNH1.java:114)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:232)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:167)
我调用action4的JSP:
<div class="modal fade" id="FinalizarCompraModal" tabindex="-1" aria-labelledby="FinalizarCompraModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="FinalizarCompraModalLabel">Purchase Confirmation</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
You are about to complete your purchase. Please review your order details. If everything is correct, click 'Confirm' to complete the purchase. If you need to make any changes, click 'Cancel'.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" name="action" value="action4" class="btn btn-primary">Confirm</button>
</div>
</div>
</div>
</div>
事实上,您无法针对单个请求发回多个响应。您基本上需要随后触发第二个请求。
最好的办法是在代表文件下载的响应中添加一个特定的 cookie,并在 JavaScript 中轮询它,然后在找到 cookie 时在 JavaScript 中执行重定向。
基本上,在 Servlet 中:
response.setHeader("Content-Disposition", ...);
response.addCookie(new Cookie("download.completed", "true"));
// now write to response.getOutputStream()
在 JSP 中,为下载按钮提供一个 ID,以便我们可以在 JS 中引用它:
<button type="submit" id="yourDownloadButton" ...>
并在 DOM 内容准备就绪时运行此 JS,以便在单击下载按钮时启动 cookie 轮询器。当找到 cookie 时,此示例将显示一条警报(当然,出于演示目的,您可以安全地删除它),然后重定向到您当前的问题:
document.getElementById("yourDownloadButton").addEventListener("click", () => {
document.cookie = "download.completed=false";
const downloadCompleteChecker = setInterval(() => {
if (document.cookie.includes("download.completed=true")) {
clearInterval(downloadCompleteChecker);
alert("Download completed!");
window.location = "https://stackoverflow.com/q/78683578";
}
}, 500);
});