一、关于 jsp 中的超链接路径问题

我们假设你的项目路径也就是 web应用程序的根目录为 /webapp

<a href="/webapp/login.jsp"></a>
<a href="login.jsp"></a>

上面两种写法是相同的,都是指向 webapp 应用程序下的 login.jsp 页面。

  • 如果以"/"开头,代表相对于web服务器的根目录
  • 如果不以"/"开头,代表相对于webapp 应用程序的根目录

我们知道,web服务器可以包含多个 web应用程序,而/代表服务器的根目录,也就是Tomcat 的根目录,加上webapp就是告诉它我要访问的是哪一个应用程序,如果不加就默认是当前的应用程序。

二、关于 jsp 中请求路径的问题

一般我们会在 jsp 页面中放一个 form 表单,这样当我们启动项目的时候请求可以直接跳转到指定的请求路径上面去,这里的规则和超链接一样,只不过要重点注意 Servlet 的路径

例如:

如果你的 jsp 页面直接在项目的根目录下的话,表单跳转如下:

<form action="customer.do" method="post">
    <table border="1">
        <tr>
            <td>客户姓名</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>邮箱地址</td>
            <td><input type="text" name="email"></td>
        </tr>
        <tr>
            <td>联系电话</td>
            <td><input type="text" name="phone"></td>
        </tr>
        <tr>
            <td><input type="submit" value="提交"></td>
            <td><input type="reset" value="重置"></td>
        </tr>
    </table>
</form>

对用的 Servlet 接口:

@WebServlet(urlPatterns = "/customer.do")
public class Servlet01 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = request.getParameter("name");
        String email = request.getParameter("email");
        String phone = request.getParameter("phone");
        Customer customer = new Customer(name, email, phone);
        HttpSession session = request.getSession();
        synchronized (session) {
            session.setAttribute("customer", customer);
        }
        request.getRequestDispatcher("/demo/displayCustomer.jsp").forward(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

但是如果你的项目结构是这样的:

也就是说 jsp 文件在项目的根目录下的一个包下。

<form action="customer.do" method="post">
    <table border="1">
        <tr>
            <td>客户姓名</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>邮箱地址</td>
            <td><input type="text" name="email"></td>
        </tr>
        <tr>
            <td>联系电话</td>
            <td><input type="text" name="phone"></td>
        </tr>
        <tr>
            <td><input type="submit" value="提交"></td>
            <td><input type="reset" value="重置"></td>
        </tr>
    </table>
</form>

对应的 Servlet 接口:

@WebServlet(urlPatterns = "/demo/customer.do")
public class Servlet01 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = request.getParameter("name");
        String email = request.getParameter("email");
        String phone = request.getParameter("phone");
        Customer customer = new Customer(name, email, phone);
        HttpSession session = request.getSession();
        synchronized (session) {
            session.setAttribute("customer", customer);
        }
        request.getRequestDispatcher("/demo/displayCustomer.jsp").forward(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

三、总结

需要填写路径的地方有四处:

  1. 链接地址: <a href=" "></a>
  2. 表单地址: <form action=" ">
  3. 重定向地址: response.sendRedirect(" ");
  4. 转发地址:request.getRequestDispatcher(" ");

相对路径:

  • 不以/开头

绝对路径:

  • /开头

两种都可以,相对路径是相对于当前项目所在的目录,如果是 Servlet 的话就是相对于 @WebServlet(urlPatterns = "/demo/customer")这里的地址。


随便拿一个 JSP 和 Servlet 举例子:

  • jsp 页面中的 form 表单的 action 指向直接写:servlet.do
  • Servlet 的 urlPatterns 的值必须是对应的 jsp 页面相对于应用根目录的绝对路径,也就是要加上 jsp 页面所在的包名,如:/demo/servlet.do
  • 注意这里不用管 Servlet 在那个包下,只需要弄清楚发请求的 jsp 在哪个包下。
  • 然后如果 Servlet 中有重定向或者转发都是根据请求发来的路径决定的,也就是相对于请求的路径(即 urlPatterns 中的发来的请求的 jsp 页面的路径),而不是相对于 Servlet 的存放路径。