前端和后端的相对路径和绝对路径
1. 相对路径访问图片
-
test.html 位于
web/a/b/c/
目录中:- 若要访问
static/img/
文件夹中的图片(假设图片名为image.png
),相对路径应该是:
这里<img src="../../../static/img/image.png" alt="Image">
../../../
用于返回到web
目录,再进入static/img/
。
- 若要访问
-
view.html 位于
WEB-INF/views/
目录中:WEB-INF
下的文件不能被直接访问,但假设你使用了一些方式(如通过 Servlet 渲染)来显示它,可以通过以下相对路径引用图片:<img src="../../static/img/image.png" alt="Image">
../../
用来从WEB-INF/views/
跳出两层,回到web
,然后进入static/img/
。
-
index.html 或 indix.html 位于
web/
根目录:- 若要访问图片,可以使用相对路径:
<img src="static/img/image.png" alt="Image">
- 若要访问图片,可以使用相对路径:
2. 绝对路径访问图片
无论 HTML 文件在哪个目录,绝对路径始终从 Web 应用的根目录(即 web/
)开始。假设你的应用部署在服务器的根路径 /
,可以使用以下绝对路径:
<img src="/static/img/image.png" alt="Image">
这种方式确保无论 HTML 文件放置在项目的哪个位置,都能够从根目录开始正确访问 static/img/image.png
。
总结:
- 相对路径 是基于当前 HTML 文件的层次位置,决定路径中
../
的使用次数。 - 绝对路径 则更为稳定,直接从应用的根目录开始引用,使用
/static/img/image.png
。
绝对路径的缺点:
绝对路径要补充项目的上下文,而项目上下文是可以改变的
1. <base>
标签(不完美的解决办法)
-
<base>
标签允许你定义相对路径的公共前缀,一旦定义,所有相对路径(如图片、CSS、JS 等)都会基于这个前缀进行解析。 - 在你给出的例子中,
<base href="/web03_war_exploded/">
将/web03_war_exploded/
作为所有相对路径的基准前缀。
2. 适用场景
- 相对路径:
<base>
标签对相对路径有效,会将其转换为基于该前缀的绝对路径。例如,如果有一个相对路径static/img/logo.png
,那么完整路径将变为/web03_war_exploded/static/img/logo.png
。 - 绝对路径:
<base>
对绝对路径无效。如果你直接使用绝对路径,如/static/img/logo.png
,它会忽略<base>
定义的前缀。
3. 注意事项
<base>
标签必须放置在<head>
标签内,并且在同一 HTML 文档中只能定义一个<base>
标签。- 如果路径以
./
或../
开头,<base>
标签仍会生效,将相对路径基于指定的前缀。
更简便的方法:
所有的HTML访问img的代码如下:
后端
1. Servlet 重定向 (sendRedirect
)
通过 ServletA 来访问 test.html 文件的流程
1. 相对路径的使用
- 在
ServletA
中,通过resp.sendRedirect("../../../a/b/c/test.html");
实现重定向。这个路径是相对于当前ServletA
所在的路径 (/web03_war_exploded/x/y/z/servletA
)。../../../
表示向上跳三层目录,正好跳到根路径/web03_war_exploded/
,然后进入a/b/c/test.html
,最终构成的完整 URL 是:http://localhost:8080/web03_war_exploded/a/b/c/test.html
2. 绝对路径的使用
-
你可以直接使用绝对路径进行重定向,如:
resp.sendRedirect("/web03_war_exploded/a/b/c/test.html");
这种方式避免了相对路径中的复杂跳转,直接从服务器根路径开始访问文件。
- 绝对路径中需要填写项目上下文路径,但是上下文路径是变换的所以需要用到getContextPath();
-
通过获取项目上下文路径: 如果项目上下文路径是动态的(如部署在不同的服务器或子路径下),推荐通过
ServletContext
获取上下文路径,确保路径的动态适应性:resp.sendRedirect(request.getContextPath() + "/a/b/c/test.html");
这里的
request.getContextPath()
会动态返回当前项目的上下文路径,避免硬编码路径不一致的问题。//绝对路径中,要写项目上下文路径 //resp.sendRedirect("/web03_war_exploded/a/b/c/test.html"); // 通过ServletContext对象动态获取项目上下文路径 //resp.sendRedirect(getServletContext().getContextPath()+"/a/b/c/test.html"); // 缺省项目上下文路径时,直接以/开头即可 resp.sendRedirect("/a/b/c/test.html");
总结:
-
相对路径:相对路径的好处是与当前资源位置相关,但可能会因为层级跳转复杂而不易维护,特别是当文件目录结构较深时,容易出错。
-
绝对路径:绝对路径较为清晰,但需要指定项目的上下文路径,若项目迁移或部署在不同上下文路径下(如
/web03_war_exploded/
变为/app/
),可能需要修改路径。通过getContextPath()
动态获取上下文路径能有效避免这个问题。
2. 请求转发 (RequestDispatcher
)
1. 相对路径写法
- 当前的请求是通过 ServletB 访问的,其 URL 为:
http://localhost:8080/web03_war_exploded/x/y/z/servletB
- ServletB 转发到目标页面
test.html
的相对路径为:RequestDispatcher requestDispatcher = req.getRequestDispatcher("../../../a/b/c/test.html"); requestDispatcher.forward(req, resp);
@WebServlet("/x/y/z/servletA")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws
ServletException, IOException {
// 相对路径重定向到test.html
resp.sendRedirect("../../../a/b/c/test.html");
}
}
- 解释相对路径:
../../../
表示向上跳出三个层级,从/x/y/z/
跳回到根路径/web03_war_exploded/
,然后再进入a/b/c/test.html
。- 最终路径为:
http://localhost:8080/web03_war_exploded/a/b/c/test.html
2. 绝对路径写法
- 另一种方式是使用绝对路径,不需要依赖项目上下文路径而重定向的绝对路径需要依赖项目上下文路径:
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/a/b/c/test.html"); requestDispatcher.forward(req, resp);
- 这里的
/a/b/c/test.html
是绝对路径,直接从服务器的根路径开始解析,无需处理层级跳转的问题。这种写法避免了相对路径复杂的目录跳转问题。
@WebServlet("/x/y/servletB")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
RequestDispatcher requestDispatcher =
req.getRequestDispatcher("../../a/b/c/test.html");
requestDispatcher.forward(req,resp);
}
}
3. 总结
- 相对路径:适用于基于当前资源位置进行跳转,需要根据当前请求的位置进行目录层级的跳转。
- 绝对路径:从项目的根路径开始定义目标资源路径,推荐使用绝对路径来减少复杂性,特别是当资源路径固定时。
- 请求转发:不同于重定向,请求转发 不会更改客户端的 URL 地址,操作完全在服务器端进行,浏览器不会察觉 URL 变化。
- 另一种方式是使用绝对路径,不需要依赖项目上下文路径:
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/a/b/c/test.html"); requestDispatcher.forward(req, resp);
- 这里的
/a/b/c/test.html
是绝对路径,直接从服务器的根路径开始解析,无需处理层级跳转的问题。这种写法避免了相对路径复杂的目录跳转问题。
目标资源内相对路径处理
- 此时需要注意,请求转发是服务器行为,浏览器不知道,地址栏不变化,相当于我们访问test.html 的路径为http://localhost:8080/web03_war_exploded/x/y/servletB;
- 那么此时 test.html资源的所在路径就是http://localhost:8080/web03_war_exploded/x/y/所以 test.html中相对路径要基于该路径编写,如果使用绝对路径则不用考虑;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
当前资源路径是 http://localhost:8080/web03_war_exploded/x/y/servletB
当前资源所在路径是 http://localhost:8080/web03_war_exploded/x/y/
目标资源路径=所在资源路径+src属性值
http://localhost:8080/web03_war_exploded/x/y/../../static/img/logo.png
http://localhost:8080/web03_war_exploded/static/img/logo.png
得到目标路径正是目标资源的访问路径
-->
<img src="../../static/img/logo.png">
</body>
</html>