jsp页面中使用JSTL标签库的的一些看法和疑问?
哎!哎!哎!不知道csdn怎么搞的,我写文章的时候,明明是大图片,保存文章之后图片就变得很小了,根本看不清图片了,csdn的体验好差啊!大家凑合着看吧!哎!哎!......
我在jsp页面中使用JSTL标签库的<c:redirect>的一些疑问?
直接看代码
goodsList.jsp商品列表页面
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!--
如果直接在地址栏中输入jsp页面的网址http://localhost:8888/jmBookShop/goodsList.jsp访问的话,
就判断在该页面中的request对象中是否保存了商品集合列表的数据,如果request对象中没有保存商品集合列表的数据,就直
接跳转(重定向)到goodsServlet?operateType=fore这个地址
-->
<c:if test="${requestScope.goods == null}">
<c:redirect url="goodsServlet?operateType=fore"></c:redirect>
</c:if>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>商品信息列表-囧萌软件有限公司,雪豹软件工作室,江西省赣州市于都县</title>
<link rel="stylesheet" type="text/css"
href="${pageContext.request.contextPath}/background/css/body.css"
media="all">
<link rel="stylesheet" type="text/css"
href="${pageContext.request.contextPath}/background/css/mark.css">
<style type="text/css">
body{
font-weight: bold;
}
</style>
</head>
<body>
<center>
<font style="font-size: 22px;">
商品编号
商品
原价
囧萌价
<a class="submitOrderA" href="${pageContext.request.contextPath}/ShoppingCartServlet?operateType=look">
我的购物车
</a>
<a title="囧萌网上商城-雪豹软件工作室-江西省赣州市于都县" href="${pageContext.request.contextPath}/login.jsp">
登录
</a>
</font>
<c:forEach var="goodsItem" items="${requestScope.goods}">
<div class="goodsDiv">
<img height="100px" title="${goodsItem.goodsName}" src="${pageContext.request.contextPath}/img/16.jpg">
${goodsItem.goodsId}
${goodsItem.goodsName}
${goodsItem.originalPrice}
${goodsItem.discountPrice}
<a href="ShoppingCartServlet?goodsId=${goodsItem.goodsId}&operateType=add" title="${goodsItem.goodsName}">
加入购物车
</a>
</div>
<br>
</c:forEach>
</center>
</body>
</html>
我在该页面写了这句话,<c:if test="${requestScope.goods == null}"><c:redirect url="goodsServlet?operateType=fore"></c:redirect></c:if>,goodsList.jsp页面是商品信息列表的展示页面,是从goodsServlet这个Servlet中跳转到goodsList.jsp页面,但是怕有些人直接在浏览器地址栏中直接访问goodsList.jsp页面,如果是直接访问goodsList.jsp页面的话,那goodsList.jsp页面就会没有数据,所以我在goodsList.jsp页面的开头的地方写了判断,如果${requestScope.goods
== null}为空的话,那就重定向到goodsServlet这个Servlet,所以问题来了啊,<c:redirect url="goodsServlet?operateType=fore"></c:redirect>这句话中的url属性的值开头要不要带斜杠,我带着好奇的心情,试了好几种写法,
第一种<c:redirect url="goodsServlet?operateType=fore"></c:redirect>
第二种<c:redirect url="/goodsServlet?operateType=fore"></c:redirect>
第三种<c:redirect url="${pageContext.request.contextPath}/goodsServlet?operateType=fore"></c:redirect>这里的${pageContext.request.contextPath}是获取项目名称(即/jmBookShop)
可是结果却大跌眼镜
第一种结果是OK的,没问题,看截图,可以正常访问,这里我们可以理解,因为url="goodsServlet?operateType=fore"这里不加斜杠,其实就是代表从项目的根目录开始,项目的根目录,明白吧,项目的根目录也就是http://localhost:8888/jmBookShop
第二种结果居然也是OK的,没问题,看截图,可以正常访问,这里我就无法理解了,因为url="/goodsServlet?operateType=fore"这里加上了/斜杠,其实就是代表从站点的根目录开始,站点的根目录,明白吧,站点根目录也就是http://localhost:8888,那就意味着url="/goodsServlet?operateType=fore"这句话,最终的完整路径是http://localhost:8888//goodsServlet?operateType=fore这样的话,明显是少了/jmBookShop项目名称嘛,怎么可能能访问成功呢?应该报404错误啊,可是偏偏没有报404错误,而是能正常访问,看如下截图就知道了
第三种写法的结果也出乎我的意料<c:redirect url="${pageContext.request.contextPath}/goodsServlet?operateType=fore"></c:redirect>这里的${pageContext.request.contextPath}是获取项目名称(即/jmBookShop),我们都知道在jsp中,form表单的action路径,如果你想在路径前面加/斜杠的话,也是可以的,但是必须要加上项目名称,就像第三种写法一样,${pageContext.request.contextPath}/goodsServlet?operateType=fore,这种写法最终会解析成/jmBookShop/goodsServlet?operateType=fore,所以按照以前jsp中的form表单的action路径的想法,第三种写法也是没问题的,可是这样写,偏偏在jstl的标签<c:redirect>行不通,最终导致
报了404错误,大家看截图
大家看到了吗?在地址栏中输入localhost:8888/jmBookShop/goodsList.jsp回车之后,就看到了404的报错提示,在看看提示的内容,大家看看,回车之后跳转到了http://localhost:8888/jmBookShop/jmBookShop/goodsServlet?operateType=fore这个页面,看到了吧,多了一层/jmBookShop目录,说明第三种写法不能加上${pageContext.request.contextPath}这句话,加了就会多一层/jmBookShop目录,所以我猜测,在jstl的标签<c:redirect>的底层的实现类中,实现类中应该已经加上了项目名称了,要不然我怎么一写${pageContext.request.contextPath}这句话就会多了一层/jmBookShop目录呢?为了证实我的猜测,我决定去看jstl的源码的实现类,于是我去网上下载了jstl的源代码,然后导入到eclispe中,怎么看源代码呢?看下我的截图
然后进入到该类中,
不知道怎么搞的,我在这些方法上打了断点,调试的时候就是跳不进来,不知道是不是导入jstl源代码的时候哪里出错了,还是我eclispe工具的问题,反正死活跳不进来,难道压根就不会调用这些方法吗?因为我在这些地方打了断点了,可是有些地方的断点进来了,有些断点一直没跳进来,我估计是我eclispe哪里出了问题,所以我折腾了半天,实在是折腾的够累的,所以我就不折腾了,反正大概就是执行这些类中的这些方法,八九不离十,所以等下次我有时间再倒回来研究这个问题吧,因为还有其他的任务工作没完成,所以就不在这里纠结了,下次回过头来再研究这个问题。
还有一个要说,就是按照我们的猜测和理解,猜测在jstl的<c:redirect>标签的底层的实现类中,如果<c:redirect>标签实现类中已经加上了request.getContextPath() 这句话,也就是底层已经获取了项目名称(即/jmBookShop),那么我们在goodsList.jsp页面中的这2中写法
第一种<c:redirect url="goodsServlet?operateType=fore"></c:redirect>
第二种<c:redirect url="/goodsServlet?operateType=fore"></c:redirect>
第三种<c:redirect url="${pageContext.request.contextPath}/goodsServlet?operateType=fore"></c:redirect>这里的${pageContext.request.contextPath}是获取项目名称(即/jmBookShop)
第一种和第二种写法最终会解析成
第一种没加斜杠的话,那么我们可以按照我们jsp中form表单的action的路径来理解,不加斜杠就代表项目根目录,所以第一种的写法的url最终会直接解析成http://localhost:8888/jmBookShop/goodsServlet?operateType=fore其实也就是类似于form表单的如下写法
<form action="goodsServlet?operateType=fore" method="post"></form>,最终会解析成<form action="http://localhost:8888/jmBookShop/goodsServlet?operateType=fore" method="post"></form>
第二种加上了斜杠的话,那么底层的jstl的<c:redirect>标签的底层的实现类中,<c:redirect>标签实现类中默认已经加上了request.getContextPath()这句话了,所以第二种的写法的url最终会解析成/jmBookShop/goodsServlet?operateType=fore,最终会解析成http://localhost:8888/jmBookShop/goodsServlet?operateType=fore,其实也就是类似于form表单的如下写法
<form action="/jmBookShop/goodsServlet?operateType=fore" method="post"></form>最终会解析成<form action="http://localhost:8888/jmBookShop/goodsServlet?operateType=fore" method="post"></form>
所以第一种和第二种写法都能正常实现重定向跳转,而不会报404错误!
那么第三种写法,我们来看看第三种写法,<c:redirect url="${pageContext.request.contextPath}/goodsServlet?operateType=fore"></c:redirect>这里的${pageContext.request.contextPath}是获取项目名称(即/jmBookShop),所以第三种写法的url就等于<c:redirect url="/jmBookShop/goodsServlet?operateType=fore"></c:redirect>,你们看得到的url的值等于/jmBookShop/goodsServlet?operateType=fore,看到了吧,加了/斜杠了,底层的jstl的<c:redirect>标签的底层的实现类中,如果是/斜杠开头,那底层的代码就会默认加上项目名称,所以这时候url的值就会等于/jmBookShop/jmBookShop/goodsServlet?operateType=fore,最终解析成http://localhost:8888/jmBookShop/jmBookShop/goodsServlet?operateType=fore,所以就多了一层/jmBookShop目录了,不报404错误才怪!看如下截图