河软CSDN乐知学院
学员周学习总结
姓名 | 张侃 | 周次 | 11 | 方向 | Java | ||||||||||||||||||||||||||||||||||||||||||||||||
内 容 | 本周学习知识点: EL表达式简介 面向对象的程序设计模式 自定义JSP标签 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
本周学习收获: EL表达式概述 • EL表达式是为了便于获取数据而定义的一种语言,JSP 2.0之后才成为一种标准。下面的示例是一个简单的EL表达式: <%@ page contentType="text/html;charset=UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN"> <html> <body> ${stuno+ 1} <br> </body> </html> EL表达式的基本语法 • EL表达式的出现让Web的显示层发生了大的变革,EL表达式用于获取数据,在JSP 2.0之后成为一种标准,是由JSP 标准标签库专家组和JSP 2.0 专家组开发。 • EL表达式的语法格式:${标识符} • 在JSP页面中使用的形式,通知JSP引擎调用pageContext.findAttribute()方法,以标识符为关键字从各个域对象中获取对象。如果域对象中不存在标识符所对应的对象,则返回结果为“”(注意,不是null)。 语法结构 • JSP EL用于以下情形 – 静态文本 – 标准标签和自定义标签(可以作为元素属性的值,也可以在自定义或者标准动作元素的内容中使用) – EL不能在脚本元素中使用 []与.运算符 • EL提供(.)和([])两种运算符来存取数据,即使用点运算符(.)和方括号运算符([])。 – 点运算符和方括号运算符可以实现某种程度的互换,如${student.name}等价于${student [“name”]}。 • 当要存取的属性名称中包含一些特殊字符,如.或?等并非字母或数字的符号时,就一定要使用[]。例如${student.name }应当改为${student[“name”] }。 • 如果要动态取值,就可以用[]来做,而.无法做到动态取值。例如${sessionScope.student[data]}中data是一个变量。 变量 • EL存取变量数据的方法很简单,例如${username}。它的意思是取出某一范围中名称为username的变量。 • 属性范围在EL中的名称如表 文字常量 • 一个EL表达式包含变量、文字常量、操作符。文字常量主要包括字符串、数字和布尔值、还有NULL,其中 – 字符串是由任何由单引号或双引号引起来的一串字符。 – 数字常量包括整型、浮点型,整型表示十进制、十六进制和八进制类型的值,浮点型与Java类似,可以包含任何正的或者负的浮点数。 – 布尔型包括true和false。 操作符 • EL表达式的操作符主要有 – 算术运算符 – 关系运算符 – 逻辑运算符 – 验证运算符empty – 条件运算符
EL表达式的隐式对象 • 与作用范围有关的EL隐含对象包含有:pageScope、requestScope、sessionScope和applicationScope – 它们可以读取使用JSP内置对象pageContext、request、session以及application的setAttribute()方法所设定的对象的数值-----即getAttribute(String name),却不能取得其他相关信息。 – 例如,要取得session中储存的一个username属性的值,可以利用下面的方法:session.getAttribute("username") – 在EL中则使用下面的方法:${sessionScope.username}即,通知JSP引擎调用pageContext.findAttribute()方法,以标识符为关键字从各个域对象中获取对象。如果域对象中不存在标识符所对应的对象,则返回结果为“”(注意,不是null)。 • 与输入有关的隐含对象有两个,即param和paramValues,它们是EL中比较特别的隐含对象。例如,要取得用户的请求参数时,可以利用下列方法: – request.getParameter(Stringname) – request.getParameterValues(Stringname) • 在EL中则可以使用param和paramValues两者来取得数据: – ${param.name} – ${paramValues.name} 其他隐式对象 • cookie – 用来取得使用者的cookie值,例如在cookie中设定了username属性值,可以使用${cookie.username.value}来取得属性值。 • header和headerValues – 读取请求的头数据,使用header或headerValues内置对象,例如${header[“User-Agent”]},headerValues则用来取得所有的头信息,等价于调用request.getHeaders()方法。 • initParam – initParam用来读取设置在web.xml中的参数值。例如${initParam.repeat},等价于:(String)application.getInitParameter(“repeat”); 或 • pageContext – pageContext用于取得其他有关用户要求或页面的详细信息 ${pageContext.request.queryString}取得请求的参数字符串 ${pageContext.request.requestURL} 取得请求的URL,不包括参数字符串 ${pageContext.request.contextPath} 服务的web application 的名称 ${pageContext.request.method} 取得HTTP 的方法(GET、POST) ${pageContext.request.protocol} 取得使用的协议(HTTP/1.1、HTTP/1.0) ${pageContext.request.remoteUser} 取得用户名称 ${pageContext.request.remoteAddr} 取得用户的IP 地址 ${pageContext.session.new} 判断session 是否为新的 ${pageContext.session.id} 取得session 的ID ${pageContext.servletContext.serverInfo} 取得主机端的服务信息 禁用 EL • 在JSP 2.0中默认是启用EL表达式的,但如果在JSP页面中使用了与JSP EL标记符相冲突的其他技术,可以通过使用page指令的isELIgnored属性来忽略JSP EL的标识符。 – <%@page isELIgnored="true|false"%> • true:表示忽略对EL表达式进行计算。 • false:表示计算EL表达式。 – isELIgnored默认为false。 • 还可以修改web.xml来决定当前的web应用不使用JSP EL。 <jsp-config> <jsp-property-group> <url-pattern>*.jsp</url-pattern> <el-ignored>true</el-ignore> </jsp-property-group> </jsp-config> Web.xml中的<el-ignored>标记用来预设所有JSP网页是否使用JSP EL,如果web.xml和page制定都进行了设定,page指令的设定优先级要高。 EL主要作用: • 获取数据: – EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域中检索java对象、获取数据。(某个web域中的对象,访问javabean的属性、访问list集合、访问map集合、访问数组) • 执行运算: – 利用EL表达式可以在JSP页面中执行一些基本的关系运算、逻辑运算和算术运算,以在JSP页面中完成一些简单的逻辑运算。${user==null} • 获取web开发常用对象 – EL 表达式定义了一些隐式对象,利用这些隐式对象,web开发人员可以很轻松获得对web常用对象的引用,从而获得这些对象中的数据。 获取数据 • 使用EL表达式获取数据语法:“${标识符}” • EL表达式语句在执行时,会调用pageContext.findAttribute方法,用标识符为关键字,分别从page、request、session、application四个域中查找相应的对象,找到则返回相应对象,找不到则返回”” (注意,不是null,而是空字符串)。 • EL表达式也可以很轻松获取JavaBean的属性,或获取数组、Collection、Map类型集合的数据,例如: • ${user.address.city} • ${user.list[0]}:访问有序集合某个位置的元素 • ${map.key} :获得map集合中指定key的值 • 结合JSTL的foreach标签,使用EL表达式也可以很轻松迭代各种类型的数组或集合,示例: • 迭代数组 • 迭代collection类型集合 • 迭代map类型集合 n 面向对象软件开发领域中,设计模式包括一些规则来完成一定任务。设计模式针对一些特定的问题,提出一种解决方案。 n 常用的面向对象设计模式有4种: n Factory模式、Singleton模式、Facade模式和MVC架构模式。 JSP设计模式 n SUN公司推出JSP技术后,同时也推荐了两种web应用程序的开发模式,一种是JSP+JavaBean模式,一种是Servlet+JSP+JavaBean模式。 n JSP设计模式包括两个: n (1)Model1,JSP+JavaBean设计模式 n (2)Model2,MVC设计模式 模式一JSP+JavaBean模式 n 在这种模式中,JSP页面独自响应请求并将处理结果返回客户,所有的数据库操作通过JavaBean来实现。 n 大量地使用这种模式,常会导致在JSP页面中嵌入大量的Java代码,当需要处理的商业逻辑非常复杂时,这种情况就会变得很糟糕。大量的Java代码使得JSP页面变得非常臃肿。前端的页面设计人员稍有不慎,就有可能破坏关系到商业逻辑的代码。 n 这种情况在大型项目中经常出现,造成了代码开发和维护的困难,同时会导致项目管理的困难。因此这种模式只适用于中小规模的项目。 n JSP+JavaBean模式适合开发业务逻辑不太复杂的web应用程序,这种模式下,JavaBean用于封装业务数据,JSP即负责处理用户请求,又显示数据。 模式二 MVC模式 n “MVC”模式即是:“Model-View-Controller”模式。在这种模式中,通过JSP技术来表现页面,通过Servlet技术来完成大量的事务处理工作,实现用户的商业逻辑。 n 在这种模式中,Servlet用来处理请求的事务,充当了控制器(Controller即“C”)的角色,Servlet负责响应客户对业务逻辑的请求并根据用户的请求行为,决定将哪个JSP页面发送给客户。JSP页面处于表现层,也就是视图(View即“V”)的角色。JavaBean则负责数据的处理,也就是模型(Model即“M”)的角色 n Servlet+JSP+JavaBean(MVC)模式适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp负责数据显示,javabean负责封装数据。 Servlet+JSP、JavaBean模式程序各个模块之间层次清晰,web开发推荐采用此种模式。 MVC架构 n Model-View-Controller架构模式是80年代中期在Smalltalk-80 GUI(一种经典的面向对象程序设计语言)实验室发明的。 n 根据MVC模式,一个软件应该将商务逻辑(Model)和显示(View)分开。分开有许多好处,最主要的有两个方面: n 1、同一的商务逻辑层(Model)可能会对应多个显示层(View),如果商务逻辑层和显示层放在一起的话,再添加一个显示层的时候就会极大的增加组件的复杂性。一个商务逻辑对着两个显示层的例子是:银行的帐户的商务逻辑层对应ATM和Internet两个显示层。 n 2、通常情况下,每次修改显示层的时候一般并不需要修改商务逻辑层。 MVC模式 三层架构思想 MVC在JSP中的实现模型 n 目前有两种实现模型: n (1)基于Bean的MVC模型。 Bean可以利用JavaBean实现,也可以利用EJB来实现,分别构成的系统是: ①JavaBean(M)+JSP(V)+Servlet ②EJB(M)+JSP(V)+Servlet(C)实现。 n (2)基于Stucts的MVC模型。 ①Struts是Apache组织的一个项目,像其他的Apache组织的项目一样,它也是开放源码项目。 ②Struts是一个比较好的MVC框架提供了对开发MVC系统的底层支持,它采用的主要技术是Servlet,JSP和custom tag library。 ③Struts 是一组相互协作的类、Servlet 和 JSP 标记,它们组成一个可重用的MVC设计。这个定义表示Struts是一个框架,而不是一个库,但Struts也包含了丰富的标记库和独立于该框架工作的实用程序类。Struts的基本结构如图所示。 自定义JSP标签 自定义JSP标签概述 • 自定义JSP标签就是程序员定义的一种JSP标签,这种标签把那些信息显示逻辑封装在一个单独的Java类中,通过一个XML文件来描述它的使用。当页面中需要使用类似的显示逻辑时,就可以在页面中插入这个标签,从而完成相应的功能。 • 使用自定义标签,可以分离程序逻辑和表示逻辑,将Java代码从HTML中剥离,便于美工维护页面;自定义标签也提供了可重用的功能组件,能够提高工程的开发效率。 • 自定义标签主要用于移除Jsp页面中的java代码。 执行过程 • 当一个含有自定义标签的JSP页面被JSP引擎(Web容器)转译成Servlet时,JSP引擎遇到自定义的标签,会把这个自定义标签转化成对一个称为“标签处理类”的调用。之后,当这个JSP页面被执行时,JSP引擎就会调用这个“标签处理类”对象,并执行其内部定义的相应操作方法,从而完成相应的功能。 开发流程 • 使用Java处理类来开发自定义JSP标签时,主要分为下几个步骤。 – 创建标签的处理类(Tag Handle Class)。这个类实现Tag接口,用来定义标签的行为,并在JSP引擎遇到自定义标签时调用执行。 – 创建标签库描述(tld)文件(Tag Library Descriptor File),在tld文件中对标签处理器类进行描述。 – 在JSP文件中用taglib指令引入标签库,然后使用标签库描述文件中指定的标签名来使用它。 Tag接口的执行流程 • JSP引擎将遇到自定义标签时,首先创建标签处理器类的实例对象,然后按照JSP规范定义的通信规则依次调用它的方法。 1、public voidsetPageContext(PageContext pc), JSP引擎实例化标签处理器后,将调用setPageContext方法将JSP页面的pageContext对象传递给标签处理器,标签处理器以后可以通过这个pageContext对象与JSP页面进行通信。 2、public void setParent(Tag t),setPageContext方法执行完后,WEB容器接着调用的setParent方法将当前标签的父标签传递给当前标签处理器,如果当前标签没有父标签,则传递给setParent方法的参数值为null。 3、public int doStartTag(),调用了setPageContext方法和setParent方法之后,WEB容器执行到自定义标签的开始标记时,就会调用标签处理器的doStartTag方法。 4、public int doEndTag(),WEB容器执行完自定义标签的标签体后,就会接着去执行自定义标签的结束标记,此时,WEB容器会去调用标签处理器的doEndTag方法。 5、public void release(),通常WEB容器执行完自定义标签后,标签处理器会驻留在内存中,为其它请求服务器,直至停止web应用时,web容器才会调用release方法。 自定义标签功能扩展 • 开发人员在编写Jsp页面时,经常还需要在页面中引入一些逻辑,例如: – 控制jsp页面某一部分内容是否执行。 – 控制整个jsp页面是否执行。 – 控制jsp页面内容重复执行。 – 修改jsp页面内容输出。 • 自定义标签除了可以移除jsp页面java代码外,它也可以实现以上功能。 • tld文件中的四种标签体类型 – EMPTY JSP scriptless tagdepentend JSP标签API • JSP 1.1和1.2规范中常用的接口主要有以下3个。 – Tag:此接口定义对于所有标签处理类都需要实现的方法。 – IterationTag:此接口扩展了Tag接口,增加了控制重复执行标签主体的方法。 – BodyTag:此接口扩展了IterationTag接口,并增加了访问和操作标签主体内容的方法。 标签库描述符 • 标签库描述符文件是一个以“.tld”结尾的标准XML文档,用来记录一个标签库内拥有哪些标签、每个标签包含哪些属性。 • 以下是一个JSP 2.0规范的标签库描述文件的内容: • <taglib>元素是标签库描述符的根元素,它包含12个子元素,详细介绍如下。 – (1)<description>:标签库的一个文本描述。 – (2)<tlib-version>:指定标签库的版本。 – (3)<short-name>:为标签定义简短的名字,在taglib指令中可作为首选的前缀名使用。 – (4)<uri>:定义一个URI,用于唯一地标识此标签库。 – (5)<tag>:用于指定自定义标签的相关信息。 – (6)<display-name>:为标签库指定一个简短的别名。 – (7)<small-icon>:为标签库指定大小为16×16的小图标(gif或jpeg格式),该图标可在图形界面工具中显示。 – (8)<large-icon>:为标签库指定大小为32×32的大图标(gif或jpeg格式),该图标可在图形界面工具中显示。 – (9)<validator>:为标签库提供一个验证器。 – (10)<listener>:为标签库提供一个监听器。 – (11)<tag-file>:用于描述标签文件。 – (12)<function>:用于指定在表达式语言中使用的函数。 传统标签的开发 • 在开发传统标签之前,需要了解清楚两个支持类(TagSupport和BodyTagSupport)的生命周期。 TagSupport类的生命周期可以用图来表示 BodyTagSupport类的生命周期 用BodyTagSupport类开发自定义标签 • BodyTagSupport类中增加了两个方法: – setBodyContent(BodyContent bc):容器在执行这个标签处理类的实例时,将调用该方法,把标签主体返回的内容缓存在BodyContent类的实例中。BodyContent除了从父类JspWriter继承提供用于向响应体中写入文本的方法,还提供了用于获取它缓冲的标签体内容。 – doInitBody():计算标签主体之前调用该方法进行初始化共,可以向bodyContent对象中写入初始内容,这些内容会放置在标签主体内容之前。 • BodyContent类专门用于缓存标签主体返回的内容,包括静态文本以及由嵌套标签或脚本元素所创建的动态内容。 简单标签 • 由于传统标签使用三个标签接口来完成不同的功能,显得过于繁琐,不利于标签技术的推广, SUN公司为降低标签技术的学习难度,在JSP 2.0中定义了一个更为简单、便于编写和调用的SimpleTag接口来实现标签的功能。实现SimpleTag接口的标签通常称为简单标签。简单标签共定义了5个方法: – setJspContext方法 – setParent和getParent方法 – setJspBody方法 – doTag方法 SimpleTag方法介绍 • setJspContext方法 – 用于把JSP页面的pageContext对象传递给标签处理器对象 • setParent方法 – 用于把父标签处理器对象传递给当前标签处理器对象 • getParent方法 – 用于获得当前标签的父标签处理器对象 • setJspBody方法 – 用于把代表标签体的JspFragment对象传递给标签处理器对象 • doTag方法 – 用于完成所有的标签逻辑,包括输出、迭代、修改标签体内容等。在doTag方法中可以抛出javax.servlet.jsp.SkipPageException异常,用于通知WEB容器不再执行JSP页面中位于结束标记后面的内容,这等效于在传统标签的doEndTag方法中返回Tag.SKIP_PAGE常量的情况。 SimpleTag接口方法的执行顺序 • 当web容器开始执行标签时,会调用如下方法完成标签的初始化 – WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象。 – WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。注意,只有在标签存在父标签的情况下,WEB容器才会调用这个方法。 – 如果调用标签时设置了属性,容器将调用每个属性对应的setter方法把属性值传递给标签处理器对象。如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。 – 如果简单标签有标签体,容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来。 • 执行标签时: – 容器调用标签处理器的doTag()方法,开发人员在方法体内通过操作JspFragment对象,就可以实现是否执行、迭代、修改标签体的目的。 JspFragment类 • javax.servlet.jsp.tagext.JspFragment类是在JSP2.0中定义的,它的实例对象代表JSP页面中的一段符合JSP语法规范的JSP片段,这段JSP片段中不能包含JSP脚本元素。 • WEB容器在处理简单标签的标签体时,会把标签体内容用一个JspFragment对象表示,并调用标签处理器对象的setJspBody方法把JspFragment对象传递给标签处理器对象。JspFragment类中只定义了两个方法,如下所示: • getJspContext方法 – 用于返回代表调用页面的JspContext对象. • public abstract voidinvoke(java.io.Writer out) – 用于执行JspFragment对象所代表的JSP代码片段 – 参数out用于指定将JspFragment对象的执行结果写入到哪个输出流对象中,如果传递给参数out的值为null,则将执行结果写入到JspContext.getOut()方法返回的输出流对象中。(简而言之,可以理解为写给浏览器) invoke方法详解 • JspFragment.invoke方法是JspFragment最重要的方法,利用这个方法可以控制是否执行和输出标签体的内容、是否迭代执行标签体的内容或对标签体的执行结果进行修改后再输出。例如: – 在标签处理器中如果没有调用JspFragment.invoke方法,其结果就相当于忽略标签体内容; – 在标签处理器中重复调用JspFragment.invoke方法,则标签体内容将会被重复执行; – 若想在标签处理器中修改标签体内容,只需在调用invoke方法时指定一个可取出结果数据的输出流对象(例如StringWriter),让标签体的执行结果输出到该输出流对象中,然后从该输出流对象中取出数据进行修改后再输出到目标设备,即可达到修改标签体的目的。 在TLD中描述标签属性attribute | |||||||||||||||||||||||||||||||||||||||||||||||||||||
学习总结: EL表达式的简单入门,面向对象程序设计模式的了解以及JSP自定义标签的学习。 | |||||||||||||||||||||||||||||||||||||||||||||||||||||
对授课教师意见建议: 希望老师能带领我们学习实战开发项目,让我们能更好的体会学习。 |