在做web开发的时候就路径的问题一直苦恼今天上网查资料 发现了一篇非常好的资料,转载来研究!!
1.jsp页面中的路径
一般地我们将在<head></head>中的<base>标签中设置网页的基本路径。
所谓基本路径是指无论该jsp页面在网站何目录下,在该jsp中的请求元素都是依照这个基本路径进行资源定位的,这就解决了因该jsp所在目录的不同而对该请求元素的资源定位不同 eg:
现有目录结构如下
------webapp
---------------a目录
| a1.jsp
| a2.jsp
---------------b目录
| b.jsp
| b.png
---------------c目录
-------------------d目录
| d.jsp
| d.jpg
没有设置<base>的情况
-
a1.jsp中访问a2.jsp
-> a1中请求元素<a href="a2.jsp">a2.jsp</a> -
a1.jsp中访问b.jsp
-> a1中请求元素<a href="../b/b.jsp">b.jsp</a> -
a1.jsp中访问d.jsp
-> a1中请求元素<a href="../c/d/d.jsp">d.jsp</a>
可以见得,资源的定位是由a1所在目录决定的,下面我们再看看设置<base>后的效果:
设置<base>的情况
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":"
+ request.getServerPort()+path+"/";
%>
<base href="<%=basePath%>">
-
a1.jsp中访问a2.jsp
-> a1中请求元素<a href="a/a2.jsp">a2.jsp</a> -
a1.jsp中访问b.jsp
-> a1中请求元素<a href="b/b.jsp">b.jsp</a> -
a1.jsp中访问d.jsp
-> a1中请求元素<a href="c/d/d.jsp">d.jsp</a>
通过对比相信你已经明白了设置与不设置的区别了。 没错,设置<base>后 资源的定位不再由a1所在目录决定的, 而是有webapp目录决定。这样有如下几点好处:
-
不需要在页面中以../或../../来回到上级或上上级目录
-
都是相对于WebRoot目录,实现了路径的统一
-
当某一资源位置变动时 只需Ctrl+f替换 有些工具会自动修改请求元素的定位路径 象dreamwaver等
补充:
1. jsp页面中请求元素中的最前面的/代表的是"主机地址:端口号/", 如:
<a href="/a.jsp">a.jsp</a> 的完整路径为http://localhost:8080/a.jsp
2. String basePath = request.getScheme()+"://"+request.getServerName()+":"
+request.getServerPort()+path+"/";
这段话的含义先看下http协议的请求信息都包含哪些东西:
请求头信息
POST /myproject/backmanager/CheckInformationSevrlet HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.2.22) Gecko/20110905 Ubuntu/10.04 (lucid) Firefox/3.6.22
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://localhost:8080/myproject/backmanager/login.jsp
Cookie: JSESSIONID=51C310206938FBA5F44CBEED0D219EAF
响应头信息
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=UTF-8
Content-Length: 708
Date: Sun, 18 Sep 2011 13:28:35 GMT
request对象封装了由客户端生成的http请求的所有细节( 请求参数,属性,请求头信息,cookies,数据)我们只关注头信息
request.getScheme()------->http
request.getServerName()-------->localhost
request.getServerPort()------------->8080
request.getContextPath()-------------->myproject
2. servlet中的路径
servlet中主要涉及路径的地方有两个: 重定向, 转发.
两者的区别:
重定向:是当服务器端执行重定向语句时, 将向客户端发送一条命令, 让浏览器重新访问新的地址, 浏览器发出两次请求。同时服务器端在执行完重定向语句后,还会继续执行重定向下面的语句,所以一般不要在重定向语句后写其他语句, 直接return就好了
转发:当服务器执行转发语句时,服务器将调用转发的页面的servlet(服务器内部转) ,再由转发页面将结果返回给客户端,rquest进行了封装传递, 调用之后别忘了return。
重定向的路径:
response.sendRedirect(request.getContextPath()+"/a/a.jsp");
JavaEE5.0对sendRedirect的解释
the servlet container must convert the relative URL to an absolute URL before sending the response to the client. If the location is relative without a leading '/' the container interprets it as relative to the current request URI.If the location is relative with a leading '/' the container interprets it as relative to the servlet container root.(tomcat所在根目录不保含具体的project名称)
相信英语说的过去的都能看懂, 原文解释的比较地道, 我就不多说了。
这句语句指重定向到 http://localhost:8080/myproject/a/a.jsp
转发中的路径:
request.getRequestDispatcher("/a/a.jsp").forward(request, response);
这句语句指 转发到 http://localhost:8080/myproject/a/a.jsp
补充:
1.servlet页面中请求元素中的最前面的/代表的是"主机地址:端口号/project/". 相当于
request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"
所以转发直接按照相对webapp进行资源定位就哦了
2.web.xml中的路径( 这个是具体项目的相关web.xml配置文件, 而不是servlet /jsp, 容器全局的web.xml配置文件)
这里的路径/的含义和servlet页面中的一样相当于:
request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"
关于jsp+servlet开发下的路径问题总结:http://hi.baidu.com/it_crazyer/item/318d105051561dd6d58bac73
--------------------------------------------------------------------------------------
为了避免jsp跳jsp,servlet跳jsp,forward方式跳转,sendredirect跳转产生的路径问题, 对于jsp和使用sendredirect跳转的servlet,采用直接使用带容器路径[string request.getcontextpath()]的绝对路径就能完全解决,即:
<%
string contextpath = request.getcontextpath();
string url = contextpath + "/user/login.jsp";
%>
<a href="<%=url%>"> login</a>
另一种方法就是使用 jsp页面的正则表达式 。 ${ctx} 这样就可以获取 ctx的值 与<%=ctx%>的功能一样。
string contextpath = request.getcontextpath();
string targetpath = contextpath + "/user/login.jsp";
requestdispatcher rd = request.getrequestdispatcher(targetpath);
rd.forward(request, response);
......
对于使用forward跳转的servlet,则不要加容器路径,否则就重复出现 容器路径。
因为在servlet中以forward方式使用的 “/” 表示的根为“host:port/app/”,包含了应用路径, 而
在servlet中以sendredirect方式使用的 “/” 表示的根为“host:port”,不包含应用路径。