1.JSP、Servlet中的相对路径和绝对路径
前提:假设你的Http地址为http://192.168.0.1/你的web应用为test,path="/test"那么你的web应用URL为http://192.168.0.1/test/
如果JSP,JS文件放在WEB-INF目录下根本无法访问的,JSP如果放在WEB-INF目录下可以通过服务器内部转向进行访问(主要是为了页面的安全),但是JS是通过客户端向服务器请求的,所以图片以及一些JS,CSS只能放在WEB-INF外面
web应用的目录结构:
test/web/
css/
js/
test.js
web-inf/
classes/
lib/
user/
a.jsp
b.jsp
images/
web.xml
<servlet-mapping>
<servlet-name>handleservlet</servlet-name>
<url-pattern>/handleservlet</url-pattern>此映射是相对于当前web应用的
</servlet-mapping>
所有相对路径都是由"/"开头的 。如:/image/a.gif,/user/main.jsp,大家知道在html中的相对路径是这样的:
有个html文件:a.html,其中有<link href="one.css" rel="stylesheet" type="text/css">,其中href属性表示引用的css文件的路径。
one.css:表示one.css和a.hmtl处于同一个目录
user/one.css:表示one.css处于a.html所在目录的子目录user中,即user是a.html在同一个目录 。
../one.css:表示one.css位于a.hmtl上一级目录下,
../../one.css:表示one.css位于a.hmtl上一级目录的上一级目录下,
./:表示和a.hmtl同一目录
我们称上述相对路径为html相对路径
1、 服务器端的地址
服务器端的相对地址指的是相对于你的web应用的地址,这个地址是在服务器端解析的 (不同于html和javascript中的相对地址,他们是 由客户端浏览器解析的 )也就是说这时候在jsp和servlet中的相对地址应该是相对于你的web应用,即相对于http://192.168.0.1/test/的。
其用到的地方有:
forward:servlet中的request.getRequestDispatcher(address);这个address是在服务器端解析的,所以,你要forwarder到user/a.jsp应该这么写:request.getRequestDispatcher("/user/a.jsp ")这个/相对于当前的web应用test,其绝对地址就是:http://192.168.0.1/test/user/a.jsp。
redirect:在jsp中<%response.sendRedirect("/rtccp/user/a.jsp");%>
2、 客户端的地址
所有的html中的相对地址都是相对于http://192.168.0.1/的,而不是http://192.168.0.1/test/的 。
Html中的form表单的action属性的地址应该是相对于http://192.168.0.1/的,所以,如果提交到user/a.jsp为:action="/test/ user/a.jsp" ;提交到servlet为action="/test/handleservlet"
Javascript也是在客户端解析的,所以其相对路径和form表单一样。
3、 站点根目录和css路径问题 (jsp是服务器端程序,地址是变化的,引用时一般用站点根目录的相对路径)
我们称类似这样的相对路径/test/…. 为相对于站点根目录 的相对路径 。
当在jsp中引入css时,如果其相对路径相对于当前jsp文件的,而在一个和这个jsp的路径不一样的servlet中forward这个jsp时,就会发现这个css样式根本没有起作用。这是因为在servlet中转发时css的路径就是相对于这个servlet的相对路径而非jsp的路径了。所以这时候不能在jsp中用这样的路径:<link href="one.css" rel="stylesheet" type="text/css">或者<link href="../../one.css" rel="stylesheet" type="text/css">类似href="one.css"和../../one.css的html相对路径是相对于引用这个css的文件(a.jsp)的相对路径 。而在servlet中转发时就是相对于这个servlet的相对路径了,因为jsp路径和servlet路径是不一样的 ,所以这样的引用肯定是出错的。
所以这个时候,要用站点根目录,就是相对于http://192.168.0.1/的目录,以“/”开头。
因此上述错误应更正为href=”/test/one.css” 类似的站点根目录的相对目录。这样在servlet转发后和jsp中都是相对于站点根目录的相对路径 ,就能正确使用所定义的css样式了。
页面跳转问题:
Forward 高, Redirect 低, 因为Redirect 的流程是这样的, request1 sent to server, server return back to client, 然后
request2 then sent to server. 但是Forward 仅在server side处理, 对client side 是透明的. 由于Redirect 有两次传输, 所以效率低.
范围:
由于对request.setAttribute() 来说, 它携带的对象生存范围只在request内, 所以Redirect 方式会导致request携带的对象丢失.
使用说明:
1. sendRedirect
servlet和jsp里面一样
response.sendRedirect();
2. include 这种也是上面提到的forward形式,request的值会保存
1) servlet里面
request.getRequestDispatcher( "jsp2.jsp" ).include(request, response);
2) jsp里面
<jsp:include page= "include.jsp" />
说明
页面会同时包含页面1和页面2的内容,地址栏不变。
使用request.setAttribute的内容,可以正常使用
3. forword
1) servlet里面
request.getRequestDispatcher( "jsp2.jsp" ).forward(request, response);
2) jsp里面
<jsp:forward page= "include.jsp" />
说明
页面会是页面2的内容,地址栏不变
使用request.setAttribute的内容,可以正常使用
3.JSP中用相对路径引用JS,CSS文件的三种情况
第一种情况 最常见的情况
一个tomcat上都跑多个工程, 用工程名来区分
因为我的的URL是 :http://localhost/工程名 /home/index.jsp
多了一个工程名,所以要加 <%=request.getContextPath() %>
如:<script src="<%=request.getContextPath() %> /home/test.js"></script>
写<%=request.getContextPath() %>太麻烦,可以在每一个jsp文件顶部加入以下内容后,
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme()+"://" +request.getServerName()+":" +request.getServerPort()+path+"/" ;
- %>
- <base href="<%=basePath%>" >
就可直接使用 <script src=" /home/test.js"></script>了
第二, 直接访问jsp文件
真实项目中, 一个tomcat上要是也跑了多个工程, 并用IP来区分
url 是这样的: http://localhost/home/index.jsp 注意这里,是直接访问JSP文件(jsp文件不在web-inf下,可以直接访问),不是servlet也不是struts 。
test2.js 与index.jsp 放在同一文件夹下,下面用相对路径来引入JS文件 是OK 的:
<script src=test2.js></script>
index.jsp可以找到test2.js文件
第三种情况: servlet转发到jsp(jsp在web-inf下,必须用servlet或action访问)
在第二情况的基础上,一个tomcat上要是也跑了多个工程, 并用IP来区分。
我们访问的是servlet 或是struts的action , 再转发到 index.jsp
url 是: http://localhost/***.do
url 是: http://localhost/index.action
这里不是访问JSP文件了
下面是OK 的.
<script src=/home/ test2.js></script>
test2.js 前面一定要有/home/
实际项目中, 访问 servlet或是struts的action最多, 所以这里要使用<script src=/home/test2.js></script>。
----------------------------------------------------------------------------------------------------------------------------------
访问servlet的路径问题
一、url-pattern的三种配置
在web.xml配置文件中配置有关Servlet的时候,<url-pattern>标签是用于配置当前Servlet拦截的路径,也就是说,客户端浏览器访问<url-pattern>标签配置的路径才能访问对应Servlet内容。
关于拦截路径的配置方式其实有三种方式:
- 完全路径匹配:是以“/”开始,路径中间不能包含通配符“*”,例如:/firstServclet,表示访问路径为http://localhost:8080/08_servlet/firstServlet。
- 目录匹配:是以“/”开始,以“/*”结尾的,例如:/firstServlet/*,表示访问路径为http://localhost:8080/08_servlet/firstServlet路径下任意内容。
- 扩展名匹配:是以“*”开始,不能以“/”开始,以“.xxx”结尾,例如:*.do,表示访问路径为所有扩展名为“.do”的路径。
值得注意的问题:
- 在一个<servlet-mapping>标签中,可以配置多个<url-pattern>标签。也就是说,一个Servlet可以拦截多个不同路径的访问。
- 上述三种配置路径方式具有优先级:完全路径匹配 -> 目录匹配 -> 扩展名匹配。
下面通过一些测试,来看看路径配置的三种方式:
如下有一些映射关系:
- Servlet1 映射到 /abc/*
- Servlet2 映射到 /*
- Servlet3 映射到 /abc
- Servlet4 映射到 *.do
问题:
- 当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配,哪个servlet响应?Servlet1
- 当请求URL为“/abc”时,“/abc/*”和“/abc”都匹配,哪个servlet响应?Servlet3
- 当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都匹配,哪个servlet响应?Servlet1
- 当请求URL为“/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应?Servlet2
- 当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应?Servlet2
如果客户端浏览器请求的路径是错误时,页面会显示404错误内容。这是因为所有发布到Tomcat服务器的Web应用程序的web.xml文件都继承了Tomcat服务器安装目录中conf目录中的web.xml文件。当访问路径是错误的,或者对应Servlet没有配置,实际上会执行Tomcat服务器中的web.xml的相关配置,具体内容如下:
1 <servlet> 2 <servlet-name>default</servlet-name> 3 4 <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> 5 <init-param> 6 <param-name>debug</param-name> 7 <param-value>0</param-value> 8 </init-param> 9 <init-param> 10 <param-name>listings</param-name> 11 <param-value>true</param-value> 12 </init-param> 13 <load-on-startup>1</load-on-startup> 14 </servlet> 15 <servlet-mapping> 16 <servlet-name>default</servlet-name> 17 <url-pattern>/</url-pattern> 18 </servlet-mapping>
1.2. 相对路径与绝对路径
之前我们开发的Servlet,在客户端浏览器中都是直接在地址栏中输入路径来访问的。如果创建一个页面来访问Servlet应该怎么样呢?下面我们来看一看:
- 在Web工程中的WebRoot目录下,创建一个新目录名为“html”,然后在该目录下创建一个新的HTML页面。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>01.html</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <h1>相对路径访问Servlet</h1><br> <a href="">相对路径访问Servlet</a> <h1>绝对路径访问Servlet</h1><br> <a href="">绝对路径访问Servlet</a> </body> </html> |
- 在Web工程中的WebRoot目录下,创建一个新的HTML页面。
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 2 <html> 3 <head> 4 <title>02.html</title> 5 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 6 <meta http-equiv="description" content="this is my page"> 7 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 8 </head> 9 <body> 10 <h1>相对路径访问Servlet</h1><br> 11 <a href="">相对路径访问Servlet</a> 12 <h1>绝对路径访问Servlet</h1><br> 13 <a href="">绝对路径访问Servlet</a> 14 </body> 15 </html>
- 在Web工程中创建一个Servlet。
public class PathServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("成功访问到Servlet");
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
- 配置Web工程的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>PathServlet</servlet-name> <servlet-class>app.java.servlet.PathServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>PathServlet</servlet-name> <url-pattern>/pathServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
- 将当前Web工程发布到Tomcat服务器,并启动Tomcat服务器。
- 打开浏览器,分别访问01.html、02.html和PathServlet。
访问01.html的路径:http://localhost:8080/08_servlet/html/01.html。
访问02.html的路径:http://localhost:8080/08_servlet/02.html。
访问PathServlet的路径:http://localhost:8080/08_servlet/pathServlet。
- 根据上述的访问路径,可以知道在01.html和02.html页面中,通过绝对路径访问PathServlet是相同的。
- 在01.html和02.html页面中,通过相对路径访问PathServlet是不同的。
在01.html页面中利用相对路径访问PathServlet应该是../pathServlet。原因是pathServlet是在01.html页面的父级目录中。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>01.html</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <h1>相对路径访问Servlet</h1><br> <a href="../pathServlet">相对路径访问Servlet</a> <h1>绝对路径访问Servlet</h1><br><a href="http://localhost:8080/08_servlet/pathServlet">绝对路径访问Servlet</a>
</body></html>
² 在01.html页面中利用相对路径访问PathServlet应该是./pathServlet或直接访问拦截名称pathServlet。原因是pathServlet与02.html页面处在同一级别的目录中。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>02.html</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <h1>相对路径访问Servlet</h1><br> <a href="pathServlet">相对路径访问Servlet</a> <h1>绝对路径访问Servlet</h1><br> <h1>绝对路径访问Servlet</h1><br> <a href="http://localhost:8080/08_servlet/pathServlet"> 绝对路径访问Servlet</a> </body> </html>
servlet中,所有路径的配置都要用绝对路径。
什么是绝对路径,就是以“/”开头的路径(开发中就这样理解)。
实际开发中,“/”所代表的含义不同,但主要分以下两种情况:
1.servlet内部配置路径
servlet内部的含义就是:在客户端看不到,全是在(应用)后台处理的部分(简单说,就是除了JSP以外的所有地方)。包含以下2点:
a. web.xml中servlet 配置的路径
<servlet>
<servlet-name>helloWorld</servlet-name>
<servlet-class>
com.bill99.li.servlet.HelloWorldServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloWorld</servlet-name>
<url-pattern>/test1/helloWorld</url-pattern>
</servlet-mapping>
我们配置的这个“ /test1/helloWorld”,前面必须加“/” ---- 该“/”代表我们应用的名称。比如我们的应用名是“test”,那访问我们应有的地址就是: http:// 192.168.XX.XX:8080/test ,说白了就是代表项目的名称。
“ /test1/helloWorld”代表的路径就是http:// 192.168.XX.XX:8080/test/test1/helloWorld
b.forward转发的路径(注意:不包含redirect重定向)
做完后台业务逻辑处理后,需要做页面的跳转,比如:
req.getRequestDispatcher("/pages/succ.jsp").forward(req, resp);
这时候跳转的页面"/pages/succ.jsp"也必须添加“/”,它代表的含义也一样,是我们应用的名称。
总结:
在应用内部,“/”代表的就是应用的名称!!!
2.页面配置的路径
页面是指什么 ------ 肯定是指我们的JSP页面,而JSP页面是服务端解析的,对我们而言是下载到客户端,让浏览器解析为HTML展示出来的页面。
比如,我们的应用url是:http:// 192.168.XX.XX:8080/test
那站点的路径就是:http:// 192.168.XX.XX:8080/ --- 很明显 test 是应用名
对客户端的浏览器而言,它认识的只有站点,也就是说,我们的jsp页面,“/”代表的是站点名。
所以在“/”后需要添加上我们应用的名称才能正确的访问到。(也容易理解,一个tomcat下可以部署多个应用,就相当于一个站点多个应用,怎么区别不同的应用呢,当然是不同应用名啦-----这个需要和上面的servlet内部配置路径区分理解一下啊,因为servlet本身就部署在服务端,在站点内部了,内部处理肯定知道它是站点下的哪个应用内,但对于外部而言,只知道一个站点IP。)
页面主要表现有以下3个地方:
a. form的action路径配置
页面举例:
<form action=" /test /test1/helloWorld" method="post">
解析:
应用名是test,/ 代表站点的url http:// 192.168.XX.XX:8080/,所以/test代表 http:// 192.168.XX.XX:8080/test
而/test1/helloWorld代表servlet在web.xml中配置的访问路径,所有上面的action可以正确的访问。
但是在真正的应用中,我们经常这样写:
<form action="${pageContext.request.contextPath}/test1/helloWorld" method="post">
${pageContext.request.contextPath} 的效果就是"/应用名" ,这里等于 /test
一样的效果,不解释啦。
b. 页面资源引用
同样,只要是页面中引入的东西(常常需要引入CSS,JS,图片等),都要如此写,比如
<script type="text/javascript" src="${pageContext.request.contextPath}/pages/event/js/addevent.js"></script>
c. jsp/servlet的重定向 redirect
首先必须理解重定向的概念:重定向其实向服务器发送了2次请求,第一次把请求url告诉给服务器,服务器看到这个请求的状态码,马上明白该url是需要浏览器来重新去请求的url,于是呢把该url显示在浏览器的地址栏内,再次向服务器请求(第二次了吧),服务器响应,然后返回。
很明显,只要和页面打交道的,“/”都代表站点名,需要在后面添加应用名以区分是哪个应用的请求。所有。。。。不解释也明白了吧!
总结:
所有涉及前端页面的地方,“/”代表的是站点名,需要我们在“/”加上应用名以明确应用服务!!
=========================================================
基本上可以总结为两点:
a. servlet中所有访问路径都要用绝对路径“/”开头
b. 页面中“/”表示站点路径(在客户端展现出来,只知道它的站点路径,所有需要“/”后追加应用名来区分属于站点下的哪个应用),其他地方的“/”表示应用路径(在服务端的应用程序内调用,肯定是相对于应用的路径啦)