用来通知翻译引擎,如何翻译当前的JSP
[ language="java" ]当前JSP使用的开发语言
[ extends="package.class" ]当前jsp翻译成servlet后要继承的类,注意此值必须是一个servlet的子类,一般情况下不要改
[ import="{package.class | package.*}, ..." ]导入需要使用到的包 java.lang.*;javax.servlet.*;javax.servlet.jsp.*;javax.servlet.http.*;
[ session="true | false" ]用来指定当前页面是否使用session,如果设置为true,则翻译过来的servlet中将会有对session对象的引用,于是可以直接在jsp中使用session隐式对象。但是这将导致一旦访问jsp就会调用request.getSession()方法,可能导致不必要的空间浪费。如果确定jsp中不需要session可以设为false
[ buffer="none | 8kb | sizekb" ] out隐式对象所使用的缓冲区的大小
[ autoFlush="true | false" ] out隐式对象是否自动刷新缓冲区,默认为true,不需要更改
[ isThreadSafe="true | false" ]翻译过来的servlet是否实现SingleThreadModel
[ errorPage="relative_url" ]如果页面出错,将要跳转到的页面,除了在jsp中使用此属性指定错误页面外也可以在web.xml中配置整个web应用的错误页面,如果两个都设置则jsp中的此属性起作用
[ isErrorPage="true | false" ]如果设置此属性为true,翻译过来的servlet中将含有Exception隐式对象,其中封装的就是上一个页面中抛出的异常对象
[ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ]和jsp乱码相关的指令,用来指定jsp输出时,设置的Content-Type响应头用来指定浏览器打开的编码
[ pageEncoding="characterSet | ISO-8859-1" ]服务器翻译jsp时使用的编码集.如果向防止jsp乱码,应该保证文件的保存编码和jsp翻译成servlet用的编码以及输出到浏览器后浏览器打开的编码一致.此属性一旦设置好,翻译引擎会间接帮我们设置content-type属性.
[ isELIgnored="true | false" ]当前页面是否使用el表达式,设置为false时表示启用el,j2ee4.0开始默认支持,j2ee4.0一下做开发时,如果要使用el表达式,需将此属性设置为fals
<%@ incluede file=""%>静态引入其他页面的内容
*静态引入:
在源文件级别进行合并,多个jsp生成一个servlet,最终由这一个servlet生成响应。推荐使用。
*动态引入:
在运行时将多个输出进行合并,多个jsp分别生成多个servlet,最终由这多个servlet生成响应,组成一个输出流,提供响应。执行效率没有静态引入高。
<%@ taglib uri="" prefix=""%>用来引入标签库。
uri指定被引入.tld文件的名称空间
prefix 对该名称空间的一个缩写
在jsp翻译成Serlvet时,jsp翻译引擎在翻译过来的Serlvet中,预先定义了一些变量,可以不需要在JSP中预先定义就可以直接使用,共有9个,统称为jsp的九大隐式对象。分别是:
page
config
application
response
request
session
out
exception
pageContext
其中其他的七个我们都学习过了,只需要再学习一下out和pageContext即可。
可以将他理解成response.getWriter()获得的PrintWriter.
它自带一个缓冲区,其大小收page指令中的buffer的设定限制。当缓冲区满或缓冲区被关闭或当前jsp页面结束,则此缓冲区中的内容将被刷新到response.getWriter()的缓冲区中。
(1)作为入口对象获取其它八大隐式对象。
getException方法返回exception隐式对象
getPage方法返回page隐式对象
getRequest方法返回request隐式对象
getResponse方法返回response隐式对象
getServletConfig方法返回config隐式对象
getServletContext方法返回application隐式对象
getSession方法返回session隐式对象
getOut方法返回out隐式对象
(2)作为入口对象获取其他域中的数据
pageContext操作所有域中属性的方法
getAttribute(String name,int scope)
setAttribute(String name, Object value,int scope)
removeAttribute(String name,int scope)
其中pageContext中代表域的常量:
PageContext.APPLICATION_SCOPE
PageContext.SESSION_SCOPE
PageContext.REQUEST_SCOPE
PageContext.PAGE_SCOPE
findAttribute方法:
在四大域中搜寻属性,搜寻的顺序是page域、request域、session域、application域,从小域到大域开始搜索,如果搜索到就直接获取该值,如果所有域中都找不到,返回一个null
(3)作为域对象使用
作用的范围:真个jsp页面,是四大作用域中最小的一个。
生命周期:当对jsp的请求开始时生成,当响应结束时销毁。
作用:在jsp页面范围内共享数据
(4)跳转到其他资源
其身上提供了forward和
在之前我们编写的程序中,JSP页面中大量的写入了java代码,我们发现在jsp页面中嵌入大量java代码会造成页面的可读性、可维护性下降。
如图-1所示:
图-1
那么该如何解决这种问题呢?sun公司考虑到这种问题,为我们提供了JSP标签技术,通过标签替换掉jsp页面中的java代码,从而提高jsp页面的可读性、可维护性。
JSP中的标签技术我们介绍如下四种:
JSP标签
EL表达式
JSTL标签
自定义标签
由sun公司提供,属于jsp规范中的内容,不需要引入第三方标签库,我们介绍其中的三个。
EL 全名为Expression Language,用来替代<%= %>脚本表达式。
在j2ee4.0以前默认是不支持el,如果需要需要指定page指令[isELIgnored="true | false" ]为false,J2EE4.0后默认支持el
EL具有获取数据、执行运算、获取常用开发对象、调用java方法这四方面的功能
EL支持数据、字符串、布尔类型的常量
${23}
${“asdf”}
${true}
${propName}在四个域中搜寻proName属性,输出该值到输出流中
搜寻域的顺序为由小到大。
如果四大域中都搜寻不到,则什么都不输出。
${pageScope/requestScope/sessionScope/applicationScope.proName}
获取指定域中的属性
${attr[0]}获取域中的数组的指定元素
${list[0]}获取list中的指定位置元素
${map.keyName}获取map中指定键的值
${bean.propName}获取javaBean的属性,可以认为是调用了javaBean的getXXX方法,
最重要的一个应用场景:
在写路径的时候最好不要把web应用名称写死,java中应该用request.getContextPath去获取,jsp中就用el获取:
${pageContext.request.contextPth}
(1)和[]区别:使用点的地方都可以用中括号,如果属性名是数字或包含特殊符号(.-)就必须使用中括号。例子:${map["first.name"]}
(2)EL只能获取不能设置
(3)EL只能获取不能遍历
${3+2}
${“3”+2}
${“3”+2}
${1+”a”}
所有参与元算的元素都会被转成数字,如果不能转就报错,空元素参与运算当作没参与。
如图-2所示:
图-2
${3 > 2}
${3 gt 2}
如图-3所示:
图-3
${3>2 && 4>5}
empty/not empty判断对象是否为null,判断集合是否为空,数组长度是否为0,判断字符串是否为空串,判断域中是否没有任何属性。
${name == null ? "张三" : name;}
El中预先定义了11个内置对象,不需要提前存入域中个,可以直接在el使用。
如图-4、图-5所示:
图-4
图-5
代表pageContext对象,通过他可以获取其他八大隐式对象
pageScope:代表page域,可以用来获取page域中的属性
reqeustScope:代表reqeust域,可以用来获取reqeust域中的属性
sessionScope:代表session域,可以用来获取session域中的属性
applicationScope:代表application域,可以用来获取application域中的属性
param 代表请求参数组成的map集合${param.userName}
paramValues 代表请求参宿组成的map集合,但是此集合的value是String[],用来获取一名多值的param
header 获取请求头组成的map
headerValues 获取请求头组成的map但是value是一个String[],用来获取一名多值的head
cookie :获取cookie组成的map对象,键为cookie的名,值为Cookie对象。
${cookie.cookieName.cookieValue}
initParam 以map封装的web.xml中配置的整个web应用的初始化参数
略。
JSTL全称为JavaServer Pages Standard Tag Library
由JCP(Java Community Process)指定标准
是提供给 Java Web 开发人员一个标准通用的标签函数库
可以和 EL 配合来取代传统直接在页面上嵌入 Java 程序(Scripting)的做法,以提高程序可读性、维护性和方便性
在javaee4.0需要导入JSTL相关的jar包,在javaee5.0开始,默认已经包含了此jar包。还要需要用<%@taglib%>指令引入标签库
核心标签库 (core) --- c
国际化标签 fmt
数据库标签 sql --Servlet
XML标签 xml
JSTL函数(EL函数) el
如图-6所示:
图-6
输出固定值
如图-7所示:
图-7
标签用于把某一个对象存在指定的域范围内,或者设置Web域中的java.util.Map类型的属性对象或JavaBean类型的属性对象的 属性。
在指定域中增加、修改属性
标签用于删除各种Web域中的属性
标签用于捕获嵌套在标签体中的内容抛出的异常,其语法格式如下:
如图-8所示:
图-8
此标签可以构造简单的“if-then”结构的条件表达式 。
标签用于指定多个条件选择的组合边界,它必须与
标签用于对一个集合对象中的元素进行循环迭代操作,或者按指定的次数重复迭代执行标签体中的内容。
如图-9所示:
图-9
varStatus属性,如图-10所示:
图-10
实验:遍历10到100的偶数,如果数字所在的位置是3的倍数,显示成红色
用来浏览一字符串中所有的成员,其成员是由定义符号所分隔的
在JSP页面进行URL的相关操作时,经常要在URL地址后面附加一些参数。
标签,实现include操作,如图-11所示:
图-11
如图-12所示:
图-12
标签用于在JSP页面中构造一个URL地址,其主要目的是实现URL重写。URL重写就是将会话标识号以参数形式附加在URL地址后面
此标签用于实现请求重定向。如图-13所示:
图-13
虽然有第三方组织提供了很多标签,但是这些都是一些通用标签,开发中常常需要根据业务需求使用jsp页面,这个时候通用的标签就不够用了,我们需要自己去开发标签库。
想要开发自定义标签需要两个步骤:
写一个类实现SimpleTag接口
在tld文件中描述该标签,在jsp页面中通过<%@taglib %>引入该标签库使用标签
SimpleTag接口的继承结构如图-14所示:
图-14
我们写一个类实现SimpleTag接口,发现其中包含如下方法:
public void doTag() throws JspException, IOException {
}
public void setParent(JspTag parent) {
}
public JspTag getParent() {
return null;
}
public void setJspContext(JspContext pc) {
}
public void setJspBody(JspFragment jspBody) {
}
当jsp页面执行到自定义标签时,首先创建出自定义标签处理类对象,创建出来后会立即调用setJspContext方法将当前页面的PageContext传入。如果当前标签具有标签体,则将标签的标签体封装到JspFragment对象中调用setJspBody方法,如果没有标签体此方法不执行。如果当前自定义标签有父标签,则调用setParent方法将父标签传入。最后调用doTag方法执行自定义标签的处理逻辑。
所以我们在开发自定义标签时,将核心代码写入doTag方法即可。
更多的时候我们不会直接实现SimpleTag接口而是继承SimpleTagSupport。
SimpleTagSupport实现了SimpleTag接口,对立面的方法都做了实现,实现了setJspContext方法,将JspContext保存成了类的成员,并提供了getJspContext()方法获取该对象。实现了setJspBody(JspFragment)方法,将JspFragment保存成了类的成员,并提供了getJspBody()方法获取该对象。实现了doTag方法,做了空实现,我们作为实现类,只需要覆盖这个方法,在其中编写标签处理代码。
控制标签体不执行:什么都不做标签体默认就不执行
控制标签体执行:获取封装了标签体的JSPFragment对象,执行invoke方法,输出到out输出流中即可
JspFragment fragment = this.getJspBody();
fragment.invoke(this.getJspContext().getOut());
fragment.invoke(null);
控制标签之后的内容执行:什么都不做,就执行
控制标签之后的内容不执行:抛出一个特殊的异常SkipPageException就可以阻止标签之后的内容执行
throw new SkipPageException();
JspFragment fragment = this.getJspBody();
for(int i = 0;i<5 ;i++){
fragment.invoke(null);
}
StringWriter writer = new StringWriter();
JspFragment fragment = this.getJspBody();
fragment.invoke(writer);
String str = writer.toString();
str = str.toUpperCase();
this.getJspContext().getOut().write(str);
tld是专门用来描述自定义标签的文件,可以在其中描述自定义标签。
tld文件必须放置在WEB-INF目录除classes和lib目录外的其他目录下。
其格式如下,如图-15所示:
图-15
其中
在jsp页面中使用<%@taglib %>引入自定义标签。
<%@ taglib uri="http://www.easymall.com/myTag" prefix="myTag" %>
想要开发带有属性的标签,需要做如下两件事:
在自定义标签处理类中定义javabean属性并提供setXxx()方法,如图-16所示:
图-16
在tld文件中描述该属性,如图-17所示:
图-17
其中,描述属性的标签如图-18所示:
图-18
略。
之前的代码十分混乱,如图-19所示:
图-19
用el+jstl改造,如图-20所示:
图-20
经过测试发现显示的用户名是经过URL编码的,而JSTL并没有提供现成的URL解码用的标签,而我们不希望在jsp页面中写java代码,对于这种非常常见的功能,我们可以开发一个自定义标签来进行处理。代码如图-21所示:
图-21
在tld文件中描述该标签,如图-22所示:
图-22
在regist.jsp中引入此tld文件,通过该自定义标签进行URL解码,如图-23所示:
图-23
经过测试,可以正确的显示中文,如图-24所示:
图-24
如图-25所示:
图-25