【发布时间】:2019-05-09 09:16:38
【问题描述】:
我正在使用 JSP 和 Servlet、TomCat 9 和 IntelliJ 创建一个 Java Web 应用程序。我正在关注的教程使用 Eclipse,讲师只是将项目运行为 Run As > Run On Server,一切都可以无缝运行。
在 IntelliJ 中,事情似乎一团糟。
这是我的项目结构-
这是运行配置 -
我将web.xml 设置为 -
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Archetype Created Web Application</display-name>
<welcome-file-list>
<welcome-file>login.do</welcome-file>
</welcome-file-list>
</web-app>
因此,任何对localhost:8080 的请求,或者在IntelliJ 的情况下,http://localhost:8080/jspservlet_war_exploded/ 都应该重定向到login.do,由LoginServlet 处理-
package app;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(urlPatterns = "/login.do")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String pass = req.getParameter("password");
req.setAttribute("name", name);
req.setAttribute("password", pass);
RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/login.jsp");
requestDispatcher.forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
req.setAttribute("name", name);
RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/welcome.jsp");
requestDispatcher.forward(req, resp);
}
}
起初,我在LoginServlet 中测试doGet() 方法,只需在起始页-http://localhost:8080/jspservlet_war_exploded/ 中手动添加?name=xxx&password=xxx 查询字符串。这些属性在request 中设置,然后转发到login.jsp,它只会使用${name} 和${password} 显示属性值。在这一步之前一切正常。
然后,我将login.jsp 页面更改为包含一个简单的form,它有一个用于输入用户名的输入字段,并通过action 属性将其发送到/login.do,使用POST 方法。这就是事情爆发的地方。
这里是login.jsp -
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Login Page</title>
</head>
<body>
<h1>Welcome</h1>
<p>Time on server is <%= new Date()%></p>
<%--<p>Your name is ${name} and password is ${password}</p>--%>
<p>pageContext.request.contextPath: ${pageContext.request.contextPath}</p>
<form action="/login.do" method="post">
<label for="inp">Enter your name </label>
<input id="inp" type="text" name="name"/>
<button>Submit</button>
</form>
</body>
</html>
这导致了这个页面 -
现在,只要我点击“提交”,请求似乎就会转到 localhost:8080/login.do(因为这是 action 属性的值),这会引发错误 -
根据我在此处阅读的其他问题,看起来会发生这种情况是因为上下文路径(即应用程序的根)是http://localhost:8080/jspservlet_war_exploded/,并且所有位置都与此路径相关(?)。所以,推荐的方式似乎是${pageContext.request.contextPath}。
基于此,如果我将action 属性更改为action="${pageContext.request.contextPath}/login.do",那么一切都会恢复正常。
但是,现在我正在尝试从LoginServlet 中的doPost() 方法重定向到TodoServlet,就像这样-
resp.sendRedirect("/todo.do");
这再次导致 404,因为 URL 变为 http://localhost:8080/todo.do,而它应该是 http://localhost:8080/jspservlet_war_exploded/todo.do。
如何解决问题,以便默认情况下所有资源都相对于http://localhost:8080/jspservlet_war_exploded/ 进行部署,并且我可以直接在action 或resp.sendRedirect() 中指定URL 模式?
【问题讨论】: