一、工程路径问题
1. 问题引出
问题:web/index.html
新建工程:new project->选Java->一直下一步到修改项目和路径即可,修改名字创建项目
add framework选WebApplication4.0,添加Servlet-api,部署Tomcat,不再赘述
添加index.html页面
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>base 标签</title>
</head>
<body>
<h1>注册用户~</h1>
<form action="http://localhost:8080/webpath/ok" method="post">
u: <input type="text" name="username"/><br><br>
<input type="submit" value="注册用户"/>
</form>
<h1>讨论区</h1>
<form action="http://localhost:8080/webpath/ok" method="post">
讨论内容: <textarea cols="50" rows="5"></textarea><br><br>
<input type="submit" value="发布讨论"/>
</form>
<h1>回复区</h1>
<form action="http://localhost:8080/webpath/ok" method="post">
回复内容: <textarea cols="50" rows="5"></textarea><br><br>
<input type="submit" value="回复"/>
</form>
</body>
</html>
可以看到以前路径写的是全路径,比较麻烦
我们可以采用相对路径
2. 相对路径
使用相对路径来解决,一个非常重要的规则:页面所有的相对路径,在默认情况下,都会参考当前浏览器地址栏的路径http://ip:port/工程名/ + 资源来进行跳转,我们可以直接这样
二、base标签
1. base标签介绍
如果需要指定页面相对路径参考的的路径,可以使用base标签来指定
base标签是HTML语言中的基准网址标记,它是一个单标签,位于网页头部文件的head标签内
一个页面最多只能使用一个base元素,用来提供一个指定的默认目标,是一种表达路径和连接网址的标记
常见的url路径形式分别有相对路径与绝对路径,如果base标签指定了目标,浏览器将通过这个目标来解析当前文档中的所有相对路径,包括的标签有(a、img、link、form)
也就是说,浏览器解析时会在路径前加上base给的目标,而页面中的相对路径也都转换成了绝对路径。使用了base标签就应带上href属性和target属性
2. 实例-静态页面跳转
需求:演示base标签的使用,说明:先演示和html相关的路径跳转,再演示和Servlet路径转发
在web目录下创建a.html文件
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>a.html</title>
</head>
<body>
<h1>这是 a.html</h1>
<a href="b1/b2/b.html">跳转到/b1/b2/b.html</a>
<br/><br/>
<a href="servlet03">转发到/b1/b2/b.html</a>
</body>
</html>
在web下创建b1目录,b1目录下创建b2目录,b2下创建b.html文件
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/">-->
<!--简写形式-->
</head>
<body>
<h1>这是/b1/b2/b.html</h1>
<a>返回 a.html~</a>
</body>
</html>
上面的b1/b2/b.html等价于http://localhost:8080/项目名/b1/b2/b.html
如果想再访问回a.html,第一种方式可以采用这样基础的base标签
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 href="http://localhost:8080/webpath/">
</head>
<body>
<h1>这是/b1/b2/b.html</h1>
<a href="a.html">返回 a.html~</a>
</body>
</html>
注意:上面http://localhost:8080/webpath/的"/"必须要带上,带上是个路径,不带上http://localhost:8080/webpath就表示一种资源
当然上面也可以表示为如下方式,下面两个等价:
html
<base href="http://localhost:8080/webpath/">
<base href="/webpath/">
因为base标签是浏览器在解析,浏览器在解析第一个"/"的时候,会将其解析成http://localhost:8080/
上面base标签已经将整个路径解析成路径了,如果<a href="/a.html">返回 a.html~</a>
再在a.html前加上/a.html,就会再次将第一个"/"解析成项目的路径http://localhost:8080/
3. 实例-Servlet跳转
正常情况下不是直接从静态页面跳转的,而是使用Servlet跳转
需求:这里使用Servlet实现跳转
上面a.html里有这个a标签,href就等于http://localhost:8080/项目名/servlet03
html
<a href="servlet03">转发到/b1/b2/b.html</a>
不能在前面带/,变成/servlet03,因为会变成http://localhost:8080/servlet03
java
@WebServlet(name = "Servlet03", urlPatterns = "/servlet03")
public class Servlet03 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//在服务器端解析第一个/时,会被解析成http://localhost:8080/项目名
//这里项目名是工程路径,因为转发是发生在服务端的,所以也可以理解"/"被解析成/项目
System.out.println("Servlet3 doPost转发");
request.getRequestDispatcher("/b1/b2/b.html").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
注意:在服务器端解析第一个/时,会被解析成http://localhost:8080/项目名 这里项目名是工程路径,因为转发是发生在服务端的,所以也可以理解"/"被解析成/项目
有的程序员会按照request.getRequestDispatcher("b1/b2/b.html").forward(request,response);
方式去请求,也就是b1/b2/b.html前面不带斜杠,这样有时也是可以的,但是不建议 ,如果服务器进行转发时,前面没找到/,就会按照默认的http://localhost:8080/项目名方式去访问
前面的项目名其实就是自己配置的application context
三、WEB工程路径注意事项和细节
1. Web工程的相对路径和绝对路径
相对路径是:
- .表示当前目录
- ..表示上一级目录
- 资源名 表示当前目录/资源名
- 绝对路径:http://ip:port/工程路径/资源路径
在实际开发中,路径都使用绝对路径,而不是相对路径
在Web中"/"斜杠如果被浏览器解析,得到的地址是:http://ip[域名]:port/,比如: 斜杠
在Web中"/"斜杠如果被服务器解析,得到的地址是:http://ip[域名]:port/工程路径/,你也可以理解成/工程路径/
下面的几种情况就是如此:
<url-pattern>/servelturl</url-pattern>
- servletContext.getRealPath("/"); ==> 是得到执行路径/工作路径,也就是out/artifacts/webpath/
- servletContext.getContextPath();==>是相对路径,配置的application context,可以用在服务器渲染技术
- request.getRequestDispatcher("/");
在JavaWeb中路径最后带/和不带/含义不同,一定要小心,比如网址</a>: servlet03
表示资源
特别说明:重定向response.sendRediect("/");这条语句虽然是在服务器执行的,但是,服务器是把斜杠 / 发送给浏览器解析。因此得到地址:http://ip[域名]:port/
在编写资源路径时,考虑这么几点:
-
这个路径前面有没有"/"
-
这个路径在哪里被解析[服务器还是浏览器],如果前面有/,并且是在浏览器被解析的,被解析成http://ip:port/,如果在服务器端被解析,被解析成
/工程路径/
-
如果这个路径,前面没有/,并且在浏览器被解析,则以浏览器当前的地址栏去掉资源部分,作为一个相对路径,这个路径,最后有没有/,如果最后有/表示路径,如果没有/表示资源
2. Web工程路径优化
前面的base标签是可以被优化的,可以使用动态技术,如jsp、theamleaf,这里使用jsp:
java
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
动态获取到工程路径:<%=request.getContextPath()%>
</body>
</html>
结果如下: