Lazy loaded image
学习思考
Lazy loaded imageJavaEE——JSP
字数 11165阅读时长 28 分钟
2025-3-16
2025-3-22
type
status
date
slug
summary
tags
category
icon
password

JSP

简介

JSP全称是JavaServer Pages,它和servlet技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。
JSP这门技术的最大的特点在于,写jsp就像在写html,但它相比html而言,html只能为用户提供静态数据,而jsp技术允许在页面中嵌套java代码,为用户提供动态数据;相比servlet而言,servlet很难对数据进行排版,而jsp除了可以用java代码产生动态数据的同时,也很容易对数据进行排版。
不管是JSP还是Servlet,虽然都可以用于开发动态web资源,但由于这2门技术各自的特点,在长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用。
其原因为,程序的数据通常要美化后再输出,让jsp既用java代码产生动态数据,又做美化会导致页面难以维护;让servlet既产生数据,又在里面嵌套html代码美化数据,同样也会导致程序可读性差,难以维护;因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,servlet只负责响应请求产生数据,并把数据通过转发技术带给jsp,数据的显示jsp来做。

语法

  1. jsp模版元素
  1. jsp表达式
  1. jsp脚本片段
  1. jsp注释
  1. jsp指令
  1. jsp标签
  1. jsp内置对象
  1. 如何查找jsp页面中的错误

Jsp模板元素

jsp页面中的HTML内容称之为jsp模版元素;jsp模版元素定义了网页的基本骨架,即定义了页面的结构和外观。

Jsp脚本表达式

jsp脚本表达式(expression)用于将程序数据输出到客户端。
语法:
举例
jsp引擎在翻译脚本表达式时,会将程序数据转成字符串,然后在相应位置用out.print(…)将数据输给客户端。
jsp脚本表达式中的变量或表达式后面不能有分号;。

Jsp脚本片段

jsp脚本片断(scriptlet)用于在jsp页面中编写多行Java代码。
语法:
注意:jsp脚本片断中只能出现java代码,不能出现其它模板元素,jsp引擎在翻译jsp页面中,会将jsp脚本片断中的Java代码将被原封不动地放到Servlet的_jspService方法中。
jsp脚本片断中的Java代码必须严格遵循Java语法,例如,每执行语句后面必须用分号;结束。
在一个jsp页面中可以有多个脚本片断,在两个或多个脚本片断之间可以嵌入文本、HTML标记和其他jsp元素。
举例:
多个脚本片断中的代码可以相互访问,犹如将所有的代码放在一对<%%>之中的情况。如:out.println(x);,单个脚本片断中的Java语句可以是不完整的,但是,多个脚本片断组合后的结果必须是完整的Java语句,例如:

Jsp声明

jsp页面中编写的所有代码,默认会翻译到servlet的service方法中, 而Jsp声明中的java代码被翻译到_jspService方法的外面。
语法:
所以,jsp声明可用于定义jsp页面转换成的Servlet程序的静态代码块、成员变量和方法。
多个静态代码块、变量和函数可以定义在一个jsp声明中,也可以分别单独定义在多个jsp声明中。
jsp隐式对象的作用范围仅限于Servlet的_jspService方法,所以在jsp声明中不能使用这些隐式对象。

Jsp 注释

jsp注释的格式:
jsp引擎在将jsp页面翻译成Servlet程序时,忽略jsp页面中被注释的内容。

Jsp 指令

jsp指令(directive)是为jsp引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理jsp页面中的其余部分。
在jsp2.0规范中共定义了三个指令:
  • page指令
  • include指令
  • taglib指令
jsp指令的基本语法格式:

page指令

page指令用于定义jsp页面的各种属性,无论page指令出现在jsp页面中的什么地方,它作用的都是整个jsp页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个jsp页面的起始位置。
jsp 2.0规范中定义的page指令的完整语法:

通过page指令设置页面的编码

举例:
这个指令的作用就相当于response.setContentType("text/html;charset=gb2312");。
但是这个指令和
的区别是:
  • pageEncoding是jsp文件本身的编码
  • contentType的charset是指服务器发送给客户端时的内容编码
