文章目录
11.1 工程路径问题
- 先看一个问题 web/index.html
- 创建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>base 标签</title>
</head>
<body>
<h1>注册用户~~</h1>
<!--
解读:
1. 可以看到,我们原来的访问一个web资源的路径非常的麻烦
2. 目前我们访问的是 ok的资源
3. 我们可以使用相对路径来解决
4. http://localhost:8080/webpath/ok => ok
5. 如果你action="ok" 等价 http://localhost:8080/webpath/ok
-->
<form action="ok"
method="post">
u: <input type="text" name="username"/><br><br>
<input type="submit" value="注册用户"/>
</form>
<h1>讨论区~</h1>
<form action="ok"
method="post">
讨论内容: <textarea cols="50" rows="5"></textarea><br><br>
<input type="submit" value="发布讨论"/>
</form>
<h1>回复区~</h1>
<form action="ok"
method="post">
回复内容: <textarea cols="50" rows="5"></textarea><br><br>
<input type="submit" value="回复"/>
</form>
</body>
</html>
- 问题分析
11.2 工程路径解决方案
11.2.1 解决方案:相对路径
- 说明: 使用相对路径来解决, 一个非常重要的规则:页面所有的相对路径,在默认情况下,都会参考当前浏览器地址栏的路径 http://ip:port/工程名/ + 资源来进行跳转。所以我们可以直接这样写
- 相对路径带来的问题举例 => 示意图
- 如果需要指定页面相对路径参考的的路径,可以使用 base 标签来指定
11.2.2 解决方案:base 标签
11.2.2.1 base 基本介绍
- base 标签是 HTML 语言中的基准网址标记,它是一个单标签,位于网页头部文件的 head标签内
- 一个页面最多只能使用一个 base 元素,用来提供一个指定的默认目标,是一种表达路径和连接网址的标记
- 常见的 url 路径形式分别有相对路径与绝对路径,如果 base 标签指定了目标,浏览器将通过这个目标来解析当前文档中的所有相对路径,包括的标签有 (a、img、link、form)
- 也就是说,浏览器解析时会在路径前加上 base 给的目标,而页面中的相对路径也都转换成了绝对路径。使用了 base 标签就应带上 href 属性和 target 属性
11.2.2.2 base 应用实例
- 需求: 演示 base 标签的使用,说明: 先演示和 html 相关的路径跳转,再演示和 Servlet 路径转发,一步步来
- 创建 web\a.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>a.html</title>
</head>
<body>
<h1>这是a.html~~~~~</h1>
<!-- 相对路径
1. href="d1/d2/b.html" 等价于 http://localhost:8080/项目名/d1/d2/b.html
-->
<a href="d1/d2/b.html">跳转到/d1/d2/b.html</a>
<br/><br/>
<!--
解析:
3. 在实际开发中,往往不是直接访问一个资源的而是在服务端进行转发或者重定向来访问资源
4. 演示转发定位 b.html
5. href="servlet03" http://localhost:8080/webpath/servlet03
-->
<a href="servlet03">转发到/d1/d2/b.html</a>
</body>
</html>
- 创建 web\d1\d2\b.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>b.html</title>
<!--
解读
1. 如果没有<base href="http://localhost:10000/hspedu_servlet/">
2. 当点击 返回a.html 超链接,将会以当前浏览器的地址为路径来确定 路径
3. 如果增加了<base href="http://localhost:10000/hspedu_servlet/">
4. 将以 base 指定的href的地址为路径,来确定 超链接的路径
-->
<!--<base href="http://localhost:10000/hspedu_servlet/">-->
<!--简写形式-->
<!--使用base 标签搞定
解读
1. 下面的 base href="http://localhost:8080/webpath/"
2. 表示的含义就是当前这个页面的访问所有资源都是以 http://localhost:8080/webpath/ 参照
-->
<!--<base href="http://localhost:8080/webpath/">-->
<!--上面的写法可以简化一把-->
<!--
解读
1. base 标签是哪个在解析? => 浏览器
2. 浏览器在解析 第一个 /时候,会解析成 http://localhost:8080/
3. 浏览器 href="/webpath/" =解析=> href="http://localhost:8080/webpath/"
4. 浏览器 <a href="a.html">返回a.html~</a> , 参考 base => 最后
href="http://localhost:8080/webpath/a.html"
-->
<base href="/webpath/">
</head>
<body>
<h1>这是/d1/d2/b.html</h1>
<!--
解读
1. 返回a.html => 使用前面的相对路径http://localhost:8080/webpath/d1/d2/
2. ../../a.html => http://localhost:8080/webpath/a.html
3. 相对路径会让这个项目相互调用的关系变得复杂
4. 使用base 标签搞定
-->
<!--<a href="../../a.html">返回a.html~</a>-->
<a href="a.html">返回a.html~</a>
</body>
</html>
- 创建 Servlet03.java , 来测试和 Servlet 的转发相关的路径知识点
package com.xjs.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author: 谢家升
* @Date: 2022/3/5-03-05-14:51
* @Version: 1.0
*/
public class Servlet03 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//这里我们希望通过转发来定位 b.html
//解读:
//1.在服务器端 解析第一个 / 时,会被解析成 http://ip:port/项目名/ 然后再拼接后面的部分
// 特别提示:上面的 项目名 ==> application context 【按照tomcat配置的】
//2. /d1/d2/b.html => 被解析成 http://ip:port/项目名/d1/d2/b.html
System.out.println("Servlet03进行转发~~");
//request.getRequestDispatcher("/d1/d2/b.html").forward(request, response);
//3. 在服务器进行转发时,没有 / 就按照默认的方式参考定位 http://ip:port/项目名/
// 建议仍然使用上面的写法 /d1/d2/b.html
request.getRequestDispatcher("d1/d2/b.html").forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
- 完成测试,重点是理解base 标签的作用
11.2.3 作业布置
【login.html】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<h1>用户登录</h1>
<!--
请写出 login.html 在不通过Servlet转发情况下, 如何 通过表单提交, 找到 user.html, 把所有的写法列出来
1. 完整的url http://localhost:8080/webpath/views/user/user.html
2. 使用相对路径 action="views/user/user.html" => 使用当前浏览器的 地址栏 ip:port/工程路径/ + ...
3. action="/webpath/views/user/user.html"
浏览器对第一个 / 进行解析 为 http://localhost:8080/ + webpath/views/user/user.html
同样是一个完整url
4. 这里提一句: 我们使用服务器渲染技术,可以动态得到 /工程路径 , 后面再说
-->
<!--<form action="/webpath/hi" method="post">-->
<form action="/webpath/redirect" method="post">
u: <input type="text" name="username"><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
【user.html】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户页面</title>
<!--
1. 使用相对路径: <a href="../../login.html">点击返回登录</a>
2. 使用相对路径是比较麻烦,即使成功,还需要考虑是直接定位到这个资源还是请求转发到这个资源
3. 使用base 标签给一个固定的相对路径
4. <base href="/webpath/"> 该标签是浏览器解析 http://localhost:8080/webpath/
5. 在 base 得到的url 路径基础上 <a href="login.html">点击返回登录</a> =>
http://localhost:8080/webpath/login.html
6. 一定要自己 玩一把
-->
<base href="/webpath/">
</head>
<body>
<h1>用户页面</h1>
<a href="login.html">点击返回登录</a>
</body>
</html>
public class HiServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//这里请求转发到 /views/user/user.html
//System.out.println("HiServlet 被调用....");
//使用转发
//注意 第一个 / 被服务器解析成 /webpath/
// 因为请求转发是发生服务器端,所以通过 /webpath/views/user/user.html
// 可以定位该资源
request.getRequestDispatcher("/views/user/user.html")
.forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
11.3 WEB 工程路径注意事项和细节
11.3.1 注意事项和细节说明
-
Web 工程的相对路径和绝对路径
相对路径是:
①
.
表示当前目录
②..
表示上一级目录
③ 资源名 表示:当前目录/资源名绝对路径是: http://ip:port/工程路径/资源路径
-
在实际开发中,路径都使用绝对路径,而不是相对路径
-
在 web 中 / 斜杠 如果被浏览器解析,得到的地址是:http://ip[域名]:port/ 比如:
<a href="/">斜杠</a>
-
在 web 中 / 斜杠 如果被服务器解析,得到的地址是:http://ip[域名]:port/工程路径/,你也可以理解成 /工程路径/ 下面的几种情况就是如此:
<url-pattern>/servelturl</url-pattern>
servletContext.getRealPath("/"); //==> 是得到执行路径/工作路径
request.getRequestDispatcher("/");
- 在 javaWeb 中 路径最后带 / 和 不带 / 含义不同,一定要小心,比如
<a href="/a/servlet03">
表示网址,而</a> : servlet03
表示资源 - 特别说明:重定向
response.sendRediect("/");
这条语句虽然是在服务器执行的,但是,服务器是把斜杠 / 发送给浏览器解析。因此得到地址 http://ip[域名]:port/
小结: 在编写资源路径时,考虑这么几点:
- 这个路径 前面有没有 /
- 这个路径 在哪里被解析 [服务器还是浏览器] ,如果前面有 / ,并且是在 浏览器被解析的 被解析成
http://ip:port/
,如果在服务器端被解析,被解析成/工程路径/
- 如果这个路径,前面没有 / ,并且在浏览器被解析,则以浏览器当前的地址栏 去掉资源部分,作为一个相对路径
- 这个路径,最后有没有 / ,如果最后有/ 表示路径, 如果没有 / 表示资源
11.3.2 作业布置
public class RedirectServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("RedirectServlet 重定向4 被调用....");
//这里如何通过重定向来定位 /views/user/user.html
//1. 分析出 重定向是发生在 浏览器
//2. 写法1: response.sendRedirect("http://localhost:8080/webpath/views/user/user.html");
//3. 写法2: response.sendRedirect("/webpath/views/user/user.html");
//4. 写法3: response.sendRedirect("views/user/user.html");
//5. 写法4: response.sendRedirect(contextPath + "/views/user/user.html");
//6. 推荐写法是 第4个写法,比较灵活,而且定位资源是稳定的.
String contextPath = getServletContext().getContextPath();//contextPath=/webpath
response.sendRedirect(contextPath + "/views/user/user.html");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
11.4 优化 WEB 工程路径
- 前面的 base 案例中,我们可以对路径进行优化
- 代码演示 web\d1\d2\b.html
- 这里, 简单演示一下,后面我们还要说
- => 使用 jsp / thymeleaf 加入标签,动态获取即可
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/5
Time: 13:37
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
$END$ 动态的获取到工程路径: <%=request.getContextPath()%>
</body>
</html>