目录
学习内容概括:1个EL表达式,2种注释类型,3个脚本元素,3个指令元素,6个动作标签 9大内置对象
EL表达式因为内容多放在后面
1.jsp简述
jsp技术是web网站的服务端技术,可以简单理解为jsp技术说是用来生成动态网页的。
普通的网页是html的,它是静态的,需要事先用html语言编写好。那么我们在html页面中加入一些java代码,用java代码部分动态的内容插入到原来的html页面中,那么,这个页面就可以成为jsp页面。即,jsp=html+java。(来自简书的用户:李灿辉
链接:https://www.jianshu.com/p/88db37562751)
后来jsp继续发展,用更方便的标签、指令代替了大部分的java脚本,使得jsp更独立和更方便
有人说jsp落后了,但是理解jsp对于我们学习后面springmvc很有帮助。学生党不要挑剔那么多,一门语言存在即合理。
下面给出一些参考文章
jsp与php的对比:https://www.cnblogs.com/jiangzhaowei/p/6419353.html 来自博客园的用户qiuri2008
jsp走向没落?:https://blog.csdn.net/xuaman/article/details/78296871 来自csdn的用户xuanman
jsp:一个装配工的没落:https://blog.csdn.net/yuanlaijike/article/details/79247856 来自csdn的用户 Jitwxs
JSP = html + Java脚本(代码片段) + JSP动态标签
2.jsp的生命周期
(下面是来自菜鸟教程的资料:http://www.runoob.com/jsp/jsp-life-cycle.html)
JSP生命周期就是从创建到销毁的整个过程,类似于servlet生命周期,区别在于JSP生命周期还包括将JSP文件编译成servlet。
以下是JSP生命周期中所走过的几个阶段:
-
编译阶段: servlet容器编译servlet源文件,生成servlet类
- 初始化阶段:加载与JSP对应的servlet类,创建其实例,并调用它的初始化方法
- 执行阶段: 调用与JSP对应的servlet实例的服务方法
- 销毁阶段:调用与JSP对应的servlet实例的销毁方法,然后销毁servlet实例
很明显,JSP生命周期的四个主要阶段和servlet生命周期非常相似,下面给出图示:
2.1 JSP编译
当浏览器请求JSP页面时,JSP引擎会首先去检查是否需要编译这个文件。如果这个文件没有被编译过,或者在上次编译后被更改过,则编译这个JSP文件。
编译的过程包括三个步骤:
- 解析JSP文件。
- 将JSP文件转为servlet。
- 编译servlet。
2.2 JSP初始化
容器载入JSP文件后,它会在为请求提供任何服务前调用jspInit()方法。如果您需要执行自定义的JSP初始化任务,复写jspInit()方法就行了,就像下面这样:
public void jspInit(){
// 初始化代码
}
一般来讲程序只初始化一次,servlet也是如此。通常情况下您可以在jspInit()方法中初始化数据库连接、打开文件和创建查询表。
2.3 JSP执行
这一阶段描述了JSP生命周期中一切与请求相关的交互行为,直到被销毁。
当JSP网页完成初始化后,JSP引擎将会调用_jspService()方法。
_jspService()方法需要一个HttpServletRequest对象和一个HttpServletResponse对象作为它的参数,就像下面这样:
void _jspService(HttpServletRequest request,
HttpServletResponse response)
{
// 服务端处理代码
}
_jspService()方法在每个request中被调用一次并且负责产生与之相对应的response,并且它还负责产生所有7个HTTP方法的回应,比如GET、POST、DELETE等等。
2.4 JSP清理
JSP生命周期的销毁阶段描述了当一个JSP网页从容器中被移除时所发生的一切。
jspDestroy()方法在JSP中等价于servlet中的销毁方法。当您需要执行任何清理工作时复写jspDestroy()方法,比如释放数据库连接或者关闭文件夹等等。
jspDestroy()方法的格式如下:
3.jsp的基本语法
3.1 2种注释类型
①html注释
<!--注释内容-->
这个应该都很熟悉 不过这个会把注释发到客户端,但是客户端不显示而已
②jsp注释
<%--注释内容--%>
jsp的注释不会发到客户端,服务器在把jsp文件编译为java文件时已经忽略了注释部分。
ps:以上两种只能定义在脚本元素之外,即非java代码区。如果要想在java代码区填写注释,还是得用//或者/* */
客户端代码,可以看到只有<!-- -->这种注释才会发送到客户端
3.2 3个脚本元素
正如上面所说,jsp由html、java代码片段、jsp动态标签组成。jsp脚本元素是用来表述java片段的。jsp脚本元素三种形式
- <%........%> 可以存放 0-n条java语句,等同于java方法里的语句
- <%=.......%> 可以存放表达式,用于输出一条表达式(变量)的结果 比如<%=i> 就是输出变量i的值
- <%!.......%> 可以存放全局变量或者全局方法(不是方法体内的局部变量)
3.3 3个指令元素
jsp指令的格式:<%@指令名 attr1="" attr2="" %>,一般都会把jsp指令放在jsp文件的最上方,但不是必须的。jsp有三大指令:page,include,taglib,其中最常用也是最复杂的就是page指令了。先放一张图让你们认识认识这三个指令元素
3.3.1 page
page指令被称为页面指令,用来定义jsp页面的全局属性。page指令有挺多属性的,这里介绍重点的几个。
- pageEncoding、contentType
pageEncoding指定当前页面的编码,这个编码是给服务器看的,因为服务器需要把当前jsp编译为java文件;contentType和response.setContentType()一样,都是设置字符流的编码,此外它还有一个功能,设置response的content-type响应头。
无论是pageEncoding还是contentType,默认值都是iso-8859-1,这个值是无法显示中文的,所以jsp存在中文的话,一定得设置这两个属性。但是有点特殊,这两个属性只要设置了一个,另一个的默认值就等于已设定的属性的值。因此一般都是选择设置contentType,毕竟它多了个“text/html”
- extends、import
extends指定jsp继承的父类;import指定导入的包,其中Java.lang.*、javax.servlet.*、javax.servlet.jsp.*、javax.servlet.http.*这几个包本身已经被导入,无需再导入。import指令是唯一一个一条page指令中可重复出现的属性,不过我们一般写多条指令,每条带一个import属性。这两个的效果是一样的
- isErrorPage、errorPage
当你设置isErrorPage为true时,说明该界面为错误界面,即专门处理错误的界面;errorPage指定处理错误的界面,当当前界面发生错误时,会将请求转向errorPage指定的界面(这个界面得设置isErrorPage="true")。
在jsp中除了可以用page的属性进行指定错误界面,其实也可以在web.xml中指定。
web.xml
<error-page> <error-code>404</error-code> <location>/error404.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/error500.jsp</location> </error-page> <error-page> <exception-type>java.lang.RuntimeException</exception-type> <location>/error.jsp</location> </error-page> |
<error-page>有两种使用方式:
<error-code>和<location>子元素
<exception-type>和<location>子元素;
其中<error-code>是指定响应码,<location>指定转发的界面;<exception-type>是指定抛出的异常类型
所以在上面这张图中:
- 当出现404时,会跳转到error404.jsp页面;
- 当出现RuntimeException异常时,会跳转到error.jsp页面;
- 当出现非RuntimeException的异常时,会跳转到error500.jsp页面。
除了以上的这6中常见属性,还有session:指定该界面是否可以用session对象;isThreadSafe:制定该jsp界面是否支持多线程; isElignored:指定该jsp界面是否支持EL表达式; info:设置页面的相关信息
- 其他的属性
3.3.2 include
include表示静态包含,即把多个jsp文件合成一个servlet文件。静态包含就是在编译前先把这两个文件合并成一个jsp文件再编译为 servlet文件。既然有静态包含也有动态包含,动态包含下面会提到
其中的file属性用于指定被引入文件的相对路径。 file属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前WEB应用程序的根目录(注意不是站点根目录),否则,表示相对于当前文件
3.3.3 taglib
taglib的作用是用来引用标签库。语法:
<%@ taglib prefix="test" uri="http://java.sun.com/jsp/jstl/core" %>
prefix是前缀,你可以随便起,url是该标签库地址
3.4 6个动作标签
动作标签的作用就是用来简化java脚本的,通俗的讲,这就是提前制定好的一些“java”片段,我们可以直接拿来使用,减少我们的工作量。就跟类库有点相似。据说,javaWeb提供了20个jsp动作标签(我在菜鸟教程只找到了10个),先来张图
语法 | 描述 |
---|---|
jsp:include | 在页面被请求的时候引入一个文件。 |
jsp:useBean | 寻找或者实例化一个JavaBean。 |
jsp:setProperty | 设置JavaBean的属性。 |
jsp:getProperty | 输出某个JavaBean的属性。 |
jsp:forward | 把请求转到一个新的页面。 |
jsp:plugin | 根据浏览器类型为Java插件生成OBJECT或EMBED标记。 |
jsp:element | 定义动态XML元素 |
jsp:attribute | 设置动态定义的XML元素属性。 |
jsp:body | 设置动态定义的XML元素内容。 |
jsp:text | 在JSP页面和文档中使用写入文本的模板 |
这里的我们只讨论6个:jsp:include jsp:forward jsp:parameter jsp:useBean jsp:setProperty jsp:getProperty,后面三个跟javaBean有关。
- jsp:include
<jsp:include page="login.jsp" />
jsp:include动作标签是动态包含 功能和RequestDispatcher的include()方法是一样的,都是在运行级别时完成合并,即当前jsp和被include的jsp各自编译为servlet文件,再“合并”(具体为当前jsp编译的servlet文件在执行时完成包含另一个jsp的servlet文件)。
与Page指令的include属性不一样,include是静态合并,是在运行前合并。
- jsp:forward
<jsp:forward page="loginB.jsp" />
jsp:forward标签的作用就是请求转发,与request中介绍的请求转发一致
ps:客户端最后看到的界面时请求转发设置的界面(loginB.jsp),比如下面这个例子中loginA\.jsp的<h1>欢迎登录</h1>是不会发到客户端的,只看到loginB.jsp的<h1>登录界面</h1>
loginA.jsp
loginB.jsp
显示结果
ps:这里page中的路径没带/就默认是当前文件下的,我的loginA.jsp和loginB.jsp都是保存在jspforward文件夹下。所以才可以直接写<jsp:forward page="loginB.jsp" />
如果要跳转的是其他文件夹的得加 / 。比如你jspforward文件夹的loginA.jsp想请求转发至jspinclude文件夹的loginB.jsp。应该这样敲
<jsp:forward page="/jspinclude/loginB.jsp" />
- jsp:param
jsp:param是jsp:include jsp:forward的子标签,起到传递参数的作用。举例说明
loginA.jsp
<body>
<h1>这里是loginA.jsp界面</h1>
<%-- 如果是跳转到其他文件夹的jsp文件得加 / --%>
<jsp:include page="/jspforward/loginB.jsp">
<jsp:param name="name" value="zhangsan" />
<jsp:param name="password" value="123"/>
</jsp:include>
</body>
loginB.jsp
<body>
<h1>登录界面 这是loginB.jsp的界面</h1>
<%
String name = request.getParameter("name");
String password = request.getParameter("password");
out.println("登录名:" + name);
out.println("登录密码:" + password);
%>
</body>
显示结果
- jsp:useBean 、jsp:getProperty、jsp:setProperty
<jsp:useBean id="唯一标识" class="JavaBean类名" scope="作用的域名" />
<%--scope四个参数为page request session application 这四大域 --%>
<jsp:setProperty property="属性名" name="id名" value="属性值" />
<jsp:getProperty property="属性名" name="id名" />
作用
jsp:useBean :创建javaBean
jsp:setProperty :设置javaBean中属性的值和名称 跟settter类似
jsp:getProperty :获取javaBean中属性的值和名称 跟gettter类似
jsp:setProperty中的属性名就是创建的bean中定义的属性(那些变量)值,name是jsp:useBean中的id名,value就是属性值。
3.5 九大隐式(内置)对象
每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理。JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet) ,然后按照servlet的调用方式进行调用。
由于JSP第一次访问时会翻译成servlet,所以第一次访问通常会比较慢,但第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所以程序的执行效率不会受到影响。
JSP引擎在调用JSP对应的_jspServlet时,会传递或创建9个与web开发相关的对象供_jspServlet使用。JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用。这九大对象分别是
对象 | 描述 |
---|---|
request | HttpServletRequest 接口的实例 |
response | HttpServletResponse 接口的实例 |
out | JspWriter类的实例,用于把结果输出至网页上 |
session | HttpSession类的实例,当设置page指令的session属性为false时,这个页面不能使用session |
application | ServletContext类的实例,与应用上下文有关 |
config | ServletConfig类的实例 |
pageContext | PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问 |
page | 类似于Java类中的this关键字 |
Exception | Exception类的对象,代表发生错误的JSP页面中对应的异常对象 |
九大对象中,有很多是极少被使用的,比如config、page、exception
九大对象中pageContext对象最重要,它代表着着一个jsp页面,另外,它的本事还不小,它自身封装着其他8个对象的引用,而且本身还是一个域(javaWeb中四大域之一),使用该对象可以访问页面中的共享数据。
pageContext作为隐式对象
pageContext可以获取其他八个对象的引用,写法:
PageContext.getOut(); //获取out对象
PageContext.getSession(); //获取session对象
PageContext.getPage(); //获取page对象
PageContext.getServletConfig(); //获取config对象
PageContext.getServletContext(); //获取application对象
PageContext.getRequest(); //获取request对象
PageContext.getResponse(); //获取response对象
PageContext.getExceptioin(); //获取exception对象
pageContext作为域对象
在介绍pagecontext作为域对象的功能前,得先讲一下jsp的四大域对象:page、request、session、application(从小到大)
page域
作用范围:当前jsp页面
生命周期:从对jsp页面的访问开始到离开该jsp页面为结束
作用:为当前jsp共享数据
①作为域对象必定有的三个方法:
void setAttribute(String name,Object vaue)
Object getAttribute(String name,Object value)
void removeAttribute(String name,Object value)
②代理其他域对象的功能,即可以使用pageContext向request、session、application域对象中存取数据
void setAttribute(String name,Object value,int scope); //在指定域范围内添加数据
Object getAttribute(String name,Object value,int scope); //在指定域范围内获取数据
void removeAttribute(String naem,Object value,int scope); //删除指定域范围内的数据
其中四个域的的常量scope写法为:REQUEST_SCOPE SESSION_SCOPE APPLICATION_SCOPE PAGE_SCOPE
③全域查找
Object findAttribute(String name)
这个方法的作用是在四个域中寻找name数据,寻找顺序从小到大:page、request、session、application
4.EL表达式
EL表达式是什么 EL(Expression Language)表达式是jsp2.0推出的产物,旨在取代这个 <%= %>jsp的脚本元素。就是取代java程序中的表达部分
EL表达式的语法也简单:${变量或者表达式}
我们顺着表达这个核心讲解EL表达式
4.1 使用el表达数据
使用el表达式你可以表达你定义的变量或者对象的值,变量很简单,直接${变量}就好了;对于一些对象,比如bean,list,map,就是如下的操作
操作bean属性 ${person.name} 、${person['name']} 替换getName()
操作List集合/数组属性 ${list[0]} ${arr[0]}
操作map的值 ${map.key} ${map['key']} 替换map.get(key)
- .和 [ ]的区别:
对EL来说,.和 [ ]都能表达数据,但是还是有一些不同
当要存取的属性名称里包含一些特殊字符时,比如- ?等非字母或数字的符号,一定要使用 [' '];。下面举例
person对象里有个My-name字段 ${person['My-name']}
或者是要动态取值时
${sessionScope.person[data]} data是一个变量
- 取值顺序
EL表达式表达数据时是用${}里的数据名为关键字,依次从page request session application四个域中检索对应的对象。当然你也可以直接指定要从那个域中获取数据。
不过有个注意的点 这四个域在El表达式里的写法是在其名字后加上Scope,即pageScope requestScope sessionScope applicationScope
指定从session域中取值: ${sessionscope.person.name}
4.2 使用el表达11大内置对象的数据
el内置了11个常见的对象,你可以直接使用这些对象里的值。除了第一个不是map类型,其他事10个都是map类型
隐含对象名称 | 描 述 |
---|---|
pageContext | 对应于JSP页面中的pageContext对象(注意:取的是pageContext对象。) |
pageScope | 代表page域中用于保存属性的Map对象 |
requestScope | 代表request域中用于保存属性的Map对象 |
sessionScope | 代表session域中用于保存属性的Map对象 |
applicationScope | 代表application域中用于保存属性的Map对象 |
param | 表示一个保存了所有请求参数的Map对象 |
paramValues | 表示一个保存了所有请求参数的Map对象,它对于某个请求参数,返回的是一个string[] |
header | 表示一个保存了所有http请求头字段的Map对象 |
headerValues | 同上,返回string[]数组。注意:如果头里面有“-”,例Accept-Encoding,则要headerValues[“Accept-Encoding”] |
cookie | 表示一个保存了所有cookie的Map对象 |
initParam | 表示一个保存了所有web应用初始化参数的map对象 |
该图来源简书的作者:暗香抚动 链接:https://www.jianshu.com/p/6bc6b14663cf
- pageContext对象
pageContext是PageContext类型!根据2.5所说,它内置了其他8个jsp对象,因此可以用它来干很多事情。
获取request
获取request就可以实现获取请求相关的东西(只要是request对象的方法都可以),比如请求头,请求码,请求行
${pageContext.request.protocol}
${pageContext.request.contentPath} //这个很实用 以后就不必要每次都要写死路径了,下面是一个例子
<form action="${pageContext.request.contextPath}/user/testSpringMVCFileupload" method="post" enctype="multipart/form-data">
其他还有很多,比如获取cookie对象之后就可以设置cookie,读取cookie;获取session对象后就可以读取sessionID了。更多的可以去查看JavaEE的api:https://docs.oracle.com/javaee/7/api/ 或者直接在你的ide中打开智能补全代码就好了
- pageScope requestScope sessionSCope applicationScope
这几个在前面3.1取值顺序已经说了,就不在多说了。直接上个图显示简单的例子
- param paramValues
param: Map<String,String>类型,param对象可以获取参数,不过获取的是request中url?后带的参数,即与request.getParameter()效果一样
ps:如果参数不存在,返回的是空字符串,不会是“null”。这个点与request.getParameter()不一样
paramValues:Map<String,String>类型,与param一样,也是获取到请求参数,但是不同的是它获取的是同一个参数名下多值的参数,返回的是一个String[]数组。比如你在url?后输入name=张三&name=李四,就可以用paramValue获取,返回的就是String[0]=“张三” String[1]="李四"
- header headerValues
header与headerValues跟上面的param/paramValues一样,都是map类型的对象,不同的是header获取的是请求头(不清楚的可以看下图,也可以去我的另一篇博客关于request看一下:https://blog.csdn.net/Vibugs/article/details/86376668)相关的数据,而headerValues不用说了,就是获取请求头多值数据的数组。下面我就介绍header就好了。
红色部分都是请求头的字段
ps:记得如果数据里带有-这种非字母/数字符号的不能使用 . 得使用 [ ' ' ]
- cookie
cookie表示一个保存了所有cookie的map对象 。所以当你想取某个值时,你得这样取 ${cookie.key.value} 其中key是cookie的name,value是cookie的值。当然如果你cookie里有一些非字母/数字的值,记得用[ ' '] 。
- initParam
initParam也是map类型的对象,主要是获取web.xml文件下的<context-param>的参数
<context-param>:说的通俗一点,就是web程序的全局变量(不知道这样说对不对)参考csdn的用户晓梦_知行 的文章https://blog.csdn.net/csdn_ds/article/details/72318557
4.3 使用el自带的函数库表达数据
“EL你已经满18岁了,是时候该自己表达数据了" 因此我们介绍一下el自带的函数库,这些函数库的作用挺多的,我抽一些来讲,其他的看api吧(这个我找了半天就找到一个,里面好像也没怎么描述,推荐你们用ide直接下载吧)
函数的功能包括对字符串的一些操作,例如转换大小写 判断是否有要查询的字符串等等 里面的跟以前String中的方法很相似
String toUpperCase(String input): //转换大写
String toLowerCase(String input): //转换小写
int indexOf(String input, String substring):
boolean contains(String input, String substring): //判断是否包含
boolean containsIgnoreCase(String input, String substring): //判断是否包含 忽略大小写
boolean startsWith(String input, String substring):
boolean endsWith(String input, String substring):
String substring(String input, int beginIndex, int endIndex):
String substringAfter(String input, String substring):hello-world, “-“
substringBefore(String input, String substring):hello-world, “-“
String escapeXml(String input):把字符串的“>”、“<”。。。转义了!
String trim(String input):
String replace(String input, String substringBefore, String substringAfter):
String[] split(String input, String delimiters):
int length(Object obj):可以获取字符串、数组、各种集合的长度!
String join(String array[], String separator):
要想用这个库,还得导包 使用taglib指令导包 <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
下面是一个例子,注释里面是最后的运行结果。这个例子来源于黑马javaWeb视频资源中day13。
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
…
String[] strs = {"a", "b","c"};
List list = new ArrayList();
list.add("a");
pageContext.setAttribute("arr", strs);
pageContext.setAttribute("list", list);
%>
${fn:length(arr) }<br/><!--3-->
${fn:length(list) }<br/><!--1-->
${fn:toLowerCase("Hello") }<br/> <!-- hello -->
${fn:toUpperCase("Hello") }<br/> <!-- HELLO -->
${fn:contains("abc", "a")}<br/><!-- true -->
${fn:containsIgnoreCase("abc", "Ab")}<br/><!-- true -->
${fn:contains(arr, "a")}<br/><!-- true -->
${fn:containsIgnoreCase(list, "A")}<br/><!-- true -->
${fn:endsWith("Hello.java", ".java")}<br/><!-- true -->
${fn:startsWith("Hello.java", "Hell")}<br/><!-- true -->
${fn:indexOf("Hello-World", "-")}<br/><!-- 5 -->
${fn:join(arr, ";")}<br/><!-- a;b;c -->
${fn:replace("Hello-World", "-", "+")}<br/><!-- Hello+World -->
${fn:join(fn:split("a;b;c;", ";"), "-")}<br/><!-- a-b-c -->
${fn:substring("0123456789", 6, 9)}<br/><!-- 678 -->
${fn:substring("0123456789", 5, -1)}<br/><!-- 56789 -->
${fn:substringAfter("Hello-World", "-")}<br/><!-- World -->
${fn:substringBefore("Hello-World", "-")}<br/><!-- Hello -->
${fn:trim(" a b c ")}<br/><!-- a b c -->
${fn:escapeXml("<html></html>")}<br/> <!-- <html></html> -->
4.4 自创el表达数据
感觉不好写出来,直接贴个视频地址你看吧(捂脸) 。步骤大概是 创建一个函数类(这个类里面的方法记得是静态) 然后再创建一个.tld的配置文件(类似下图这种)
5. EL辅助--JSTL
5.1 JSTL是什么
JSTL是apache对EL表达式的扩展,它是个标签语言,只不过跟jsp的内置标签不同,使用时需要导包。
JSTL提供了一个有效的途径,以在JSP页面中嵌入逻辑,而不是直接嵌入Java代码。使用标准标签集,减少了Java代码导致的不连续,从而提高代码的可维护性,并达到应用软件代码开发与用户界面间的关注点分离。
安装JSTL库:如果你的是tomcat
-
下载的二进制发行版,从Apache标准标记库和解压的压缩文件。
-
使用标准的标签库从Jakarta Taglibs分布,复制发行版'lib'目录到应用程序的JAR文件 webapps\ROOT\WEB-INF\lib 目录中。
5.2 JSTL标签库
JSTL有四大库:core fmt sql xml 。下面只讲前两个,因为后面两个优点过时了
导入标签库
core:
<%@taglib prefix="core" url="http://java.sun.com/jsp/jstl/core" %>
ps: prefix是前缀名,可以顺便写
5.2.1 core
下面是core中的标签,这里我们挑一些讲,其他的可以看文档:https://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/c/tld-summary.html
- out set remove
从名字上也可以看出,out就是·输出,功能跟<%= %>一样
set就是设置一个结果在指定域中,默认是page
remove是删除指定域中的数据,也可以不指定,不指定就默认page
<c:out value="abc" /> //输出 abc
<c:set var="name" value="zhangsan" /> //设置一个名为name,值为zhangsan的数据
<c:set var="name" value="lisi" scope="session" /> //设置一个名为name,值为lisi的数据到session域中
<c:remove var="name" value="lisi" /> //在所有域中删除名为name的数据
<c:remove var="name" value="lisi" scope="session" /> //在session域中删除名为name的数据
ps:里面的c是prefix的值,如果你定义为core前缀,那就是<core:out value="abc" />
- url
<c:url>标签将URL格式化为一个字符串,从而进行对URL的操作的标签。jstl标签都是为了简化java脚本才创建出来的,那url标签肯定有其比较方便实用的功能。在介绍功能前介绍URL几个属性
<c:url>标签有如下属性:
属性 | 描述 | 是否必要 | 默认值 |
---|---|---|---|
value | 基础URL | 是 | 无 |
context | 本地网络应用程序的名称 | 否 | 当前应用程序 |
var | 代表URL的变量名 | 否 | Print to page |
scope | var属性的作用域 | 否 | Page |
ps:用了var之后,url便签将不会输出到页面中,而是添加到指定域中(没有指定默认page域)
功能1:当value的值为路径时 在路径前面自动添加项目名
<c:url value="/index.jsp" /> 会输出 /项目名/index.jsp
功能2:当有子标签param有参数时,自动进行URL编码
<c:url value="/index.jsp" >
<c:param name="name" value="张三" />
</c:url>
输出:/项目名/index.jsp?name=%ED%2C //这个张三转码后的值我是瞎打的
实际小例子:html标签嵌套jstl便签
严格来说,不单单是可以嵌套jstl便签,jsp标签也可以嵌套
输出:成为一个超链接, <a href="/项目名/index.jsp" />",下图为客户端上的显示结果
原理:<a href="" />是一个静态标签,是由客户端解析;而<c:url>是动态标签,在发往客户端之前由服务器端解析,因此发到客户端时应该是这样的: <a href="/项目名/index.jsp" />"
- if
if标签取代的就是java片段中的if,一般跟其他标签搭配,最常见的是<c:out>.先介绍属性
<c:if>标签有如下属性:
属性 | 描述 | 是否必要 | 默认值 |
---|---|---|---|
test | 条件 | 是 | 无 |
var | 用于存储条件结果的变量 | 否 | 无 |
scope | var属性的作用域 | 否 | page |
下面给个实例
ps:test属性必须是一个boolean值,如果为true,执行if标签里面的内容
- choose
choose对应着switch语句,case对应着<c:when>,default对应着<c:otherwise>。这些标签都只有一个属性test,这个属性我就不介绍了,也是判断。下面直接给出实例
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>c:choose 标签实例</title>
</head>
<body>
<c:set var="salary" scope="session" value="${2000*2}"/>
<p>你的工资为 : <c:out value="${salary}"/></p>
<c:choose>
<c:when test="${salary <= 0}">
太惨了。
</c:when>
<c:when test="${salary > 1000}">
不错的薪水,还能生活。
</c:when>
<c:otherwise>
什么都没有。
</c:otherwise>
</c:choose>
</body>
</html>
结果:
你的工资为 : 4000
不错的薪水,还能生活。
- forEach forToken
这两个标签代替了java中的for循环和迭代输出,forToken多出一个特点,就是讲输出的数据按照条件分割为子串数组然后迭代。下面是属性介绍
<c:forEach>标签有如下属性:
属性 | 描述 | 是否必要 | 默认值 |
---|---|---|---|
items | 要被循环的信息 | 否 | 无 |
begin | 开始的元素(0=第一个元素,1=第二个元素) | 否 | 0 |
end | 最后一个元素(0=第一个元素,1=第二个元素) | 否 | Last element |
step | 每一次迭代的步长(比如i+2这个2) | 否 | 1 |
var | 代表当前条目的变量名称 | 否 | 无 |
varStatus | 代表循环状态的变量名称 | 否 | 无 |
<c:forTokens>标签与<c:forEach>标签有相似的属性,不过<c:forTokens>还有另一个属性:
属性 | 描述 | 是否必要 | 默认值 |
---|---|---|---|
delims | 分隔符 | 是 | 无 |
ps:item的两个冒号里面千万不能有空格,不然会报bug
实例
模仿for(int i=1; i<=5; i++){system.out.println("i");}
<c:forEach>实例演示
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>c:forEach 标签实例</title>
</head>
<body>
<c:forEach var="i" begin="1" end="5">
Item <c:out value="${i}"/><p>
</c:forEach>
</body>
</html>
结果
Item 1
Item 2
Item 3
Item 4
Item 5
<c:forToken>实例
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>c:forTokens 标签实例</title>
</head>
<body>
<c:forTokens items="google,w3cschool,taobao" delims="," var="name">
<c:out value="${name}"/><p>
</c:forTokens>
</body>
</html>
结果
google
w3cschool
taobao
遍历list、map、数组
遍历List
<% List<String> names = new ArrayList<String>(); names.add("zhangSan"); names.add("liSi"); names.add("wangWu"); names.add("zhaoLiu"); pageContext.setAttribute("ns", names); %> <c:forEach var="item" items="${ns }">[崔1] <c:out value="name: ${item }"/><br/> </c:forEach> |
与遍历数组没有区别!
for(String s : ns) {
…
}
map也一样,只不过是输出的时候输出两个变量而已,一个key,一个value
遍历Map
<% Map<String,String> stu = new LinkedHashMap<String,String>(); stu.put("number", "N_1001"); stu.put("name", "zhangSan"); stu.put("age", "23"); stu.put("sex", "male"); pageContext.setAttribute("stu", stu); %> <c:forEach var="item[备注1] " items="${stu }"> <c:out value="${item.key }: ${item.value }[备注2] "/><br/> </c:forEach> |
[备注1]因为遍历的是Map,所以每一项是Entry类型
[备注2]获取Entry的key和value
还有一个点就是varStatus的使用,这个属性可以获取当前循环到的变量的值
5.2.2 fmt
使用fmt库
<%@taglib prefix="fmt" url="http://java.sun.com/jsp/jstl/fmt" %>
fmt的作用是格式化数据并输出的,下面是fmt库中的标签。
标签 | 描述 |
---|---|
<fmt:formatNumber> | 使用指定的格式或精度格式化数字 |
<fmt:parseNumber> | 解析一个代表着数字,货币或百分比的字符串 |
<fmt:formatDate> | 使用指定的风格或模式格式化日期和时间 |
<fmt:parseDate> | 解析一个代表着日期或时间的字符串 |
<fmt:bundle> | 绑定资源 |
<fmt:setLocale> | 指定地区 |
<fmt:setBundle> | 绑定资源 |
<fmt:timeZone> | 指定时区 |
<fmt:setTimeZone> | 指定时区 |
<fmt:message> | 显示资源配置文件信息 |
<fmt:requestEncoding> | 设置request的字符编 |
这里只介绍时间和数字
- <fmt:formatDate>
<fmt:formatDate>标签有如下属性:
属性 | 描述 | 是否必要 | 默认值 |
---|---|---|---|
value | 要显示的日期 | 是 | 无 |
type | DATE, TIME, 或 BOTH | 否 | date |
dateStyle | FULL, LONG, MEDIUM, SHORT, 或 DEFAULT | 否 | default |
timeStyle | FULL, LONG, MEDIUM, SHORT, 或 DEFAULT | 否 | default |
pattern | 自定义格式模式 | 否 | 无 |
timeZone | 显示日期的时区 | 否 | 默认时区 |
var | 存储格式化日期的变量名 | 否 | 显示在页面 |
scope | 存储格式化日志变量的范围 | 否 | 页面 |
直接上例子
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>JSTL fmt:dateNumber 标签</title>
</head>
<body>
<h3>日期格式化:</h3>
<c:set var="now" value="<%=new java.util.Date()%>" />
<p>日期格式化 (1): <fmt:formatDate type="time" //日期格式化 (1): 11:19:43
value="${now}" /></p>
<p>日期格式化 (2): <fmt:formatDate type="date" //日期格式化 (2): 2016-6-26
value="${now}" /></p>
<p>日期格式化 (3): <fmt:formatDate type="both" //日期格式化 (3): 2016-6-26 11:19:43
value="${now}" /></p>
<p>日期格式化 (4): <fmt:formatDate type="both" //日期格式化 (4): 16-6-26 上午11:19
dateStyle="short" timeStyle="short"
value="${now}" /></p>
<p>日期格式化 (5): <fmt:formatDate type="both" //日期格式化 (5): 2016-6-26 11:19:43
dateStyle="medium" timeStyle="medium"
value="${now}" /></p>
<p>日期格式化 (6): <fmt:formatDate type="both" //日期格式化 (6): 2016年6月26日 上午11时19分43秒
dateStyle="long" timeStyle="long"
value="${now}" /></p>
<p>日期格式化 (7): <fmt:formatDate pattern="yyyy-MM-dd" //日期格式化 (7): 2016-06-26
value="${now}" /></p>
</body>
</html>
- <fmt:formatNumber>
fmtmatNumber用来解析数字,百分数,货币
<fmt:parseNumber>标签有如下属性:
属性 | 描述 | 是否必要 | 默认值 |
---|---|---|---|
value | 要解析的数字 | 否 | Body |
type | NUMBER,,CURRENCY,或 PERCENT | 否 | number |
parseLocale | 解析数字时所用的区域 | 否 | 默认区域 |
integerOnly | 是否只解析整型数(true)或浮点数(false) | 否 | false |
pattern | 自定义解析模式 | 否 | 无 |
timeZone | 要显示的日期的时区 | 否 | 默认时区 |
var | 存储待解析数字的变量 | 否 | Print to page |
scope | var属性的作用域 | 否 | page |
pattern属性与<fmt:formatNumber>标签中的pattern有相同的作用。在解析时,pattern属性告诉解析器期望的格式。
例子:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>JSTL fmt:parseNumber 标签</title>
</head>
<body>
<h3>数字解析:</h3>
<c:set var="balance" value="1250003.350" />
<fmt:parseNumber var="i" type="number" value="${balance}" />
<p>数字解析 (1) : <c:out value="${i}" /></p>
<fmt:parseNumber var="i" integerOnly="true"
type="number" value="${balance}" />
<p>数字解析 (2) : <c:out value="${i}" /></p>
</body>
</html>
结果:
数字解析:
数字解析 (1) : 1250003.35
数字解析 (2) : 1250003