jsp要经过两次的“编码”,第一阶段会用pageEncoding,第二阶段会用utf-8至utf-8,第三阶段就是由Tomcat出来的网页,用的是contentType。
第一阶段是jsp编译成.java,它会根据pageEncoding的设定读取jsp,结果是由指定的编码方案翻译成统一的utf-8格式java源码(即.java),如果pageEncoding设定错了,或没有设定,出来的就是中文乱码。
第二阶段是由javac的Java源码至java byteCode的编译,不论jsp编写时候用的是什么编码方案,经过这个阶段的结果全部是utf-8的encoding的Java源码。
javac用utf-8的encoding读取java源码,编译成utf-8 encoding的二进制码(即.class),这是JVM对常数字串在二进制码(java encoding)内表达的规范。
第三阶段是Tomcat(或其的application container)载入和执行阶段二的来的Java二进制码,输出的结果,也就是在客户端见到的,这时隐藏在阶段一和阶段二的参数contentType就发挥了功效
contentType的设定:
pageEncoding和contentType的预设都是ISO8859-1,而随便设定了其中一个, 另一个就跟着一样了(Tomcat4.1.27是如此);但这不是绝对的,这要看各自JSPC的处理方式,而pageEncoding不等于contentType,更有利亚洲区的文字CJKV系jsp网页的开发和展示,(例pageEncoding=GB2312不等于contentType=utf-8)。
jsp文件不像.java,.java在被编译器读入的时候默认采用的是操作系统所设定的locale所对应的编码,比如中国大陆就是GBK,台湾就是BIG5或者MS950;而一般不管是在记事本还是在ue中写代码,如果没有经过特别转码的话,写出来的都是本地编码格式的内容。所以编译器采用的方法刚好可以让虚拟机得到正确的资料。
但是jsp文件不是这样,它没有这个默认转码过程,但是指定了pageEncoding就可以实现正确转码了。
当同时使用这两个命令时:
这时候就会发现,文件的编码是utf-8,而页面浏览的编码是gb2312,所以说上面的一条指令是专门设置页面浏览的编码的,下面的指令是专门设置文件的保存编码的。

通过page指令导入Java包

jsp引擎自动导入下面的包:
可以在一条page指令的import属性中引入多个类或包,其中的每个包或类之间使用逗号分隔:
上面的语句也可以改写为使用多条page指令的import属性来分别引入各个包或类:

buffer属性

使用这个属性是指定out对象的缓存大小,如果我们想关闭缓冲区的话,只需要设置值为none就可以了。

isThreadSafe 属性

这个属性见名知意,是设置是否线程安全的。
  • isThreadSafe=false模式表示它是以Singleton模式运行;该模式implements了接口SingleThreadMode,该模式同一时刻只有一个实例,不会出现信息同步与否的概念;若多个用户同时访问一个这种模式的页面,那么先访问者完全执行完该页面后,后访问者才开始执行
  • isThreadSafe=true模式表示它以多线程方式运行;该模式的信息同步,需访问同步方法(用synchronized标记的)来实现

session属性

是指不能在本页使用session,也就是在本页面禁用了session,也就是在将jsp翻译成servlet的时候不会传递session对象了

errorPage属性

这个属性是设置服务器端出错之后的错误页面的。
通过这个属性值,设置一个错误页面,当服务器发生错误的时候都会跳转到这个页面中。
转到错误页面使用的是转发技术,所以在书写url地址的时候,那个开始的斜杠代表是当前应用,因为这个地址是给服务器用的。
在web.xml文件中给应用配置一个全局的错误页面
在web.xml文件中可以配置抛出的异常类型所对应的错误页面,也可以配置状态码对应的错误页面,且这里配置的结果的优先级没有errorPage属性配置错误页面的优先级高。

isErrorPages属性

是否开启错误页面,就是控制上面的errorPage属性的作用开关的。

isELIgnored 属性

是否在该页面中忽视EL表达式的功能,这个一般都不去做设置,因为在页面中肯定会使用到EL表达式的。
注意:如果一个指令有多个属性,这多个属性可以写在一个指令中,也可以分开写。
例如:
也可以写作:

include指令

include指令是实现页面包含的,使用include指令来实现页面包含是静态包含。

taglib指令

这个指令作用是引入标签(收JSTL的内容)。

Jsp内置的9个隐式对象

每个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大对象的引用。
这9个对象分别是:
对象
类型
request
HttpServletRequest
response
HttpServletResponse
session
HttpSession
application
servletContext
config
servletConfig
out
JspWriter
exception
Throwable
page
this
pageContext
PageContext
exception是个异常对象,只有当jsp页面中抛出异常的时候,才会有这个对象的产生,否则是不会传递这个对象的。
page对象就是当前对象,即jsp翻译后的servlet对象。

out对象

用于向客户端发送文本数据。
out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。
jsp页面中的out隐式对象的类型为jspWriter,jspWriter相当于一种带缓存功能的PrintWriter,设置jsp页面的page指令的buffer属性可以调整它的缓存大小,甚至可以关闭它的缓存。
只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
  1. 设置page指令的buffer属性关闭了out对象的缓存功能
  1. out对象的缓冲区已满
  1. 整个jsp页面结束
实例:
访问jsp页面可以看到,是先向浏览器中输出bbb,然后在输出aaa,原因是out对象是jspWriter,是带有缓冲的。
看下图解释:
所以给浏览器输出数据的时候一定要注意,最好不要同时使用这两个对象,一般只是用out对象进行输出数据。

pageContext对象

pageContext对象是jsp技术中最重要的一个对象,它代表jsp页面的运行环境,这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象,这个域对象的生命周期最短,作用域最小,它的作用域就是当前的jsp页面,当然它可以用来保存数据;并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。
  • getException方法返回exception隐式对象
  • getPage方法返回page隐式对象
  • getRequest方法返回request隐式对象
  • getResponse方法返回response隐式对象
  • getServletConfig方法返回config隐式对象
  • getServletContext方法返回application隐式对象
  • getSession方法返回session隐式对象
  • getOut方法返回out隐式对象

pageContext封装其它8大内置对象的意义

只需要传递一个pageContext对象,就可以操作其他多个对象。

pageContext对象中的操作域中数据的方法

pageContext对象中还封装了访问其它域的方法(和上面的方法不同之处就是多了一个参数,这个参数是可以直接指定相应的域)。
代表各个域的常量:
findAttribute方法是在所有的域中查找数据,查找顺序是:pageContext->request->session->ServletContext,如果查找不到相应的数据的话,就返回一个空字符串。
PageContext类中定义了一个forward方法和两个include方法来分别简化和替代RequestDispatcher.forward方法和include方法。
传递给这些方法的资源路径都只能是相对路径,如果路径以/开头,表示相对于当前web应用程序的根目录,否则,表示相对于当前jsp所映射到的访问路径。

JSP标签库

虽然希望jsp页面仅用作数据显示模块,不要嵌套任何java代码引入任何业务逻辑,但在实际开发中不引入一点业务逻辑是不可能的,引入业务逻辑会导致页面出现难看的Java代码怎么办?
Sun公司允许用户开发自定义标签封装页面的Java代码,以便jsp页面不出现一行java代码,当然Sun公司在jsp页面中也内置了一些标签(这些标签叫做jsp标签),开发人员使用这些标签可以完成页面的一些常用业务逻辑。
jsp标签也称之为Jsp Action(jsp动作)元素,它用于在jsp页面中提供业务逻辑功能。
  • <jsp:include>标签
  • <jsp:forward>标签
  • <jsp:param>标签
  • <jsp:useBean>标签
  • <jsp:setProperty>标签
  • <jsp:getProperty>标签

<jsp:include>标签

<jsp:include>标签用于把另外一个资源的输出内容插入进当前jsp页面的输出内容之中,这种在jsp页面执行时的引入方式称之为动态引入。
语法:
page属性用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。
flush属性指定在插入其他资源的输出内容时,是否先将当前jsp页面的已输出的内容刷新到客户端。
<jsp:include>标签是动态引入(和使用代码进行include一样),<jsp:include>标签涉及到的2个jsp页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并。
include指令是静态引入(编译时引入),涉及到的2个jsp页面会被翻译成一个servlet,其内容是在源文件级别进行合并。
不管是<jsp:include>标签,还是include指令,它们都会把两个jsp页面内容合并输出,所以这两个页面不要出现重复的html全局架构标签,否则输出给客户端的内容将会是一个格式混乱的html文档。
例子:
使用<jsp:include>标签来实现包含页面:
在tomcat的work目录中可以发现会将head.jsp和foot.jsp单独翻译成servlet,这个就是动态包含。
使用include指令实现页面包含:
这时候可以发现work目录中并不会还单独翻译head.jsp页面了,同时我们看看jsp页面翻译的servlet代码:
可以看到在代码中使用静态代码块实现静态页面包含的。

<jsp:forward>标签

<jsp:forward>标签用于把请求转发给另外一个资源。
语法:
page属性用于指定请求转发到的资源的相对路径,它也可以通过执行一个表达式来获得。

<jsp:param>或<jsp:params>标签

当使用<jsp:include>和<jsp:forward>标签引入或将请求转发给其它资源时,可以使用<jsp:param>标签向这个资源传递参数。
  • 语法1
    • 语法2
      name属性用于指定参数名,value属性用于指定参数值。在<jsp:include>和<jsp:forward>标签引中可以使用多个<jsp:param>标签来传递多个参数。

      <jsp:useBean>、<jsp:setProperty>和<jsp:getProperty>标签

      这三个标签是一起用来操作bean对象的,<jsp:useBean>是用来初始化bean对象的,<jsp:setProperty>标签是用来设置bean对象中的属性值,<jsp:getProperty>标签是用来获取bean对象中的属性值的
      例子:
      同时定义了一个bean对象:com.weijia.domain.Person,其中有一个name属性(一定要有get/set方法才叫属性)。
      对于标签<jsp:useBean>,它可以指定在哪个域中创建这个bean对象,它的规则是首先在这个域中查找有没有这个对象,没有就创建,有就直接拿来使用。
      对于<jsp:setProperty>标签,可以直接使用value属性设置属性的值,这里面他内部是有一个类型转换的,可以将字符串值转化成8中基本类型的值,其他对象类型的转化是会报错的,比如现在Person类中有一个属性birthday是Date型的,那么这里就不能直接写成这样:
      这样系统会报类型转化错误,当然可以直接使用脚本表达式给这个属性值传递一个Date类型的对象,这样就不会错了:
      当然也可以使用请求参数来设置属性值:
      访问http://localhost:8080/JspDemo/bean.jsp?name=jiangwei就可以进行属性赋值。
      同时这里的name属性中的填的是<jsp:useBean>标签中的id值,所以说,在使用get/setProperty标签的时候一定是在useBean标签之后。

      EL

      简介

      EL提供了在jsp脚本编制元素范围外使用运行时表达式的功能。脚本编制元素是指页面中能够用于在jsp文件中嵌入Java代码的元素。它们通常用于对象操作以及执行那些影响所生成内容的计算。JSP 2.0将EL表达式添加为一种脚本编制元素。

      基本语法

      ${ EL Expression},EL表达式是配合JSTL使用的。需要引入JSTL标签库。
      示例:
      EL 表达式
      说明
      ${ “Helloworld” }
      输出字符串常量
      ${ str }
      输出字符串变量str的值
      ${ 3 + 2 }
      输出3+2的结果
      {user["name"] }
      输出user对象的name属性
      ${ sessionScope["user"].name }
      输出session域中user对象的name属性
      ${user.name}
      访问对象user的getName()方法以得到name成员的值
      ${list[1]}
      访问list对象的第二项
      ${map["key"]}
      访问map指定键的值

      “.”与”[ ]”的相同点和差别

      • 相同:都可以访问对象有属性
      • 差别:当属性的名字包含有空格,点号等复杂符号时。使用”.”来访问对象有属性将会出现异常

      EL 变量

      EL存取变量数据的方法很简单,例如${username}的意思是取出某一范围中名称为username的变量,因为并没有指定哪一个范围的username,所以它的默认值会先从Page范围找,假如找不到,再依序到Request、Session、Application范围;假如途中找到username,就直接回传,不再继续找下去,但是假如全部的范围都没有找到时,就回传NULL,当然EL表达式还会做出优化,页面上显示空白,而不是打印输出NULL。
      属性范围(JSTL名称)
      EL中的名称
      Page
      PageScope
      Request
      RequestScope
      Session
      SessionScope
      Application
      ApplicationScope
      也可以指定要取出哪一个范围的变量:
      范例
      说明
      ${pageScope.username}
      取出Page范围的username变量
      ${requestScope.username}
      取出Request范围的username变量
      ${sessionScope.username}
      取出Session范围的username变量
      ${applicationScope.username}
      取出Application范围的username变量
      其中,pageScope、requestScope、sessionScope和applicationScope都是EL的隐含对象。

      自动转变类型

      EL除了提供方便存取变量的语法之外,它另外一个方便的功能就是:自动转变类型。
      例如${param.count + 20},假若窗体传来count的值为10时,那么上面的结果为30,之前没接触过jsp可能会认为上面的例子是理所当然的,但是在jsp 1.2之中不能这样做;原因是从窗体所传来的值,它们的类型一律是String,所以当你接收之后,必须再将它转为其他类型,如:int、float等等,然后才能执行一些数学运算,下面是之前的做法:
      所以,注意不要和Java的语法(当字符串和数字用+链接时会把数字转换为字符串)搞混淆。

      EL 隐含对象

      jsp有9个隐含对象,而EL也有自己的隐含对象,EL隐含对象总共有11个。
      隐含对象
      类型
      说明
      PageContext
      javax.servlet.ServletContext
      表示此jsp的PageContext
      PageScope
      java.util.Map
      取得Page范围的属性名称所对应的值
      RequestScope
      java.util.Map
      取得Request范围的属性名称所对应的值
      sessionScope
      java.util.Map
      取得Session范围的属性名称所对应的值
      applicationScope
      java.util.Map
      取得Application范围的属性名称所对应的值
      param
      java.util.Map
      如同ServletRequest.getParameter(String name),回传String类型的值
      paramValues
      java.util.Map
      如同ServletRequest.getParameterValues(String name),回传String[]类型的值
      header
      java.util.Map
      如同ServletRequest.getHeader(String name),回传String类型的值
      headerValues
      java.util.Map
      如同ServletRequest.getHeaders(String name),回传String[]类型的值
      cookie
      java.util.Map
      如同HttpServletRequest.getCookies()
      initParam
      java.util.Map
      如同ServletContext.getInitParameter(String name),回传String类型的值
      不过有一点要注意的是如果你要用EL输出一个常量的话,字符串要加双引号,不然的话EL会默认把你认为的常量当做一个变量来处理,这时如果这个变量在4个声明范围不存在的话会输出空,如果存在则输出该变量的值。

      属性(Attribute)与范围(Scope)

      与范围有关的EL隐含对象包含以下四个:pageScope、requestScope、sessionScope和applicationScope。
      它们基本上就和jsp的pageContext、request、session和application一样。
      必须注意的是,这四个隐含对象只能用来取得范围属性值,即jsp中的getAttribute(String name),却不能取得其他相关信息,例如:
      jsp中的request对象除可以存取属性之外,还可以取得用户的请求参数或表头信息等等。
      但是在EL中,它就只能单纯用来取得对应范围的属性值,
      例如:
      要在session中储存一个属性,它的名称为username,在jsp中使用session.getAttribute("username")来取得username的值,但是在EL中,则是使用${sessionScope.username}来取得其值的。

      cookie

      所谓的cookie是一个小小的文本文件,它是以key、value的方式将Session Tracking的内容记录在这个文本文件内,这个文本文件通常存在于浏览器的暂存区内。
      JSTL并没有提供设定cookie的动作,因为这个动作通常都是后端开发者必须去做的事情,而不是交给前端的开发者。
      假若在cookie中设定一个名称为userCountry的值,那么可以使用${cookie.userCountry}来取得它。

      header和headerValues

      header储存用户浏览器和服务端用来沟通的数据,当用户要求服务端的网页时,会送出一个记载要求信息的标头文件,例如:用户浏览器的版本、用户计算机所设定的区域等其他相关数据;假若要取得用户浏览器的版本,即${header["User-Agent"]}。另外在鲜少机会下,有可能同一标头名称拥有不同的值,此时必须改为使用headerValues来取得这些值。
      注意:因为User-Agent中包含-这个特殊字符,所以必须使用[],而不能写成$(header.User-Agent)。

      initParam

      就像其他属性一样,可以自行设定web站台的环境参数(Context),当想取得这些参数initParam就像其他属性一样,可以自行设定web站台的环境参数(Context),当想取得这些参数
      那么就可以直接使用${initParam.userid}来取得名称为userid,其值为mike的参数。
      下面是之前的做法:

      param和paramValues

      在取得用户参数时通常使用一下方法:
      在EL中则可以使用param和paramValues两者来取得数据。
      这里param的功能和request.getParameter(String name)相同,而paramValues和request.getParameterValues(String name)相同。
      如果用户填了一个表格,表格名称为username,则就可以使用${param.username}来取得用户填入的值。

      pageContext

      可以使用${pageContext}来取得其他有关用户要求或页面的详细信息。
      下表列出了几个比较常用的部分:
      Expression
      说明
      ${pageContext.request.queryString}
      取得请求的参数字符串
      ${pageContext.request.requestURL}
      取得请求的URL,但不包括请求之参数字符串,即servlet的HTTP地址
      ${pageContext.request.contextPath}
      服务的webapplication的名称
      ${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是否为新的,所谓新的session,表示刚由server产生而client尚未使用
      ${pageContext.session.id}
      取得session的ID
      ${pageContext.servletContext.serverInfo}
      取得主机端的服务信息
      这个对象可有效地改善代码的硬编码问题,如页面中有一A标签链接访问一个servlet,如果写死了该servlet的HTTP地址,那么如果当该servlet的servlet-mapping改变的时候必须要修改源代码,这样维护性会大打折扣。

      EL算术运算

      表达式语言支持的算术运算符和逻辑运算符非常多,所有在Java语言里支持的算术运算符,表达式语言都可以使用;甚至Java语言不支持的一些算术运算符和逻辑运算符,表达式语言也支持。
      上面页面中示范了表达式语言所支持的加、减、乘、除、求余等算术运算符的功能,表达式语言还支持div、mod等运算符。
      而且表达式语言把所有数值都当成浮点数处理,所以3/0的实质是3.0/0.0,得到结果应该是Infinity。
      如果需要在支持表达式语言的页面中正常输出$符号,则在$符号前加转义字符\,否则系统以为$是表达式语言的特殊标记。

      EL关系运算符

      关系运算符
      说明
      范例
      结果
      ==或eq
      等于
      {5==5}或{5eq5}
      true
      !=或ne
      不等于
      {5!=5}或{5ne5}
      false
      <或lt
      小于
      {3<5}或{3lt5}
      true
      >或gt
      大于
      ${3>5}或{3gt5}
      false
      <=或le
      小于等于
      {3<=5}或{3le5}
      true
      >=或ge
      大于等于
      {3>=5}或{3ge5}
      false
      表达式语言不仅可在数字与数字之间比较,还可在字符与字符之间比较,字符串的比较是根据其对应UNICODE值来比较大小的。
      注意:在使用EL关系运算符时,不能够写成:${param.password1} == ${param.password2}或者${${param.password1} == ${param.password2}}而应写成${ param.password1 == param.password2 }。

      EL逻辑运算符

      逻辑运算符
      范例
      结果
      &&或and
      交集${A && B}或${A and B}
      true/false
      |或or
      !或not
      非${! A}或${not A}
      true/false

      Empty 运算符

      Empty运算符主要用来判断值是否为空(NULL,空字符串,空集合)。

      条件运算符

      ${ A ? B : C}。

      JSTL

      简介

      JSTL是Java中的一个定制标记库集。
      jsp标准标签库(JSTL)是一个jsp标签集合,它封装了jsp应用的通用核心功能。
      JSTL支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。

      jstl 标签库

      JSTL一共包含四大标签库:
      • core:核心标签库,学习的重点;
      • fmt:格式化标签库,只需要学习两个标签即可
      • sql:数据库标签库,不需要学习了,它过时了
      • xml:xml标签库,不需要学习了,它过时了
      除了jsp动作标签外,使用其他第三方的标签库都需要导包。
      在使用标签的jsp页面中使用taglib指令导入标签库;下面是导入jstl的core标签库:
      • prefix="c":指定标签库的前缀,这个前缀可以随便给值,但大家都会在使用core标签库时指定前缀为c
      • uri="http://java.sun.com/jstl/core":指定标签库的uri,它不一定是真实存在的网址,但它可以让jsp找到标签库的描述文件

      core标签库

      out和set标签

      标签
      说明
      <c:out value=”aaa”/>
      输出aaa字符串常量
      <c:out value=”{aaa}” default=”xxx”/>
      当{aaa}不存在时,输出xxx字符串
      <%request.setAttribute("a","<script></scrip>")%><c:out value="${a }" default="xxx" escapeXml="false" />
      当escapeXml为false,不会转换<、>,这可能会受到JavaScript攻击
      <c:set var=”a” value=”hello”/>
      在pageContext中添加name为a,value为hello的数
      <c:set var=”a” value=”hello” scope=”session”/>
      在session中添加name为a,value为hello的数据

      remove标签

      标签
      说明
      <c: remove var="a"/> <c: out value="${a}" default="none"/>
      删除所有域中name为a的数据
      <c:remove var="a" scope=”page”/>
      删除pageContext中name为a的数据

      url标签

      该标签会在需要重写URL时添加。
      表格
      说明
      <c:url value="/"/>
      输出上下文路径:/项目名/
      <c:url value="/" var="a" scope="request"/>
      把本该输出的结果赋给变量a。范围为request
      <c:url value="/AServlet"/>
      输出:/项目名/AServlet
      <c:url value="/AServlet"><c:param name="username" value="abc"/><c:param name="password" value="123"/>
      输出:/项目名/AServlet?username=abc&password=123
      如果参数中包含中文,那么会自动使用URL编码!

      if标签

      if标签的test属性必须是一个boolean类型的值,如果test的值为true,那么执行if标签的内容,否则不执行。

      choose标签

      choose标签对应Java中的if/else结构。when标签的test为true时,会执行这个when的内容。当所有when标签的test都为false时,才会执行otherwise标签的内容。

      forEach标签

      forEach就是循环标签,forEach标签有多种两种使用方式:
      • 使用循环变量,指定开始和结束值,类似for(int i = 1; i <= 10; i++) {}
        • 循环遍历集合,类似for(Object o : 集合)
          • 遍历集合或数组
            • 遍历List
              • 遍历Map
              forEach标签还有一个属性varStatus,这个属性用来指定接收循环状态的变量名,例如:
              这时就可以使用vs这个变量来获取循环的状态了。
              • count:int类型,当前已遍历元素的个数
              • index:int类型,当前元素的下标
              • first:boolean类型,是否为第一个元素
              • last:boolean类型,是否为最后一个元素
              • current:Object类型,表示当前项目

              fmt标签库

              fmt标签库是用来格式化输出的,通常需要格式化的有时间和数字。
              • 格式化时间
                • 格式化数字

                  自定义标签

                  步骤

                  在jsp页面中使用标签就等于调用某个对象的某个方法,例如<c:if test=””>,自定义标签其实就是自定义类一样!
                  1. 定义标签处理类:必须是Tag或SimpleTag的实现类
                  1. 编写标签库描述符文件(TLD),SimpleTag接口是jsp2.0中新给出的接口,用来简化自定义标签,所以现在基本上都是使用SimpleTag;Tag是老的,传统的自定义标签时使用的接口,现在不建议使用它了

                  SimpleTag接口

                  SimpleTag接口内容如下:
                  • void doTag():标签执行方法;
                  • JspTag getParent():获取父标签;
                  • void setParent(JspTag parent):设置父标签
                  • void setJspContext(JspContext context):设置PageContext
                  • void setJspBody(JspFragment jspBody):设置标签体对象
                  标签对应的类称为“标签处理类”!

                  标签的生命周期

                  1. 当容器(Tomcat)第一次执行到某个标签时,会创建标签处理类的实例
                  1. 然后调用setJspContext(JspContext)方法,把当前jsp页面的pageContext对象传递给这个方法
                  1. 如果当前标签有父标签,那么使用父标签的标签处理类对象调用setParent(JspTag)方法
                  1. 如果标签有标签体,那么把标签体转换成JspFragment对象,然后调用setJspBody()方法
                  1. 每次执行标签时,都调用doTag()方法,它是标签处理方法

                  标签库描述文件(TLD)

                  标签库描述文件是用来描述当前标签库中的标签的!
                  标签库描述文件的扩展名为tld,可以把它放到WEB-INF下,这样就不会被客户端直接访问到了。

                  使用标签

                  在页面中使用标签分为两步:
                  1. 使用taglib导入标签库
                  1. 使用标签

                  自定义标签进阶

                  继承SimpleTagSupport

                  继承SimpleTagSuppport要比实现SimpleTag接口方便太多了,只需要重写doTag()方法,其他方法都已经被SimpleTagSuppport完成了。

                  有标签体的标签

                  标签体内容的可选值:
                  <body-content>元素的可选值有:
                  • empty:无标签体
                  • jsp:传统标签支持它,SimpleTag已经不再支持使用<body-content>jsp</body-content>。标签体内容可以是任何东西:EL、JSTL、<%=%>、<%%>,以及html
                  • scriptless:标签体内容不能是java脚本,但可以是EL、JSTL等;在SimpleTag中,如果需要有标签体,那么就使用该选项
                  • tagdependent:标签体内容不做运算,由标签处理类自行处理,无论标签体内容是EL、JSP、JSTL,都不会做运算。这个选项几乎没有人会使用!
                  自定义有标签体的标签需要:
                  • 获取标签体对象:JspFragment jspBody = getJspBody()
                  • 把标签体内容输出到页面:jspBody.invoke(null)
                  • tld中指定标签内容类型:scriptless

                  不执行标签下面的页面内容

                  如果希望在执行了自定义标签后,不再执行jsp页面下面的东西,那么就需要在doTag()方法中使用SkipPageException。

                  带有属性的标签

                  一般标签都会带有属性,例如
                  其中test就是一个boolean类型的属性。
                  完成带有属性的标签需要:
                  • 在处理类中给出JavaBean属性(提供get/set方法)
                  • 在TLD中部属相关属性

                  AJAX

                  简介

                  是一种用于创建更好更快以及交互性更强的Web应用程序的技术,是基于JavaScript、XML、HTML、CSS新用法。
                  1. JavaScript:更新局部的网页
                  1. XML:一般用于请求数据和响应数据的封装
                  1. XMLHttpRequest对象:发送请求到服务器并获得返回结果
                  1. CSS:美化页面样式
                  1. 异步:发送请求后不等返回结果,由回调函数处理结果

                  步骤

                  1. 创建XmlHttpRequest对象
                  1. 注册状态监控回调函数
                  1. 建立与服务器的异步连接
                  1. 发出异步请求
                  如下是一个搜索框提示的JavaScript函数写法。
                  对应调用的是一个SearchBookAJAXServlet,这里可以自己进行数据的封装,也可以直接调用json,json的使用很简单,String str = JSONArray.fromObject(list).toString();即可。
                  创建XMLHttpRequest对象时,不同浏览器提供不同的支持。

                  XMLHttpRequest

                  属性

                  • readyState:类型short,只读
                  • responseText:类型String,只读
                  • responseXML:类型Document,只读
                  • status:类型short,只读

                  方法

                  1. open()
                  1. send()
                  1. setRequestHeader()
                  1. 事件处理器onreadystatechange

                  将状态触发器绑定到一个函数

                  1. var xmlHttp;
                  1. createXMLHttpRequest()
                  1. xmlHttp.onreadystatechange = processor;,这里的processor是回调函数的方法名
                  1. function processor (){… …}

                  使用open方法建立连接

                  open(method,url, asynch)
                  • 其中method表示HTTP调用方法,一般使用"GET","POST"
                  • url表示调用的服务器的地址
                  • asynch表示是否采用异步方式,true表示异步,一般这个参数不写
                  范例代码:
                  • xmlHttp.open("POST", "url");
                  • xmlHttp.open("GET", "url?name=xxx&pwd=xxx");

                  向服务器端发送数据

                  1. GET方式提交,数据在URL上xmlHttp.send(null);
                  1. POST方式提交
                      • xmlHttp.setRequestHeader("CONTENT-TYPE","application/x-www-form-urlencoded");
                      • xmlHttp.send("name=xxx&pwd=xxx");
                  在回调函数中对数据进行处理:

                  常用的服务器返回数据格式

                  • HTML片段
                  • JSON格式的数据
                  • XML格式的数据

                  验证码机制

                  验证码是由后端随机生成的(后端始终认为前端有可能会被伪造)
                  1. 后端调用相关的绘图第三方类库或是(平台PHP、.NET、Java)系统核心类库进行图片的绘制
                  1. 绘制的那些随机的数字、字母都是后端预先定义好的
                  1. 将绘制的图片url地址通过网络返回给客户端,然后客户端使用img标签去引用这个验证码的地址
                  1. 后端在绘制完毕验证码之后,随机选择生成的字母不能丢弃,而是需要保存到Session中
                  1. 当客户端输入验证码完毕后,表单提交到服务器,后端服务器拿到客户端提交的验证码,与服务器端Session中的验证码进行比较

                  MD5

                   
                  上一篇
                  JavaEE——域对象
                  下一篇
                  JavaSE——基础

                  评论
                  Loading...