_160_Java_JavaWeb开发中访问的地址是否有斜杠“/”(绝对路径和相对路径)的区别

转自https://blog.csdn.net/freelk/article/details/79280021,感谢作者的无私分享。

刚开始做开发的时候,对于要路径前是否加斜杠“/”一直比较疑惑,即绝对路径和相对路径问题。最近写了一个demo用来测试这个问题,对这个问题做了一个总结。

这里先贴上项目的结构,方便能看到各资源的实际位置。

下面是web.xml的配置,主要是各个servlet的资源路径

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns="http://java.sun.com/xml/ns/javaee" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                      http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
                      id="WebApp_ID" version="2.5">
  <display-name>pathDemoApp</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <servlet>
    <servlet-name>Demo1</servlet-name>
    <servlet-class>com.lk.demo.Demo1</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Demo1</servlet-name>
    <url-pattern>/demo1</url-pattern>
  </servlet-mapping>
  
  <servlet>
    <servlet-name>Demo2</servlet-name>
    <servlet-class>com.lk.demo.Demo2</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Demo2</servlet-name>
    <url-pattern>/demo2</url-pattern>
  </servlet-mapping>
  
  <servlet>
    <servlet-name>Demo3</servlet-name>
    <servlet-class>com.lk.demo.Demo3</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Demo3</servlet-name>
    <url-pattern>/test/demo3</url-pattern>
  </servlet-mapping>
  
  <servlet>
    <servlet-name>Demo4</servlet-name>
    <servlet-class>com.lk.demo.Demo4</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Demo4</servlet-name>
    <url-pattern>/demo4</url-pattern>
  </servlet-mapping>
  
  <servlet>
    <servlet-name>Demo5</servlet-name>
    <servlet-class>com.lk.demo.Demo5</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Demo5</servlet-name>
    <url-pattern>/test/demo5</url-pattern>
  </servlet-mapping>
  
  <servlet>
    <servlet-name>Demo6</servlet-name>
    <servlet-class>com.lk.demo.Demo6</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Demo6</servlet-name>
    <url-pattern>/test/demo6</url-pattern>
  </servlet-mapping>
</web-app>

需要强调,路径的问题要区别开是“服务器(或者说servlet处理的路径)”还是“客户端(即浏览器要发送的请求)”。

1、先说“客户端”:

1.1 HTML页面的请求。

下面的代码是在HTML页面中,浏览器请求图片资源的情况。

test1.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
  
  <img src="/pathDemoApp/iamge/pic.jpg">
  <br/>
  <img src="/iamge/pic.jpg">
  <br/>
  <img src="iamge/pic.jpg">
  
  <!-- 
    当前HTML页面的访问路径为:
    http://localhost:8080/pathDemoApp/html/test1.html
    
    总结:
    1.在HTML页面中的请求路径,斜杠“/”代表服务器站点的根路径,这里是 http://localhost:8080/,
    然后加上图片的URI地址,因此第一个的实际请求路径为:
    http://localhost:8080/pathDemoApp/iamge/pic.jpg
    第二个img标签的实际请求路径为:
    http://localhost:8080/iamge/pic.jpg
    因此第一个图片可以正常显示,第二个路径是错误的(404)。
    
    2.如果路径前不加“/”,则浏览器会将URI的最后一个斜杠后的资源名称替换为请求的路径,
    例如第三个img标签的src的实际请求路径为:
    http://localhost:8080/pathDemoApp/html/iamge/pic.jpg
    这个图片都不能正确显示(404)。
   -->
  
</body>
</html>

结果如下图所示,只有第一个图片请求成功。

1.2 Response的重定向。

response.sendRedirect(path);

虽然response重定向资源是在servlet代码中实现的,但是,是将要重定向的路径返回给浏览器,让浏览器重新请求,因此,其规律和HTML页面请求资源是一样的,所以这里将重定向归为客户端请求这一类。

代码如下:

Demo3.java
 

package com.lk.demo;
 
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * 该类用于测试Response的重定向
 * 将该类的访问路径特别设置为/test/demo3
 */
public class Demo3 extends HttpServlet {
 
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("我是Demo3");
    
    /*
     * 总结:
     * response的重定向方法,是将路径返回给浏览器,让浏览器重新请求,因此可以发现,
     * 重定向的规律和浏览器在页面中发送请求的规律是一样的。
     * “/”表示服务器站点的根路径,这里是 http://localhost:8080/,
     * 如果参数路径前不加“/”,则浏览器会将URI的最后一个斜杠后的资源名称替换为参数请求的路径。
     */
    response.sendRedirect("/pathDemoApp/demo4");//正确
//    response.sendRedirect("pathDemoApp/demo4");//路径为http://localhost:8080/pathDemoApp/test/pathDemoApp/demo4
//    response.sendRedirect("/demo4");//错误路径为http://localhost:8080/demo4
//    response.sendRedirect("demo4");//错误路径为http://localhost:8080/pathDemoApp/test/demo4
  }
 
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
  }
 
}

HTML中,“/”表示的是服务器站点的根路径,案例中为http://localhost:8080/;

如果不加“/”,则是在当前页面的路径基础上,将请求的URI替换掉最后一个“/”后的资源名称。

2、服务器

2.1 ServletContext.getRealPath()方法获取资源的路径。

ServletContext的getRealPath方法可以获取项目下任何位置资源的路径。

Demo2.java
 

package com.lk.demo;
 
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * 用于测试ServletContext的getRealPath方法的结果
 *
 */
public class Demo2 extends HttpServlet {
  
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    /*
     * ServletContext的getRealPath方法可以获取项目下任何资源的路径
     * 总结:
     * 该方法都是从项目根路径(即站点+项目名称)下查找参数传递的资源路径,不论参数前是否有斜杠。
     * 然后将参数代表的资源路径拼接到项目根路径之后。
     */
    String path1 = getServletContext().getRealPath("pathDemoApp/iamge/pic.jpg");
    System.out.println(path1);
    //  D:\WorkProgramFiles\apache-tomcat-7.0.35\webapps\pathDemoApp\pathDemoApp\iamge\pic.jpg
    String path2 = getServletContext().getRealPath("/iamge/pic.jpg");
    System.out.println(path2);
    //  D:\WorkProgramFiles\apache-tomcat-7.0.35\webapps\pathDemoApp\iamge\pic.jpg
    String path3 = getServletContext().getRealPath("iamge/pic.jpg");
    System.out.println(path3);
    //  D:\WorkProgramFiles\apache-tomcat-7.0.35\webapps\pathDemoApp\iamge\pic.jpg
    String path4 = getServletContext().getRealPath("/pic.jpg");
    System.out.println(path4);
    //  D:\WorkProgramFiles\apache-tomcat-7.0.35\webapps\pathDemoApp\pic.jpg
    String path5 = getServletContext().getRealPath("/");
    System.out.println(path5);
    //  D:\WorkProgramFiles\apache-tomcat-7.0.35\webapps\pathDemoApp\
    String path6 = getServletContext().getRealPath("");
    System.out.println(path6);
    //  D:\WorkProgramFiles\apache-tomcat-7.0.35\webapps\pathDemoApp
  }
 
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
  }
 
}

该方法都是从项目根路径(即站点+项目名称)下查找参数传递的资源路径,不论参数前是否有斜杠“/”, 然后将参数代表的资源路径拼接到项目根路径之后。

2.2 Request的转发请求。

request.getRequestDispatcher(path).forward(request, response);

Demo5.java

package com.lk.demo;
 
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * 用于测试Request的转发
 * 将该类的访问路径特别设置为/test/demo5
 */
public class Demo5 extends HttpServlet {
 
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    /*
     * 总结:
     * 经过测试,可以发现
     * “/”表示项目的根路径,这里是 http://localhost:8080/pathDemoApp/,
     * 如果参数路径前不加“/”,则会将当前资源的请求路径中,最后一个斜杠后的资源名称替换为参数请求的路径。
     */
    
    System.out.println("我是Demo5");
    
//    String path = "/pathDemoApp/test/demo6";//错误404:/pathDemoApp/pathDemoApp/test/demo6
//    String path = "pathDemoApp/test/demo6";//错误404:/pathDemoApp/test/pathDemoApp/test/demo6
    String path = "/test/demo6";//正确
//    String path = "test/demo6";//错误404:/pathDemoApp/test/test/demo6
    
    request.getRequestDispatcher(path).forward(request, response);
 
    System.out.println("又回到了Demo5");
    
  }
 
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
  }
 
}

该方法中,“/”表示项目的根路径,这里是 http://localhost:8080/pathDemoApp/;

 如果参数路径前不加“/”,则会将当前资源的请求路径中,最后一个斜杠后的资源名称替换为参数请求的路径,不加“/”类似于重定向的请求。

总结:

上述的例子是我现在能想到的一些情况。

对于浏览器端,“/”表示的是服务器根站点,即http://localhost:8080/ 。

对于服务器端,“/”表示的是项目的根路径,即http://localhost:8080/pathDemoApp/ 。

总的来说,可以发现,在使用资源路径时,最好使用当前项目的根据路,这样不会出现什么大问题。

对于浏览器请求,比如在jsp的渲染引擎中,我们可以使用request.getContextPath的方法获取当前项目的项目名称,在后面拼接具体资源的路径,以避免在代码中将项目名称写为固定值。

猜你喜欢

转载自blog.csdn.net/poiuyppp/article/details/87725107
今日推荐