JSP
JSPWeb技术概述1.认知静态网页和动态网页:1.静态网页:静态网页是指没有后台数据库,不含程序,不可交互的网页。代码编写的是什么它就显示什么,不会有任何的改变静态网页更新起来相对比较麻烦,适用于一般更新较少的展示型网站在网页设计中,纯粹HTML格式的网页通常被称为静态网页静态网页通常都是以.htm,.html,.shtml等为后缀的页面文件在HTML格式的网页中,也可以出现各种动态的效果(如:
JSP
Web基础概述
1.认知静态网页和动态网页:
1.静态网页:
- 静态网页是指没有后台数据库,不含程序,不可交互的网页。
- 代码编写的是什么它就显示什么,不会有任何的改变
- 在网页设计中,纯粹HTML格式的网页通常被称为静态网页
- 静态网页通常都是以.htm,.html,.shtml等为后缀的页面文件
- 在HTML格式的网页中,也可以出现各种动态的效果(如:gif动画,Flash,滚动字幕等),这些动态效果只是视觉上的,与动态网页时不同的概念
静态网页的特点:
- 静态网页没有数据库的支持,在网站制作和维护方面工作量较大,因此当网站信息量很大时,完全依靠静态网页制作比较困难
- 网页内容一经发布到网站服务器上,无论是否有用户访问,每个静态网页的内容都是保持在网站服务器上的,即静态网页是实实在在保存在服务器上的文件,每个网页都是一个独立的文件
- 静态网页每个网页都有一个固定的URL,且网页URL以.htm,.html,.shtml等常见形式为后缀
- 静态网页的内容相对稳定,因此容易被搜索引擎检索
- 静态网页的交互性较差,在功能上有较大的限制
2.动态网页
- 动态网页是相对于静态网页而言的,是指可交互,有后台数据库,含有程序的网页,它显示的内容随着用户的需求的改变而改变
- 动态网页通常是以.asp,.jsp,.php,.aspx等形式为后缀的页面文件
- 这里说的动态网页与网页上的各种动画,滚动字幕等视觉上的动态效果没有直接关系,动态网页也可以是纯文字内容的,也可以是包含各种动画的内容,这些只是网页具体内容的表现形式,无论网页是否具有动态效果,采用动态网页技术生成的网页都称为动态网页
动态网页的特点
- 动态网页是以数据库技术为基础的,可以大大降低网站维护的工作量
- 动态网页实际上并不是独立存在于服务器上的网页文件,只有当用户请求时服务器才返回一个完整的网页
- 采用动态网页技术的网站可以实现更多的功能,如用户注册,用户登录,在线调查,用户管理,订单管理等
搜索引擎一般不可能从一个网站的数据库中访问全部网页
2.认知Web服务器和网络数据库
1.Web服务器
- Web服务器不是常常提到的物理机器(服务器),而是一种软件,可以管理各种Web文件,并为提出HTTP请求的浏览器提供HTTP响应
- Web服务器可以解析HTTP协议。当Web服务器接收到一个HTTP请求会返回一个HTTP响应送回一个HTML页面
- 为了处理一个请求,Web服务器可以返回一个静态页面,进行页面跳转,或者把动态响应的产生委托给一些其他的程序,像CGI脚本,JSP脚本,Servlets程序,ASP脚本,Javascript程序
- 无论他们的目的如何,这些服务器端的程序通常可以产生一个HTML的响应来让浏览器可以响应
- 在UNIX和Linux平台下使用最广泛的免费HTTP服务器是W3C,NCSA和Apache服务器
- 而Windows平台NT/2000/2003使用IIS的Web服务器
- 在选择使用Web服务器时应考虑的本身特性因素有:性能,安全性,日志和统计,虚拟主机,代理服务器,缓冲服务和集成应用程序等
1.Miscrosoft IIS
- Microsoft的Web服务器产品为Internet Information Server(IIS),IIS是允许在公共Intranet或Internet上发布信息的Web服务器。
- IIS提供了一个图形界面的管理工具可用于监视配置和控制Internet服务
- IIS是一种Web服务组件,其中包括Web服务器,FTP服务器,NNTP服务器和SMTP服务器,分别用于网页浏览,文件传输,新闻服务和邮件发送等方面。它提供ISAPI(Intranet Server API)作为扩展Web服务器功能的编程接口;同时它还提供一个Internet数据库连接器可以实现对数据库的查询和更新
2.IBM WebSphere
- WebSphere Application Server是一种功能完善,开放的Web应用程序服务器,是IBM电子商务计划的核心部分,它是基于Java的应用环境,用于建立,部署和管理Internet和Intranet Web应用程序
3.BEA WebLogic
- BEA WebLogic Server是一种多功能,基于标准的Web应用服务器
4.Apache
- Apache是用的最多的Web服务器,它源于NCSAhttpd服务器。
5.Tomcat
- Tomcat是一个开放源代码,运行Servlet和JSP Web应用软件的基于Java的Web应用软件容器。
2.Web数据库
- Web数据库就是将数据库技术与Web技术融合在一起,使数据库系统成为Web技术的重要有机组成部分,从而实现数据库与网络技术的无缝结合
3.C/S结构与B/S结构
1.C/S结构
- C/S结构全称为Client/Server,即:客户端/服务器模式
- C/S结构的系统分为两个部分:客户端和服务器;应用程序也分为客户端程序和服务端程序。
- 服务器程序负责管理和维护数据资源,并接受客户端的服务请求(例:数据查询或更新等),向客户端提供所需的数据或服务。对于用户的请求,如果客户端能够满足就直接给出结果;反之则交给服务器处理
- 客户端应用软件一般包括用户界面,本地数据库等,它面向用户,接受用户的应用请求,并通过一定的协议或接口与服务器进行通信,将服务器提供的数据等资源经过处理后提供给用户。
- 当用户通过客户端向服务器发出数据访问请求时,客户端将请求传送给服务器,服务器对该请求进行分析执行,最后将结果返回给客户端,显示给用户。客户端的请求可采用SQL语句或直接调用服务器上的存储过程来实现服务器将运行的结果发送给客户端,客户端和服务器之间的通信通过数据库引擎(例:ODBC引擎,OLEDB引擎等)来完成,数据库一般采用大型数据库(例:SQL Server,Oracle等)
- 该结构模式可以合理均衡事物的处理,充分保证数据的完整性和一致性
- C/S结构的优缺点:
- 优点:C/S结构模式能够在网络环境完成数据资源的共享,提供了开放的接口,在客户端屏蔽掉了后端的复杂性,使客户端的开发,使用更加容易和简单,适合管理信息系统的一般应用。
- 缺点:
- 1.C/S结构模式只能适用于中,小规模的局域网,对于大规模的局域网或广域网不能很好的胜任
- 2.开发成本高,C/S结构对客户端软硬件要求较高,尤其是软件的不断升级换代,对硬件要求不断提高,增加了整个系统的成本
- 3.当系统的用户数量增加时,服务器的负载急剧增加,使系统性能明显下降
- 4.移植困难,不同开发工具开发的应用程序,一般兼容性差,不能移植到其他平台上运行
- 5.系统管理和维护工作较困难,不同客户机安装了不同的子系统软件,用户界面风格不一使用复杂
2.B/S结构
- B/S结构全程为Browser/Server,即:浏览器/服务器模式
- B/S结构模式的工作原理:
JSP技术
1.JSP定义
- 1.JSP(Java Server Pages):它是建立在Servlet规范之上的动态网页开发技术
- 2.JSP文件中HTML代码与Java代码共同存在,HTML代码用来实现网页中静态内容的显示,Java代码用来实现网页中动态内容的显示
- 3.JSP文件的扩展名为.jsp
- 4.JSP技术所开发的Web应用是基于Java,它用一种简捷的方法从Java程序生成Web页面,使用上具有如下特征:
- 1.跨平台: JSP是基于Java语言的,它可以使用Java API,所以它也是跨平台的,可以应用于不同的系统中;当从一个平台移植到另一个平台时,JSP和JavaBean的代码不需要重新编译,这是因为Java字节码是与平台无关的
- 2.业务代码分离: JSP技术开发Web应用时,可以将页面的开发与应用程序的开发分离开;开发人员使用HTML来设计页面,使用JSP标签和脚本来动态生成页面上的内容;在服务器端,JSP引擎(或容器,这里指Tomcat)负责解析JSP标签和脚本程序,生成所请求的内容,并将执行结果以HTML页面的形式返回到浏览器
- 3.组件重用: JSP中可以使用JavaBean编写业务组件,也就是使用一个JavaBean类封装业务处理代码或者作为一个数据存储模型,在JSP页面中,甚至在整个项目中,都可以重复使用这个JavaBean,JavaBean也可以应用到其他Java应用程序中
- 4.预编译: 预编译就是在用户第一次通过浏览器访问JSP页面时,服务器将对JSP页面代码进行编译并且仅执行一次编译;编译好的代码将被保存,在用户下一次访问时,会直接执行编译好的代码
2.JSP运行原理
- 1.JSP的工作模式是请求/响应模式,客服端首先发出HTTP请求,JSP程序收到请求后进行处理并返回处理结果
- 2.JSP文件第一次被请求时,JSP引擎(容器)把该JSP文件转换成为一个Servlet,这个引擎本身也是一个Servlet
- 3.JSP运行过程:
- 1.客户端发出请求,请求访问JSP文件
- 2.JSP容器先将JSP文件转换成一个Java源文件(Java Servlet 源程序),转换过程中如果发现JSP文件中存在任何语法错误则中断转换程序并向服务器和客户端返回出错信息
- 3.如果转换成功,JSP容器将生成的Java源文件编译成相应的字节码.class文件;该.class文件是一个Servlet,Servlet容器会像处理其他Servlet一样来处理它
- 4.Servlet容器加载转换后的Servlet类(.class文件)创建一个该Servlet(JSP页面的转换结果)实例,并执行Servlet的jsplnit()方法;jsplnit()方法在Servlet的整个生命周期中只会执行一次
- 5.执行jspService()方法来处理客户端请求。对于每个请求,JSP容器都会创建一个新的线程来处理它;如果多个客户端同时请求该JSP文件,JSP容器也会创建多个线程使得每个客户端请求都对应一个线程;JSP运行过程中采用的这种多线程的执行方式可以极大地降低对系统资源的需求,提高系统的并发量并缩短响应时间;需要注意的是,由于第4步生成的Servlet是常驻内存的,所以响应速度非常快
- 6.如果JSP文件被修改了,服务器将根据设置决定是否对该文件重新编译;如果需要重新编译,则使用重新编译后的结果取代内存中常驻的Servlet,并继续上述处理过程
- 7虽然JSP效率很高,但在第一次调用的时候往往由于需要转换和编译,所以会产生一些轻微的延迟;此外由于系统资源不足等原因,JSP容器可能会以某种不确定的方式将Servlet从内存中移除,发生这种情况时首先会调用jspDestroy()方法,然后Servlet实例会被加入垃圾收集处理
- 8.当请求处理完成后,响应对象由JSP容器接收,并将HTML格式的响应信息发送回客户端
- 9.可以在jspInit()中进行一些初始化工作(建立数据库的连接,建立网络连接等);可以在jspDestroy()中释放相应的资源
2.分析JSP所生成的Servlet代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试</title> </head> <body> <p>Hello World</p> <b>测试</b> </body> </html>
package org.apache.jsp; public void _jspInit() { } public void _jspDestroy() { } public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { final javax.servlet.jsp.PageContext pageContext; javax.servlet.http.HttpSession session = null; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null; final java.lang.Object page = this; javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null; try { response.setContentType("text/html; charset=UTF-8"); pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("\r\n"); out.write("<!DOCTYPE html>\r\n"); out.write("<html>\r\n"); out.write("<head>\r\n"); out.write("<meta charset=\"UTF-8\">\r\n"); out.write("<title>娴嬭瘯</title>\r\n"); out.write("</head>\r\n"); out.write("<body>\r\n"); out.write("\t<p>Hello World</p>\r\n"); out.write("\t<b>娴嬭瘯</b>\r\n"); out.write("</body>\r\n"); out.write("</html>"); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { if (response.isCommitted()) { out.flush(); } else { out.clearBuffer(); } } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); else throw new ServletException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } }
- 1.用户第一次访问HelloWorld.jsp页面时,该页面会先被JSP容器转换成HelloWorld_jsp的源文件,然后将源文件编译成HelloWorld_jsp的.class文件
- 2.运行jsp文件时,HelloWorld_jsp.java和HelloWorld_jsp.class文件都会出现在Tomcat安装目录/work/Catalina/localhost/应用名/org/apache/jsp目录下,删除jsp文件时,不会发生变化
- 3.如果项目发布在Tomcat的work目录中,源文件和.class文件可以在Tomcat安装目录/work/Catalina/localhost/应用名/org/apache/jsp下找到;如果发布在Eclipse工作空间的.matadata中,可在上述目录的localhost文件中创建一个名称为chapter01的文件夹,并将HelloWorld_jsp文件复制到该文件夹中;启动Tomcat服务器,使用浏览器访问页面成功后,在chapter01文件夹中多出相应的文件
- 3.地址栏的路径多出了org\apache\jsp,这是由于JSP文件转换成Java类文件时会带有包名,该包名为org.apache.jsp
- 从图中可以看出FirstWeb2.jsp已被转换成源文件和.class文件。打开源文件,可查看转换后的源代码,从代码中可以看出FirstWeb2.jsp文件转换后的源文件没有实现Servlet接口,但继承了org.apache.jasper.runtime.HttpJspBase类,从HttpJspBase源代码中可以看出,HttpJspBase类是HttpServlet的一个子类,由此可见,FirstWeb2_jsp类就是一个Servlet
- HttpJspBase源代码解析:
- 代码中定义了init()方法,该方法使用final进行修饰,并且其内部调用了jsplnit()和_jsplnit()方法.因此,在JSP页面所生成的Servlet、不能覆盖这两个方法。但是如果要在JSP页面完成Servlet的init()方法的功能只能覆盖jsplint()和_jsplnit()这两个方法中任何一个;同样,如果要在JSP页面中完成Servlet的destroy()方法,则只能覆盖jspDestroy和_jspDestroy()两个方法中的任何一个
- 在service()方法中调用了_jspService()方法,也就是说用户访问JSP文件时,会调用HttpJspBase类中的service()方法来响应用户的请求。根据Java的多态性的特征,在service()方法中,会调用FirstWeb2_jsp类中实现_jspService()的方法,用来响应用户的请求
3.JSP基本语法
- 在JSP文件中可以嵌套很多内容(例:JSP的脚本内容和注释等),这些内容的编写都需要遵循一定的语法规范
- JSP语法包括4个部分
- 1.静态模板
- 2.脚本
- 3.指令
- 4.动作标签
1.静态模板-注释形式
注释用来在程序代码中说明程序语句,在程序中加适当的注释可以提高程序的可读性。JSP注释包括两种:分部是html注释和jsp注释
- html注释(显示注释):是指包含在< !-- --> 之间的内容,在客户端源代码中显示内容,但不被浏览器直接显示。< !-- -->之间可以包含jsp表达式并被jsp容器解释
- jsp注释(隐藏注释):隐藏注释写在jsp程序中,用隐藏注释标记的字符在jsp编译时会被忽略。它不会显示在客户端浏览器中,也不会出现在客户端源代码中
- html注释和jsp注释的区别:
- 1.html是显示注释,注释内容可以在客户端源代码中看到,而jsp隐藏注释的注释内容不能传输到客户端,即在客户端源代码中不能看到jsp隐藏注释内容;
- 2.html注释还可以在注释中使用表达式,这个表达式是不定的由页面来决定,而在jsp隐藏注释中不能使用表达式。html注释和jsp注释都不能显示在客户端浏览器中,所以这里的显示和隐藏是指注释内容是否显示在客户端源代码中
基本语法:
<%-- 注释内容 --%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <p>JSP注释</p> <p>测试内容</p> <p>这个是HTML注释</p> <p>这个是JSP注释</p> <p>这个是普通注释</p> <p>这个是普通注释</p> <p>这是是普通注释</p> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <p>JSP注释</p> <p>测试内容</p> <!-- <p>这个是HTML注释</p> --> <%-- <p>这个是JSP注释</p> --%> //<p>这个是普通注释</p> /* <p>这个是普通注释</p> */ /** <p>这是是普通注释</p> */ </body> </html>
语法说明:
- 需要注意的是,Tomcat在将JSP页面编译成Servlet程序时,会忽略JSP页面中被注释的内容,不会将注释信息发送到客户端
- Java注释的3种形式都不能在jsp页面中起到注释的作用
2.脚本元素
- JSP脚本元素是指嵌套在<% %>之中的一条或多条Java代码。通过JSP脚本元素可以将Java代码嵌入HTML页面中,所以可执行的Java代码,都可以通过JSP脚本来执行
- JSP脚本元素主要包含如下3种类型
- 1.JSP Scriptlets
- 2.JSP 声明语句
- 3.JSP表达式
1.JSP Scriptlets
- JSP Scriptlets是一段代码段。可以放置Java代码片段,实现逻辑功能
- 基本语法:
<% java代码 (变量,方法,表达式等)%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <% System.out.println("测试JSP Scriptlets"); %><br/> <% out.println("测试JSP Scriptlets"); %><br/> <% int a=5; int b=3;out.println(a+b); %> <% out.println(a+b);out.println(a+b); %> </body> </html>
- 语法说明:
- 在JSP Scriptlets中可以声明变量,且该变量是所在JSP页面的局部变量,调用JSP Scriptlets时会为局部变量分配内存空间,调用结束后释放局部变量占有的内存空间
- 在JSP Scriplets中可以调用方法
- 注意jsp中不能用System.out.println();而要用out.println();
- 因为out对象是jsp的内置对象,所以可以直接使用。System.out.println()是在java代码中实现输出在控制台;out.println()是在jsp代码中实现输出在页面
- 这里的out是PrintWrite类的实例,JspWriter类型的out对象使用print方法和write方法都可以输出字符串,但是如果字符串对象的值为null时,print方法将输出内容为null的字符串而write方法则是抛出NullPointerException异常
2.JSP 声明语句
- JSP的声明语句用于声明变量和方法等
- 基本语法:
<%! 定义的变量或方法等 %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <% System.out.println("测试JSP Scriptlets"); %><br/> <% out.println("测试JSP Scriptlets"); %><br/> <% int a=5; int b=3; out.println(a+b); %><br/> <% out.println(a+b); out.println(a+b); %><br/> <% String str="abc"; out.println(str); %><br/> <% out.write(str); %> <hr/> <%! public class Text{ public int a; public int b; public int c; public Text(){ a = 5; b = 6; c = 8; } public int getTotal(){ int sum = a+b+c; return sum; } } %> <% Text text = new Text(); out.println(text.getTotal()); %> </body> </html>
- 语法说明:
- 在上述语法格式中,被声明的Java代码将被编译到Servlet的_jspService()方法之外,即在JSP声明语句中定义的都是成员方法,成员变量,静态方法,静态变量,静态代码块等
- 在JSP声明语句中声明的方法在整个JSP页面内有效,但是在方法内定义的变量只在该方法内有效;当声明的方法被调用时,会为方法内定的变量分配内存,而调用结束后立即释放所占的内存
- 在一个JSP页面中可以有多个JSP声明语句,单个声明中的Java语句可以是不完整的,但是多个声明结合后的结果必须是完整的Java语句
- <%! %>和<% %>的区别:
- <%! %>里面定义的属性是成员属性,相当于类的属性,方法相当于全局的方法,也相当于类里面的方法,但是它是不可以进行输出的,因为它只是进行方法的定义和属性的定义
- <% %>可以进行属性的定义,也可以输出内容,但是它不可以进行方法的定义。因为这对标签里面的内容是在此JSP被编译为Servlet的时候放在_jspService()方法里面的,这个方法就是服务器向客户端输出内容的地方,它本身就是一个方法,所以如果在它里面定义方法的话那么就相当于是在类的方法里面嵌套定义了方法,这在Java中是不允许的。但是可以在里面定义自己的私有变量,因为方法里面也可以定义变量,可以调用方法,唯独不可以再定义方法了
- 总之<%! >是用来定义成员变量属性和方法的,<% >主要是用来输出内容的,因此如果涉及到成员变量的操作那么就应该使用<%! >,而如果涉及输出内容就使用<% %>,且在<%! >声明的语句可以在<% >中调用
3.JSP 表达式
- JSP 表达式(expression)用于将程序数据输出到客户端,它将要输出的变量或者表达式直接封装在<%= %>的标记中
- 基本语法:
<%= expression %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <% System.out.println("测试JSP Scriptlets"); %><br/> <% out.println("测试JSP Scriptlets"); %><br/> <% int a=5; int b=3; out.println(a+b); %><br/> <% out.println(a+b); out.println(a+b); %><br/> <% String str="abc"; out.println(str); %><br/> <% out.write(str); %> <hr/> <%! public class Text{ public int a; public int b; public int c; public Text(){ a = 5; b = 6; c = 8; } public int getTotal(){ int sum = a+b+c; return sum; } } public int get(){ int sum=5; return sum; } %> <hr/> <% Text text = new Text(); out.println(text.getTotal()); %> <hr/> <%= text.getTotal() %><br/> <%= text.a + text.b %><br/> <%= get() %> </body> </html>
- 语法说明:
- 在上述语法格式中,JSP表达式中的变量或则表达式的计算结果被转换成一个字符串然后插入到JSP页面输出结果的相应位置处
- 注意:<%= %>标记之间插入的是表达式,不能插入语句;<%= 是一个完整的符号,<和=之间不能有空格,且JSP表达式中的变量或表达式后面不能有分号
3.指令
- 为了设置JSP页面中的一些信息,Sun公司提供了JSP指令,每种指令都定义了各自的属性
- 基本语法:
<%@ 指令名 属性名1="属性值1" ... %>
- JSP指令:
- 1.page指令
- 2.include指令
- 3.taglib指令
1.page指令
- page指令用来对JSP页面的某些特性进行描述(例:页面的编码方式,JSP页面采用的语言等)
- 基本语法:
<%@ page 属性名1="属性值1" ... >
属性名称 取值范围 描述 language java 指明解释该JSP文件时采用的语言,默认为Java import 任何包名,类名 指定在JSP页面翻译成的Servlet源文件中导入的包或类。import是唯一可以声明多次的page指令属性。一个import属性可以引用多个类,中间用英文逗号隔开 session true,false 指明该JSP内是否内置Session对象,如果为true则说明内置Session对象,可以直接使用,否则没有内置Sessio对象。默认情况下session属性的值为true。注意JSP引擎自动导入4个包:java.lang. * ;javax.servlet.* ;javax.servlet.jsp. * ;javax.servlet.http. * ; isErrorPage true,false 指定该页面是否为错误处理页面,如果为true则该JSP内置有一个Exception对象的exception可直接使用,默认情况isErrorPage的值为false errorPage 某个JSP页面的相对路径 指定一个错误页面,如果该JSP程序抛出一个未捕捉的异常则转到errorPage指定的页面。errorPage指定页面的isErrorPage属性为true且内置的exception对象为未捕捉的异常 content-type 有效的文档类型 客户端浏览器根据该属性判断文档类型;例:HTML格式为text/html;纯文本格式为text/plain;JPG图像为image/jpeg;GIF图像为imgae/gif;Word文档为application/msword pageEnCoding 当前页面 指定页面编码格式 <%@ page language="java" import="java.util.Scanner,javax.swing.*" import="java.math.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.awt.*" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <p>测试内容</p> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试标题</title> </head> <body> <h2>欢迎来到Tomcat的测试页面</h2> <form action="/FirstWeb1/FirstWeb3.jsp" method="get"> 姓名:<input name="username"/><br/> 年龄:<input name="age"/><br/> 课程:<input type="checkbox" value="english" name="course"/>英语 <input type="checkbox" value="math" name="course"/>数学 <input type="checkbox" value="java" name="course"/>Java <br/> <input type="submit" value="提交"> </form> </body> </html>
<%@ page language="java" import="java.util.Scanner,javax.swing.*" import="java.math.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.awt.*" %> <%@ page errorPage="error.jsp" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <p>测试内容</p> <%! String param = "234"; public void sayHello(){ System.out.println("Hello!"); } %> <% String name = request.getParameter("username"); sayHello(); int i = 1/0; %> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page isErrorPage="true" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h3>出错了!!!<%= exception %></h3> </body> </html>
- 语法说明:
- page指令可以出现多次;page指令的属性除了import属性外,其他属性都只能出现一次,否则会编译失败
- page指令对整个页面都有效,可以在页面内随便放置,而与其书写位置无关,但是习惯上把page指令写在JSP页面的最前面
- 注意:page指令的属性名称都是区分大小写的
- 注意:区分pageEncoding和contentType中的charset
- pageEncoding:设定JSP源文件和响应正文中的字符集编码
- contentType:设置JSP源文件和响应正文的字符集编码及MIM类型
- 可见pageEncoding和contentType都可以设置JSP源文件和响应正文中的字符集编码。但也有区别
- JSP要经过两次的编码,第一阶段会用pageEncoding,第二阶段会用utf-8至utf-8,第三阶段就是由Tomcat出来的网页用的是contentType
- 第一阶段是jsp编译成.java,它会根据pageEncoding的设定读取jsp,结果是由指定的编码方式翻译成统一的utf-8的Java源码,如果pageEncoding设定错误或没有设定出来的就是中文乱码
- 第二阶段是由Javac的Java源码至Java byteCode的编译,不论JSP编写的时候用的是什么编码方案,经过这个阶段的结果全部是utf-8的encoding1的java源码;
2.include指令
- include指令用来在JSP页面静态的包含一个文件(例:html文件,文本文件等)
- 基本语法:
<%@ include file="被包含文件的文件地址" >
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h3>欢迎你,现在时间是:</h3> <%@ include file="Date.jsp" %> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>当前时间</title> </head> <body> <h3><% out.println(new java.util.Date().toLocaleString()); %></h3> </body> </html>
- 语法说明:
- include指令只有一个file属性,该属性用来指定插入到JSP页面目标位置的文件资源
- 注意:插入文件的路径一般不以/开头而是使用相对路径
- include指令可以放在JSP页面的任何一行,放在哪个位置,包含页面的内容就显示在那里,可以将包含的JSP页面的代码合并到当前所在的JSP文件中
- 注意:
- 1.被引入的文件必须遵循JSP语法,其中的内容可以包含静态HTML,JSP脚本元素等JSP页面所具有的一切内容
- 2.除了指令元素之外,被引入的文件中的其他元素都被转换成了相应的Java源代码,然后插入当前的JSP页面所翻译的Servlet源文件中,插入位置与incllude指令在当前JSP页面中的位置保持一致
- 3.file属性的设置值必须使用相对路径,如果以/开头表示相对于当前Web应用程序的根目录(注意不是站点根目录),否则表示相对于当前文件;这里的file属性制动的路径是相对于文件file而不是相对于页面page
3.taglib指令
- 作用:声明可用的标签库,JSTL标签库
- 基本语法:
<%@ taglib prefix="c" url="地址" %>
- 语法说明:
- prefix表示前缀
4.JSP动作元素
- JSP动作元素用来控制JSP的行为,执行一些常用的JSP页面动作。通过动作元素可以实现使用多行代码能够实现的效果(例:包含页面文件,实现请求转发等)
- 基本语法:
<%@ 指令名 属性名1="属性值1" ... %>
- JSP动作元素:
- 1.< jsp:include>动作元素
- 2.< jsp:forward>动作元素
1.< jsp:include>动作元素
- < jsp:include>动作元素用来把其他资源的输出内容插入到当前JSP页面的输出内容中
- 基本语法:
<jsp:include page="relativeURL" flush="true|false" />
属性名称 描述 page 用于指定被引入资源的相对路径 flush 用于指定是否将当前页面的输出内容刷新到客户端,默认情况flush属性的值为false <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>当前时间</title> </head> <body> <% Thread.sleep(5000); %> <h3><% out.println(new java.util.Date().toLocaleString()); %></h3> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h3>欢迎你,现在时间是:</h3> <jsp:include page="Date.jsp" flush="true"></jsp:include> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h3>欢迎你,现在时间是:</h3> <jsp:include page="Date.jsp" flush="false"></jsp:include> </body> </html>
- 语法说明:
- < jsp:include>包含的原理是将被包含的页面编译处理处理后将结果包含在页面中。当浏览器第一次请求一个使用< jsp:include>包含其他页面的页面时,Web容器首先会编译被包含的页面,然后将编译处理后的返回结果包含在页面中,之后编译包含页面,最后将两个页面组合的结果回应给浏览器
- Include.jsp页面用于引入Date.jsp页面,Date.jsp作为被引入的文件,让他暂停5秒钟后才输出时间,用来测试< jsp:include>标签的flush属性
- 1.启动Tomcat服务器,访问地址http://localhost:8080/FirstWeb1/Include.jsp后发现浏览器首先会显示include.jsp页面的输出内容。说明被引用的资源Date.jsp在当前JSP页面输出内容后才被调用
- 2.修改include.jsp文件,将< jsp:include>动作元素的flush属性设置为false,再次访问地址http://localhost:8080/FirstWeb1/Include.jsp,这时浏览器等待5秒后将Include.jsp和Date.jsp页面的的输出内容同时显示了出来。由此可见Tomcat调用被引入资源Date.jsp时并没有将当前JSP页面中已输出的内容刷新到客户端
- 区分include指令和< jsp:include>动作标签
- 1.< jsp:include>标签中要引入的资源和当前JSP页面是两个彼此独立的执行实体,即被动态引入的资源必须能够被Web容器独立执行。而include指令只能引入遵循JSP格式的文件,被引入文件与当前JSP文件需要共同合并才能翻译成一个Servlet源文件
- 2.< jsp:include>标签中引入的资源是在运行时才包含的,而且只包含运行结果。而include指令引入的资源是在编译时期包含的,包含的是源代码
< jsp:include>标签
include指令
- 3.< jsp:include>标签运行原理与RequestDispatcher.include()方法类似,,即被包含的页面不能改变响应状态码或者设置响应头。而include指令没有这方面的限制
1.< jsp:forward>动作元素
- < jsp:forward>动作元素将当前请求转发到其他Web资源(html页面。jsp页面,Servlet等),在执行请求转发之后的当前页面将不再执行,而是执行该元素指定的目标页面
- 基本语法:
<jsp:forward page="relativeURL"/>
属性名称 描述 page 用于指定请求转发到的资源的相对路径,该路径是相对于当前JSP页面的URL <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>当前时间</title> </head> <body> <h3>你好,欢迎进入首页,当前访问的时间是:</h3> <h3><% out.println(new java.util.Date().toLocaleString()); %></h3> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h3>欢迎你,现在时间是:</h3> <jsp:forward page="Date.jsp" /> </body> </html>
- 语法说明:
- 从结果看出:虽然地址栏中访问的是IncludeTest.jsp,但浏览器显示出了welcome.jsp页面的输出内容。由于请求转发是服务器端的操作,浏览器并不知道请求的页面,所以浏览器的地址栏不会发生变化
4.JSP内置(隐式)对象(9个)
在JSP页面中,有一些对象需要频繁使用,如果每次都要重新创建这些对象则会非常麻烦。为了简化Web应用程序的开发,JSP2.0规范中提供了9个内置(隐式)对象,他们是JSP页面默认创建的,可以直接在JSP页面中使用
名称 类型 描述 out javax.servlet.jsp.JspWriter 用于页面输出 request javax.http.HttpServletRequest 得到用户请求信息 response javax.http.HttpServletResponse 服务器向客户端的回应信息 config javax.servlet.ServletConfig 服务器配置,可以取得初始化参数 session javax.servlet.http.HttpSession 用来保存用户的信息 application javax.servlet.ServletContext 所有用户的共享信息 page java.lang.Object 指当前页面转换后的Servlet类的实例 pageContext java.servlet.jsp.PageContext JSP的页面容器 exception java.lang.Throwable 表示JSP页面所发生的异常,在错误页中才起作用
1.out对象
- JSP页面中out对象用来向客户端发送文本内容
- out对象是javax.servlet.jsp.JspWriter类的实例对象,它的作用与ServletResponse.getWriter()方法返回的PrintWriter对象非常相似,都是用来向客户端发送文本形式的实体内容。不同的是out对象的类型为JspWriter,它相当于一种带缓冲功能的PrintWriter
- 在JSP页面中,通过out隐式对象写入数据相当于将数据插入到JspWriter对象的缓冲区中,只有调用了ServletReponse.getWriter()方法,缓冲区中的数据才能真正写入到Servlet引擎所提供的缓冲区中
- out对象被封装成javax.servlet.JspWriter接口,用来向客户端输出内容。out变量是从PageContext对象初始化而获得的,out对象的作用域是page
- 基本语法:
<% out.方法 %>
方法名 方法功能 print() 输出各种类型数据 println() 输出各种类型数据并换行 newLine() 输出一个换行符 close() 关闭输出流 flush() 输出缓冲区里的数据 clearBuffer() 清除缓冲区里的数据,并把数据写到客户端 clear() 清除缓冲区里的数据,但不写到客户端 getBufferSize 获得缓冲区的大小 getRemaining 获得缓冲区剩余空间的大小 isAutoFlush 判断缓冲区是否自动刷新 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>out对象</title> </head> <body> <% out.println("<h3>out对象应用实例</h3>"); out.println("<br/>输出布尔型数据:"); out.println(true); out.println("<br/>输出字符型数据:"); out.println('l'); out.println("<br/>输出字符组数据:"); out.println(new char[]{'l','z','c'}); out.println("<br/>输出双精度数据:"); out.println(5.66d); out.println("<br/>输出单精度数据:"); out.println(35.2f); out.println("<br/>输出整型数据:"); out.println(8); out.println("<br/>输出长整型数据:"); out.println(12345678912345L); out.println("<br/>输出对象:"); out.println(new java.util.Date()); out.println("<br/>输出字符串:"); out.println("<font size=4 color=red>liuzc@hnrpc.com</font>"); out.println("<br/>输出新行:"); out.newLine(); out.println("<br/>缓冲区大小:"); out.println(out.getBufferSize()); out.println("<br/>缓冲区剩余大小:"); out.println(out.getRemaining()); out.println("<br/>是否自动刷新:"); out.println(out.isAutoFlush()); out.flush(); out.println("<br/>调用out.flush()"); out.close(); out.println("这一行信息不会输出"); %> </body> </html>
- 语法说明:
- out.println()方法是将内容输出到客户端,System.out.println()方法是将内容输出到控制台
- 在out.println()方法中使用html标签需要带上双引号
2.request对象
- request对象是和请求相关的HttpServletRequest类的一个对象,该对象封装了用户提交的信息,通过调用该对象相应的方法可以获取封装的信息
- 使用该对象可以查看请求参数的配置情况(调用getParameter),请求的类型(如:Get,Post,Head等),已经请求的HTTP头(如:Cookie,Referer等)
- 基本语法:
<% request.方法 %>
方法名 方法功能 getAttribute(String name) 获得由name指定的属性的值,如果不存在指定的属性,返回空值(null) setAttribute(String name,java.lang.Object obj) 设置名字为name的request参数的值为obj getCookie 返回客户端的Cookie对象,结果是一个Cookie数组 getHeader(String name) 获得HTTP定义的传送文件头信息 getHeaderName() 返回所有request header的名字,结果保存在一个Enumeration类的实例中 getScheme() 返回HTTP请求方式 getServerName(String name) 获得服务器的名字 getServerPort(String name) 获得服务器的端口号 getRemoteAddr() 获得客户端的IP地址 getRemoteHost() 获得客户端的计算机名字 getProtocol() 获得客户端向服务器端传送数据的协议名称 getMethod() 获得客户端向服务器端传送数据的方法 getServletPath() 获得客户端所请求的脚本文件的文件路径 getCharacterEncoding() 获得请求中的字符编码方式 getSession(Boolean create) 返回和请求相关的Session getParameter(String name) 获得客户端传送给服务器端的参数值 getParameterNames() 获得所有的参数值的名字 getParameterValues() 获得指定的参数值 getQueryString() 获得查询字符串,该串由客户端GET方法方法向服务器传递 getRequestURl() 获得发出请求字符串的客户端地址 getContentLength() 获得内容的长度 1.使用request对象获取HTML表单信息
- input.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>账户登录</title> </head> <body> <form action="requestObject.jsp" method="post" id="form1" name="form1"> <table> <tr> <td> 用户名: </td> <td> <input type="text" name="username" form="form1"/> </td> </tr> <tr> <td> 密码: </td> <td> <input type="password" name="pwd" form="form1"/> </td> </tr> <tr> <td> 爱好: </td> <td> <input type="checkbox" name="habit" value="read" form="form1"/>读书 <input type="checkbox" name="habit" value="movie" form="form1"/>电影 <input type="checkbox" name="habit" value="game" form="form1"/>游戏 </td> </tr> <tr> <td> <input type="submit" value="提交" name="submit" form="form1"/> </td> <td> <input type="reset" value="取消" name="cancel" form="form1"/> </td> </tr> </table> </form> </body> </html>
- requestObject.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>request对象</title> </head> <body> <p>获取用户名: <% String username = request.getParameter("username"); %> <%= username %> <p>获取密码: <% String pwd = request.getParameter("pwd"); %> <%= pwd %> <p>获取按钮1的名称: <% String buttom1 = request.getParameter("submit"); %> <%= buttom1 %> <p>获取按钮2的名称: <% String buttom2 = request.getParameter("cancel"); %> <%= buttom2 %> <p>获取参数值的名字: <% Enumeration e = (Enumeration)request.getParameterNames(); %> <% while(e.hasMoreElements()){ String parName=(String)e.nextElement(); out.print("<br/>"+parName+"<br/>"); } %> <p>获取爱好: <% String habit1 = request.getParameter("habit"); %> <%= habit1+"<br/>" %> <% String[] habit= request.getParameterValues("habit"); %> <% for(String h:habit){ out.println(h+"<br/>"); } %> </body> </html>
- 语法说明:
- 1.使用request对象获取信息要避免使用空对象(null),否则会出现NullPointerException异常
- 2.request对象的getParameter(String name)获得的是客户端传送给服务器端指定的参数值,即:value值,如果没有发生传递则参数值为null;而getParameterValues()获取的是客户端传送给服务器端指定的一个String数组,其值为name为相同的一组的value值,结果保存在String数组中
- 3.一般form表单中的submit是将客户端的参数传递给服务器端
- 4.getParameterNames()方法用来获取表单的中所有的name名称,该结果是一个Enumeration类型,且需要导入java.util.Enumeration包
2.使用request对象获取复杂表单信息
- exam.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JSP程序设计网上测试系统</title> </head> <body> <form action="examRequest.jsp" method="post" name="form2"> 请输入姓名:<input type="text" name="username"/><br/> 请选择班级: <select name="class" size="1"> <option selected value="计科一班">计科一班 <option value="计科二班">计科二班 <option value="计科三班">计科三班 </select><br/> <p>在JSP中,可以获得用户表单提交的信息的内置对象是:()<br/> <input type="radio" name="t1" value="a"/>response对象 <input type="radio" name="t1" value="b"/>request对象 <br/> <input type="radio" name="t1" value="c"/>session对象 <input type="radio" name="t1" value="d"/>application对象 <br/> <p>在SQL语言中,为了实现数据的更新,使用的命令是:()<br/> <input type="radio" name="t2" value="a"/>update语句 <input type="radio" name="t2" value="b"/>insert语句 <br/> <input type="radio" name="t2" value="c"/>select语句 <input type="radio" name="t2" value="d"/>delete语句 <br/> <input type="submit" value="提交答案" name="submit"/> </form> </body> </html>
- examRequest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>exam处理页面</title> </head> <body> <font size=3> <% int n=0; String strName=request.getParameter("username"); String strClass=request.getParameter("class"); String strTemp=strClass + "的" + strName; String s1=request.getParameter("t1"); String s2=request.getParameter("t2"); if(s1==null){ s1=""; } if(s2==null){ s2=""; } if(s1.equals("b")){ n++; } if(s2.equals("a")){ n++; } %> <%=strTemp%> <p>你的得分为:<%=n%>分</p> </font> </body> </html>
- 语法说明:
- 需要对s1,s2进行null处理
3.使用request对象处理null参数
- requestNull.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>处理Null</title> </head> <body bgcolor="cyan"> <font size=5> <form> <input type="text" name="null"/> <input type="submit" value="enter" name="submit"/> </form> <% String strContent=request.getParameter("null"); double number=0; double r=0; if(strContent == null){ strContent=""; } try{ number=Double.parseDouble(strContent); if(number>=0){ r=Math.sqrt(number); out.println("<br/>"+String.valueOf(number)+"平方根:"); out.println("<br/>"+String.valueOf(r)); }else{ out.println("请输入一个正数"); } }catch(NumberFormatException e){ out.println("<br/>"+"请输入数字字符"); } %> </font> </body> </html> ```![在这里插入图片描述](https://img-blog.csdnimg.cn/20210330164156466.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3d1MjQ2MDUx,size_16,color_FFFFFF,t_70)
- 语法说明:
- 如果将
if(strContent == null){strContent="";}
去掉就会出现NullPointerException异常
4.使用request对象的其他方法
- requestNull.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>request对象方法演示</title> </head> <body> <table border="1"> <tr> <td> 通信协议: </td> <td> <%= request.getProtocol() %> </td> </tr> <tr> <td> 请求方式: </td> <td> <%= request.getScheme() %> </td> </tr> <tr> <td> 服务器名称: </td> <td> <%= request.getServerName() %> </td> </tr> <tr> <td> 通信端口: </td> <td> <%= request.getServerPort() %> </td> </tr> <tr> <td> 使用者IP: </td> <td> <%= request.getRemoteAddr() %> </td> </tr> <tr> <td> 主机地址: </td> <td> <%= request.getRemoteHost() %> </td> </tr> <tr> <td> 传送方法: </td> <td> <%= request.getMethod() %> </td> </tr> <tr> <td> 客户端所请求的脚本文件的文件路径: </td> <td> <%= request.getServletPath() %> </td> </tr> <tr> <td> 请求中的字符编码方式: </td> <td> <%= request.getCharacterEncoding() %> </td> </tr> <tr> <td> 返回和请求相关的Session: </td> <td> <%= request.getSession(false) %> </td> </tr> <tr> <td> 获得查询字符串,该串由客户端GET方法方法向服务器传>递: </td> <td> <%= request.getQueryString() %> </td> </tr> <tr> <td> 获得内容的长度: </td> <td> <%= request.getContentLength() %> </td> </tr> </table> </body> </html>
5.使用GET方法和POST方法提交数据
get方法login.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>方法提交数据</title> </head> <body> <form action="getLogin.jsp" method="get"> <p>用户名:<input type="text" name="username" size="18"></p> <p>密码:<input type="password" name="pwd" size="20"></p> <p> <input type="submit" value="提交" name="submit"> <input type="reset" value="重置" name="reset"> </p> </form> </body> </html>
<!DOCTYPE html> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>处理Get方法传递参数</title> </head> <body> <% String strUser=request.getParameter("username"); String strPwd=request.getParameter("pwd"); if(strUser.equals("wudong") && strPwd.equals("123456")){ out.println("<h3>用户登录成功</h3>"); }else{ out.println("<h3>用户登录失败</h3>"); } %> </body> </html>
post方法login.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>方法提交数据</title> </head> <body> <form action="postLogin.jsp" method="post"> <p>用户名:<input type="text" name="username" size="18"></p> <p>密码:<input type="password" name="pwd" size="20"></p> <p> <input type="submit" value="提交" name="submit"> <input type="reset" value="重置" name="reset"> </p> </form> </body> </html>
<!DOCTYPE html> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>处理Post方法传递参数</title> </head> <body> <% String strUser=request.getParameter("username"); String strPwd=request.getParameter("pwd"); if(strUser.equals("wudong") && strPwd.equals("123456")){ out.println("<h3>用户登录成功</h3>"); }else{ out.println("<h3>用户登录失败</h3>"); } %> </body> </html>
语法说明:
- 通过get方法提交数据会将所有数据显示在URL地址的后面,同时会将一些显示的隐藏信息显示出来,这样会存在许多不安全的因素
- 而通过post方法提交数据不会将所有数据显示在URL地址的后面,更加安全
3.response对象
response是和应答相关的HttpServletResponse类的一个对象,封装了服务器对客户端的响应,然后被发送到客户端以响应客户请求
- response对象产生的对客户的请求做出动态的响应,并向客户端发送数据。HttpServletResponse对象具有页面作用域
基本语法:
<% response.方法 %>
方法名 方法功能 addHeader(String name,String value) 添加HTTP文件头,该文件夹将会传递到客户端 setHeader(String name,String value) 设置指定名字的HTTP文件头值 containsHeader(String name) 判断指定名字的HTTP文件头是否存在 addCookie(Cookie cook) 添加一个Cookie对象,用来保存客户端的用户信息 encodeURL() 使用sessionId来封装URL flushBuffer() 强制将当前缓冲区的内容发送到客户端 getBufferSize() 返回缓冲区的大小 sendError(int sc) 向客户端发送错误信息 sendRedirect(String location) 把响应发送到另一个指定的位置进行处理 getOutputStream() 返回到客户端的输出流对象 setContentType() 动态改变contentType属性 1.使用response对象保存文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>response对象的setContentType方法演示</title> </head> <body bgcolor="cyan"> <font size="3"> <p>将当前页面保存为Word文档吗?</p> <form action="" method="get" name="form"> <input type="submit" value="yes" name="submit"> <input type="button" value="no" name="cancel"> </form> </font> <% String str=request.getParameter("submit"); if(str==null){ str=""; } if(str.equals("yes")){ response.setContentType("application/msword;charset=UTF-8"); } %> </body> </html> </html>
语法说明:
2.使用response对象实现重定向
在某些情况下,当响应客户时,需要将客户重新引导至另一个页面,可以使用response的sendRedirect(URL)方法实现客户的重定向
goto.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>重定向演示</title> </head> <body> <b>友情链接</b><br/> <form action="responseGoto.jsp" method="get"> <select name="where"> <option value="baidu" selected>百度 <option value="souhu">搜狐 <option value="tengxun">腾讯 </select> <br/> <input type="submit" value="跳转" name="submit"> </form> </body> </html>
responseGoto.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>response对象的sendRedirect方法演示</title> </head> <body> <% String address=request.getParameter("where"); if(address!=null){ if(address.equals("baidu")){ response.sendRedirect("http://www.baidu.com"); }else if(address.equals("souhu")){ response.sendRedirect("http://www.souhu.com"); }else if(address.equals("tengxun")){ response.sendRedirect("https://v.qq.com/"); } } %> </body> </html>
语法说明:
3.使用response刷新页面
- 在某些情况下,当响应客户时,需要将客户重新引导至另一个页面,可以使用response的sendRedirect(URL)方法实现客户的重定向
- responseDemo2.html
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.util.*" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>动态刷新页面</title> </head> <body> <% response.setHeader("refresh","2"); out.println(new Date().toLocaleString()); %> </body> </html>
- 语法说明:
4.session对象
session对象是与HttpSession对象请求相关的,它封装了属于客户会话的所有信息
session对象也是一个JSP内置对象,在第一个JSP页面被装载时自动创建,完成会话期管理
从一个客户端打开浏览器并连接到服务器开始,到客户端关闭浏览器离开这个服务器结束,被称为一个会话
当一个客户访问一个服务器时,可能会在这个服务器的几个页面之间反复连接,反复刷新一个页面,服务器应当通过某种办法知道这是同一个客户,这就需要session对象
session对象的Id是指当一个客户首次访问服务器上的一个JSP页面时,JSP引擎产生一个session对象,同时分配一个字符类型的Id号,JSP引擎同时将这个ld号发送给客户端,存放在Cookie中,这样session对象和客户之间就建立了一一对应的关系。当客户端再访问该服务器的其他页面时,不再分配给客户新的session对象,直到客户关闭浏览器后,服务器端将该客户的session对象取消,服务器与该客户的会话对应关系消失。当客户重新打开浏览器再连接到该服务器时,服务器会为该客户再创建一个新的session对象
基本语法:
<% session.方法 %>
方法名 方法功能 getAttribute(String name) 获得指定名字的属性 getAttributeNames() 返回sessioon对象中存储的每一个属性对象 getCreationTime() 返回session对象的创建时间 getId() 返回当前session对象的编号 getLastAccessdTime() 返回当前session对象最后一次被操作的时间 getMaxInactiveInterval() 获取session对象的生存时间 removeAttribute() 删除指定属性的属性值和属性名 setAttribute(String name,Object obj) 设置指定名字的属性 Invalidate() 注销当前的session isNew() 判断是否是一个新的session 1.session对象实现网站计数器
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>session网站计数器</title> </head> <body> <%! int number=0; synchronized void countpeople(){ number++; } %> <% if(session.isNew()){ countpeople(); String str=String.valueOf(number); session.setAttribute("count",str); } %> <p>你是第<%=(String)session.getAttribute("count") %>个访问本站的人 </body> </html>
语法说明:
- 在同步方法(synchronized)中实现计数器的累加
- 注意需要从不同的机器上打开该jsp页面或者关闭浏览器后重新打开浏览器才有作用,因为当客户重新打开浏览器再连接到该服务器时,服务器才会为该客户再创建一个新的session对象
2.使用session对象记录表单信息
login1.html<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>登录网页</title> </head> <body> <form action="login1.jsp" method="post"> <p>用户名:<input type="text" name="username" size="18"/></p> <p>密码:<input type="password" name="pwd" size="20"/></p> <p><input type="submit" name="submit" value="提交"><input type="reset" name="reset" value="重置"/></p> </form> </body> </html>
login1.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>登录响应网页</title> </head> <body> <% String username=request.getParameter("username"); String pwd=request.getParameter("pwd"); if(username==null||pwd==null){ username=""; pwd=""; } if(username!=""&&pwd!=""){ if(username.equals("wuyong")&&pwd.equals("123456")){ session.setAttribute("login","OK"); session.setAttribute("username", username); response.sendRedirect("welcome.jsp"); }else{ out.println("<h2>登录错误,请输入正确的用户名和密码</h2>"); out.println("<h2>5秒后自动跳转到登录页面</h2>"); response.setHeader("refresh","5,URL=login1.html"); /* response.sendRedirect("login1.html"); */ } }else{ out.println("<h2>请输入的用户名和密码</h2>"); out.println("<h2>5秒后自动跳转到登录页面</h2>"); response.setHeader("refresh","5,URL=login1.html"); /* response.sendRedirect("login1.html"); */ } %> </body> </html>
welcome.html
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <% String strLogin=(String)session.getAttribute("login"); String strUser=(String)session.getAttribute("username"); if(strLogin==null){ out.println("<h2>请先登录,谢谢!</h2>"); out.println("<h2>5秒后自动跳转到登陆页面</h2>"); response.setHeader("refresh","5,URL=login1.html"); }else{ if(strLogin.equals("OK")){ out.println(strUser+"<h2>欢迎进入我们的网站</h2>"); } } %> </body> </html>
语法说明:
- 跳转页面有时间延迟时最好用response.setHeader()方法,可以设置延迟时间;没有延迟时间可以用response.sendRedirect();
- session.setAttribute()方法和session.getAttribute()方法可以搭配使用,作用范围在一个会话的生存期
- 如果不是从登录页面登录,而是在浏览器的地址栏直接输入地址,会提示用户要先登录,并自动跳转到登录页面
5.application对象
application对象提供了对javax.servlet.ServletContext对象的访问,用于多个程序或多个用户之间共享数据。对于一个容器而言,每个用户都共用一个application对象,这和session对象不同
服务器启动后就产生了这个application对象,当客户在所访问的网站的各个页面之间浏览时,这个application对象都是同一个,直到服务器关闭。
与session不同的是,所有客户的application对象都是同一个,即所有客户共享这个内置的application对象
基本语法:
<% application.方法 %>
方法名 方法功能 getAttribute(String name) 获得指定名字的application对象属性的值 setAttribute(String name,Object obj) 用object来初始化某个由name指定的属性值 getAttributeNames() 返回application对象中存储的每一个属性名字 getInitParameter(String name) 返回application对象某个属性的初始值 removeAttribute(Stirng name) 删除一个指定的属性 getServerInfo() 返回当前版本的Servlet储存器的信息 getContext(URI) 返回指定URI的ServletContext getMajorVersion() 返回Servlet API的版本 getMimeType(URI) 返回指定的URI的文件格式 getRealPath(URI) 返回指定URI的实际路径 1.application对象读写属性的应用
applicationDemo1.jsp<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Application应用实例</title> </head> <body> <% application.setAttribute("username", "liuxusheng"); application.setAttribute("pwd","liu123456"); %> <jsp:forward page="applicationDemo2.jsp"></jsp:forward> </body> </html>
applicationDemo2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>application应用演示</title> </head> <body> <% String username = (String)application.getAttribute("username"); String pwd = (String)application.getAttribute("pwd"); out.println("username=" + username + "<br/>"); out.println("password=" + pwd); %> </body> </html>
2.使用application制作站点计数器
applicationDemo1.jsp<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>application计数器</title> </head> <body> <center><font size="5" color="blue">Application计数器</font></center> <hr/> <% String strNum = (String)application.getAttribute("num"); int num = 1; if(strNum != null){ num = Integer.parseInt(strNum) + 1; } application.setAttribute("num",String.valueOf(num)); %> <font size="3"><b>访问次数为:</b></font> <font color="red" size="3"><b><%= num %></b></font> </body> </html>
6.page对象
- page对象是可以从JSP脚本小程序和表达式中获得的一个内置对象
- 它是java.lang.Object类的一个实例
- 当脚本语言为Java时,page对象只是thi引用的一个代名词
7.config对象
- config对象提供了对每一个给定的服务器小程序及JSP页面的javax.servlet.ServletConfig对象的访问
方法名 方法功能 getInitParameter(String name) 获得初始化参数 getInitPatameterNames() 获得所有初始化参数的名称 getServletName() 获得当前服务器小程序或JSP页面的名称 getServletContext() 获得当前服务器或JSP页面的环境
8.pageContext对象
- pageContext对象提供了对JSP页面内所在的对象及名字空间的访问
- 既可以访问本页所在的session,也可以取本页面所在的application的属性值,它是页面中所以功能的集大成者
方法名 方法功能 forword(String url) 把页面重定向到另外一个页面或者servlet组件上 getAttribute(String name[,int scope]) 获得某一指定范围内的属性值 getException() 返回当前的exception对象 getRequest() 返回当前的request对象
9.exception对象
- exception对象是Java.lang.Throwable类的一个实例
- 它指的是运行时的异常,也就是被调用的错误页面的结果,只有在错误的页面才可以被使用
Cookie对象
Cookie是Web服务器保存在用户硬盘上的一段文本,Cookie允许一个Web站点在用户的计算机上保存信息并且随后再将其取回
浏览器与Web服务器之间是使用HTTP进行通信的,当某个用户发出页面请求时,Web服务器只是简单地进行响应,然后就关闭与该用户的连接。因此当一个请求发送到Web服务器时,无论是否是第一次来访,服务器都会当做第一次来对待。
为了弥补这个缺陷,Netscape开发出了Cookie这个有效工具来保存某个用户的识别信息。Cookie是一种Web服务器通过浏览器在访问者的硬盘上存储信息的手段:Netscape Navigator使用一个名为cookies.txt的本地文件保存从所有站点接收的Cookie信息;而IE浏览器把Cookie信息保存在类似于C:\XXX\cookies的目录下。当用户在访问某个站点时,服务器端将要求浏览器查找并返回先前发送的Cookie信息来识别这个用户
Cookie的优点:
- 1.Cookie能使站点跟踪特定访问者的访问次数,最后访问时间和访问者进入站点的路径
- 2.Cookie能告诉在线广告商广告被点击的次数,从而可以更精确地投放广告
- 3.Cookie有效期未到时,用户无需重复输入密码和用户名可以直接进入曾经浏览过的一些站点
- 4.Cookie能帮助站点统计用户个人资料以实现各种各样的个性化服务
服务器读取Cookie的时候,只能读取到这个服务器相关的信息,而且浏览器一般只允许存放300个Cookie,每个站点最多存放20个,每个Cookie的大小为4KB;同时Cookie是具有时效性质的
由于代理服务器,缓存等的使用,帮助网站精确统计来访人数的比较好的一个方法就是为每个访问者创建一个唯一的ID。当一个用户第一次访问时,网站在数据库中建立一个新的ID,并把ID通过Cookie传送给用户,当用户再次来访时,网站把该用户ID对应的计数器加1,得到用户的来访次数。借助Cookie,网站可以完成以下工作
- 测定多少人访问过
- 测定访问者有多少是新用户(即第一次来访),多少是老客户
- 测定一个用户多久访问一次网站
基本语法:
Cookie是以“关键字=值”(key=value)的格式来保存记录的,其基本操作包括创建,传送和读取 1.创建Cookie对象 调用Cookie对象的构造函数可以创建Cookie。Cookie对象的构造函数有两个字符串参数:Cookie的名字和Cookie的值 Cookie c = new Cookie("username","liuxusheng"); 2.传送Cookie对象 JSP中如果要将封装好的Cookie对象传送到客户端,使用response的addCookie()方法 response.addCookie(c); 3.读取Cookie对象 读取保存到客户端的Cookie是使用request对象的getCookies()方法。 执行时将所有客户端传来的Cookie对象以数组的形式排列,如果要取出符合需要的Cookie对象,就需要循环比较数组内每个对象的关键字 Cookie[] c = response.getCookies(); if(c!=null){ for(int i=0; i<c.length(); i++){ if("username".equals(c[i].getName())){ out.println(c[i].getValue()); } } } 4.设置Cookie对象的有效时间 设置Cookie对象有效时间可以使用setMaxAge()方法。如果设置其时间为0,则表示删除该Cookie c.setMaxAge(值);
比较项目 Cookies session 存在期限 浏览器未关闭之前及设定时间内 浏览器未关闭之前及默认时间内 存在方式 客户端 服务器 数量限制 20(同一服务器) 无 类 Cookie session 处理速度 快 慢 1.使用Cookie对象制作站点计数器
CookieDemo1.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>基于Cookie对象的站点计数器</title> </head> <body> <% //创建thisCookie对象,初始值为null Cookie thisCookie = null; //设置逻辑变量cookieFound,用来判断指定的Cookie在cookie数组中是否找到 boolean cookieFound = false; //应用request.getCookies()方法请求获取cookies数组 Cookie[] cookies = request.getCookies(); //遍历cookies数组,检查是否存在名为CookieCount的cookie if(cookies!=null){ for(int i=0; i<cookies.length; i++){ //将cookies数组中的某一数组元素赋值给thisCookie对象 thisCookie = cookies[i]; //应用thisCookie.getName()方法获取cookies数组元素的名称并与名称CookieCount进行比较,检查CookieCount是否存在 if(thisCookie.getName().equals("CookieCount")){ cookieFound = true; break; } } } out.println("<center><h1>Cookie计数器</h1></center>"); //如果指定的CookieCount存在,则首先获取Cookie的值并且加1,然后将Cookie的新值写入相应对象thisCookie中 if(cookieFound){ int cookieCount = Integer.parseInt(thisCookie.getValue()); cookieCount++; out.println("<font color=bule size=+1>"); out.println("<p>这是你第<b>"+cookieCount+"</b>访问本页面</p>"); thisCookie.setValue(String.valueOf(cookieCount)); //设置Cookie的生存时间 thisCookie.setMaxAge(60); //应用response.addCookie()方法将更新后的Cookie值传送到客户端 response.addCookie(thisCookie); } if(cookieFound==false){ out.println("<font color=bule size=+1>"); out.println("<p>你在近一分钟内没有访问过此页面,现在是第一次访问此页"); thisCookie = new Cookie("CookieCount","1"); thisCookie.setMaxAge(60); response.addCookie(thisCookie); } %> </body> </html>
5.对象作用范围
请作用域(request)
- 每当客户发出HTTP请求时,服务器会创建一个实现javax.servlet.http.HttpServletRequest接口的对象,此对象包含一个由属性(key/value)构成的集合,用来存储各种对象,以供该请求在其生命周期中使用
- 属性的作用域局限在请求的生命周期中,当服务器完成请求,响应也回馈给客户时,请求及其属性对客户而言没有什么价值,由JVM当做垃圾回收
会话作用域(session)
- Web容器会创建一个实现了javax.servlet.http.HttpSession接口的对象,用来识别某个跨多个页面请求的用户,即会话。
- 会话建立的时机是由应用程序和容器实现来决定的。用户的会话会保持一段时间,可以通过应用程序的部署描述文件(deployment descriptor)来配置或调用会话对象上的invalidate()方法来撤销会话
页面作用域(page)
- 页面作用域只和JSP页面有关。有页面作用域的对象都会存储在每个页面的javax.servlet.jsp.PageContext里,并且只有所属的JSP页面才可以存取这些对象,一旦响应返回客户或者页面转发到其他资源,这些对象就不能再使用了
对象名 作用范围 request 请求作用域,就是客户端的一次请求(可以包含多个页面) seesion 会话作用域,当用户首次访问时,产生一个新的会话,以后服务器就可以记住这个会话状态。生命周期是会话超时,或者服务器端强制使会话失效 application 全局作用域,整个应用程序共享,就是在部署文件中的同一个webapp共享,生命周期为应用程序启动到停止 page 一个JSP页面
EL表达式
- 1.JSP开发中为了获取Servlet域对象中存储的数据,需要书写很多java代码,会使JSP页面混乱,难以维护
- 2.JSP2.0规范中提供了EL表达式
- 3.EL(Expression Language)是一种简单的数据访问语言
1.EL语法格式
- 1.EL表达式的语法格式
${表达式}
- 2.例:对比使用Java代码与EL表达式的区别
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>获取数据</title> </head> <body> <form action="MyjspServlet" method="post"> 用户名:<%=request.getAttribute("username")%><br> 密码:<%=request.getAttribute("pwd")%><br> 用户名:${username}<br> 密码:${pwd}<br> 测试:${ceshi}<br> <input type="submit" value="提交"> </form> </body> </html>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub request.setAttribute("username", "myjsp"); request.setAttribute("pwd", "123456"); request.getSession().setAttribute("ceshi", "success"); RequestDispatcher dispatcher = request.getRequestDispatcher("/myjsp.jsp"); dispatcher.forward(request, response); }
- 3.语法说明:
- 1.当域对象里面的值不存在时,使用EL表达式获取域对象里面的值时返回空字符串;使用Java方式获取域对象里面的值时返回null;
- 2.使用Java方式获取返回值是null时会报空指针异常,即:推荐使用EL表达式获取域对象中存储的数据
2.EL标识符
- 1.EL表达式中需要使用一些符号来标记一些名称,这些符号被称为标识符
- 2.EL表达式中的标识符可以由任意的大小写字母,数字和下划线组成
- 3.定义标识符的规范
- 1.不能以数字开头
- 2.不能是EL中的保留字
- 3.不能是EL的隐式对象
- 4.不能包含单引号,双引号,减号和正斜杠等特殊字符
3.EL保留字
- 1.保留字是事先定义好并赋予含义的单词
- 2.EL保留字
and eq gt true or ne le false not lt ge null - 3.保留字不能被作为标识符
4.EL变量
- 1.EL表达式中的变量就是一个基本的存储单元
- 2.EL表达式可以将变量映射到一个对象上
${product}
- 3.语法说明:
1.product是一个变量
2.EL中的变量不用事先定义就可以直接使用
3.${product}可以访问变量product的值
5.EL常量
- 1.EL表达式中的常量又称为字面量,它是不能改变的数据
1.布尔常量
- 1.布尔常量用于区分一个事物的正反两面
- 2.它只有两个值,分别是true和false
2.整型常量
- 1.整型常量与Java中的十进制的整型常量相同
- 2.取值范围是(-2)63与263-1之间的整数
3.浮点数常量
- 1.浮点数常量用整数部分加小数部分表示,也可以使用指数形式表示
- 2.取值范围是4.9E-324 ~ 1.8E308之间的浮点数
4.字符串常量
- 1.字符串常量是用单引号或双引号引起来的一连串字符
- 2.字符串本身包含的单引号或双引号或反斜杠需要用反斜杠( \ )进行转义
- 3.只有相同类型的符号才需要转义,不同类型的不需要转义
5.Null常量
- 1.Null常量用于表示变量引用的对象为空,它只有一个值用null表示
6.EL运算符
- 注意:应用EL表达式取值时,没有数组的下标越界,没有空指针异常,没有字符串的拼接
1.点运算符( . )
- 1.EL表达式中的点运算符,用于访问JSP页面中的某些对象的属性(例:JavaBean对象,List集合,Array数组等)
- 2.语法格式:
${customer.name}
- 3.语法说明:
- 1.表达式${customer.name}中点运算符的作用就是访问customer对象中的name属性
2.方括号运算符([ ])
- 1.EL表达式中的方括号运算符与点运算符的功能相同,都用于访问JSP页面中某些对象的属性
- 2.当获取的属性名中包含一些特殊的符号(例:-,?)等非字母或数字的符号,就只能使用方括号运算符来访问该属性
- 3.语法格式:
${user["my-name"]}
- 4.语法说明:
- 1.点运算符和方括号运算符在某些情况下可以互换(例:$ {student.name} 等价于${student[“name”]})
- 2.方括号运算符可以访问List集合或数组中指定索引的某个元素(例:${User[0]}用于访问集合或数组中的第一个元素),这种情况下只能使用方括号运算符,不能使用点运算符
- 3.方括号运算符和点运算符可以相互结合使用(例:${Users[0].name}可以访问集合或数组中的第一个元素的name属性)
3.算术运算符
- 1.EL表达式中的算符运算符用于对整数和浮点数的值进行算术运算
- 2.使用这些算符运算符可以在JSP页面进行算符运算,简化代码量
算术运算符 说明 算术表达式 结果 + 加 ${10+2} 12 - 减 ${10-2} 8 * 乘 ${10*2} 20 /或div 除 ${10/4}或 ${10 div 4} 2.5 %或mod 取余 ${10%4}或 ${10 mod 4} 2 - 3.注意:
- 1.
-
运算符既可以作为减号,也可以作为符号- 2.
/
或div
运算符在进行除法运算时,商为小数4.比较运算符
- 1.EL表达式中的比较运算符用于比较两个操作数的大小
- 2.操作数可以是各种常量,EL变量或EL表达式;所有的运算符执行的结果都是布尔类型
比较运算符 说明 算术表达式 结果 ==或eq 等于 ${10==2}或 ${10 eq 2} false !=或ne 不等于 ${10!=2}或 ${10 ne 2} true <或lt 小于 ${10<2}或 ${10 lt 2} false >或gt 大于 ${10>2}或 ${10 gt 2} true <=或le 小于等于 ${10<=2}或 ${10 le 2} false >=或ge 大于等于 ${10>=2}或 ${10 ge 2} true - 3.注意:
- 1.为了避免与JSP页面的标签产生冲突,对于后4种比较运算符通常采用第二种表示方式
- 2.如果运算符后面是数字,在运算符和数字之间至少要有一个空格(例:${1 lt 2})
- 3.如果运算符后面有其他符号,可以不加空格(例:${1 lt(1+1)})
5.逻辑运算符
- 1.EL表达式中的的逻辑运算符用于对结果为布尔类型的表达式进行运算,运算的结果仍为布尔类型
逻辑运算符 说明 算术表达式 结果 &&或and 逻辑与 ${true&&false}或 ${true and false} false ||或or 逻辑或 ${true||false}或 ${true or false} ture !或not 逻辑非 ${!true}或 ${not true} false 6.empty运算符
- 1.EL表达式中的empty运算符用于判断某个对象是否为null或" ",结果为布尔类型
- 2.语法格式:
${empty var}
- 3.语法说明:
- 1.var变量不存在(即:没有定义;例:${empty name}中的name变量不存在),就返回true
- 2.var变量的值为null(例:${empty customer.name}中的customer.name的值为null),就返回true;
- 3.var变量引用集合(Set,Map,List)类型对象,并且在集合中不包含任何元素时,则返回值为true
7.条件表达式
- 1.EL表达式中条件运算符用于执行某种条件的判断
- 2.语法格式:
${A?B:C}
- 3.语法说明:
- 1.表达式A的计算结果为布尔类型,如果表达式A的计算结果为true,则执行表达式B并返回B的值;如果表达式A的计算结果为false,则执行表达式C并返回C的值
8.()运算符
- 1.EL表达式中圆括号用于改变其他运算符的优先级
7.EL隐式对象
- 1.EL中的隐式对象共用11个
隐含对象名称 描述 pageContext 对应于JSP页面中的pageContext对象 pageScope 代表page域中用于保存属性的Map对象 requestScope 代表request域中用于保存属性的Map对象 sessionScope 代表session域中用于保存属性的Map对象 applicationScope 代表application域中用于保存属性的Map对象 param 表示一个保存了所有请求参数的Map对象 paramValues 表示一个保存所有请求参数的Map对象,它对于某个请求参数,返回的是一个String类型数组 header 表示一个保存了所有HTTP请求头字段的Map对象 headerValues 表示一个保存了所有HTTP请求头字段的Map对象,返回String类型数组 cookie 用来取得使用者的cookie值,cookie的类型是Map initParam 表示一个保存了所有Web应用初始化参数的Map对象 - 2.语法说明:
- 1.pageContext可以获取其他10个隐式对象
- 2.pageScope,requestScope,sessionScope,applicationScope是用于获取指定域的隐式对象
- 3.param和paramValues是用于获取请求参数的隐式对象
- 4.header和headerValues是用于获取HTTP请求消息头的隐式对象
- 5.cookie是用于获取Cookie信息的隐式对象
- 6.initParam是用于获取Web应用初始化信息的隐式对象
1.pageContext对象
- 1.EL表达式中的pageContext隐式对象是为了获取JSP页面的隐式对象
- 2.例1:
${pageContext.response.characterEnconding}
- 3.语法说明:
- 1.pageContext对象获取response对象中的characterEncoding属性
- 4.例2:
<body> ${pageContext.response.characterEncoding}<br/> <% out.println("first line<br/>"); response.getWriter().println("second line<br/>"); %> 请求URI:${pageContext.request.requestURI}<br/> Content-Type响应头:${pageContext.response.contentType}<br/> 服务信息:${pageContext.servletContext.serverInfo}<br/> Servlet注册名:${pageContext.servletConfig.servletName} </body>
- 5.注意:不要将EL表达式中的隐式对象与JSP中的隐式对象混淆,只有pageContext对象是它们所共用的,其它隐式对象则毫不相关
2.Web域相关对象
- 1.Web开发中,PageContext,HttpServletRequest,HttpSession和ServletContext这4个对象之所以可以存储数据,是因为它们内部定义了一个Map集合
- 2.这些Map集合是有一定作用范围的(例:HttpServletRequest对象存储的数据只在当前请求中可以获取),习惯把这些Map集合称为域,这些Map集合所在的对象称为域对象
- 3.EL表达式中为了获取指定域中的数据,提供了pageScope,requestScope,sessionScope,applicationScope4个隐式对象
- 4.注意:EL表达式只能在这4个作用域中获取数据
<body> <% pageContext.setAttribute("userName", "test1"); %> <% request.setAttribute("bookName", "test2"); %> <% session.setAttribute("userName","test3");%> <% application.setAttribute("bookName","test4");%> ${pageScope.userName}<br/> ${requestScope.bookName}<br/> ${sessionScope.userName}<br/> ${applicationScope.bookName}<br/> ${userName} </body>
- 5.使用EL表达式获取某个域对象中的属性时,可以不使用这些隐式对象来查找指定域,而是直接应用域中的属性名称即可(按顺序依次查找)
3.param和paramValues对象
- 1.JSP页面中经常需要获取客户端传递的请求参数,因此EL表达式提供了param和paramValues两个隐式对象,专门用于获取客户端访问JSP页面时传递的请求参数
- 2.param对象用于获取请求参数的某个值,它是Map类型,与request.getParameter()方法相同
- 3.使用EL获取参数时,如果参数不存在,返回的是空字符串而不是null
- 4.param对象语法格式:
${param.num}
- 5.如果一个请求参数有多个值,可以使用paramValues对象来获取请求参数的所有值,该对象用于返回请求参数所有值组成的数组
- 6.paramValue对象的语法格式:
${param.num[0]} //获取某个请求参数的第一个值
<body style="text-align:center"> <form action="${pageContext.request.contextPath}/NewFile.jsp"> name:<input type="text" name="name"><br/> sex:<input type="radio" name="sex" value="boy">男<input type="radio" name="sex" value="girl">女<br/> test1:<input type="text" name="test"><br/> test2:<input type="text" name="test"><br/> <input type="submit" value="提交"> <input type="reset" value="重置"><hr/> ${pageContext.request.contextPath}<br/> name:${param.name}<br/> sex:${paramValues.sex[0]}<br/> test1:${paramValues.test[0]}<br/> test2:${paramValues.test[1]}<br/> </form> </body>
- 7.语法说明:
- 1.${pageContext.request.contextPath}是JSP取得绝对路径的方法,等价于<%=request.getContextPath()%> ,也就是取出部署的应用程序名或者是当前的项目名称
- 2.注意radio单项选择虽然只能有一个结果但是需要使用paramValues获取相应数组的下标为0的值
- 3.如果一个请求参数有多个值,在使用param获取请求时,则返回请求参数的第一个值
4.Cookie对象
- 1.JSP开发中经常需要获取客户端的Cookie信息,因此在EL表达式中提供了Cookie隐式对象
- 2.该对象是一个代表所有Cookie信息的Map集合,Map集合中元素的键为各个Cookie的名称,值则为对应的Cookie对象
<body> Cookie对象的信息: ${cookie.userName}<br/> Cookie对象的名称和值: ${cookie.userName.name} = > ${cookie.userName.value} <%response.addCookie(new Cookie("userName","test")); %> </body>
- 3.语法说明:
- 1.第一次访问该页面服务器没有接收到Cookie信息,因此浏览器不会显示,需要刷新浏览器
- 2.第一次访问服务器时,服务器会向浏览器写一个Cookie,此时的Cookie信息是存储在浏览器中的;当刷新浏览器,第二次访问该页面时,浏览器已经存储了Cookie信息,浏览器会将Cookie信息一同发送给服务器,这时使用$ {cookie.userName.name} 和${cookie.userName.value}便可以获取Cookie的名称和值
JSTL
1.JSTL的定义
- 1.JSTL(JavaServer Pages Standard Tag Library)是Sun公司制定的一套标准标签库
- 2.JSTL标签库由5个功能不同的标签库共同组成
- 3.JSTL规范中为5个标签库分别指定了不同的URI以及使用前缀
标签库 标签库的URI 前缀 Core http://java.sun.com/jsp/jstl/core c I18N http://java.sun.com/jsp/jstl/fmt fmt SQL http://java.sun.com/jsp/jstl/sql sql XML http://java.sun.com/jsp/jstl/xml x Functions http://java.sun.com/jsp/jstl/functions fn - 4.语法说明:
- 1.Core是一个核心标签库,它包含了实现Web应用中的通用操作的标签(例:输出文本内容的<c:out>标签;条件判断的<c:if>标签;迭代循环的<c:forEach>标签)
- 2.I18N是一个国际化/格式化标签库,它包含实现Web应用程序的国际化标签和格式化标签(例:设置JSP页面的本地信息;设置JSP页面的时区使日期按本地格式显示;)
- 3.SQL是一个数据库标签库,它包含用于访问数据库和对数据库中的数据进行操作的标签(例:从数据库中获取数据库连接;从数据库中检索数据)
- 4.XML是一个操作XML文档的标签库,它包含对XML文档中的数据进行操作的标签(例:解析XML文件;输出XML文档内容;迭代处理XML文档的元素)
- 5.Functions是一个函数标签库,它提供了一套自定义EL函数,包含JSP网页常用到的字符串操作(例:提取字符串中的子字符串;获取字符串长度)
2JSTL的下载和使用
- 1.下载网站
http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/
- 2.下载文件
jakarta-taglibs-standard-1.1.2.zip
- 3.解压后将lib目录下的两个JAR文件(jstl.jar和standard.jar)复制到相应项目下的lib目录下即可使用
- 4.jstl.jar文件包含JSTL规范中定义的接口和相关类
- 5.standard.jar文件包含用于实现JSTL的.class文件以及JSTL中5个标签库描述文件(TLD)
- 6.使用标签时首先需要使用taglib指令导入相应的标签库
<%@ taglib uri="http://java.sun.cm/jsp/jstl/相应标签库url" prefix="相应标签库前缀"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试标签</title> </head> <body> <c:out value="Hello!">sadfadf</c:out> </body> </html>
3.JSTL中的Core标签库
1.<c:out>标签
- 1.该标签可以将一段文本内容或表达式的结果输出到客户端(通常和EL表达式连用)
- 2.如果输出的文本内容中包含需要转义的特殊字符(例:>,<,&等),该标签会默认对它们进行HTML编码转换后再输出
- 3.语法格式
//语法1:没有标签体的情况 <c:out value="value" [default="defaultValue"] [escapeXml="{true|false}"]/> //语法2:有标签体的情况 <c:out value="value" [escapeXml="{true|false}"]>defaultValue</c:out>
- 4.语法说明:
- 1.value属性:用于指定输出的文本内容
- 2.default属性:用于指定当value属性为null时所输出的默认值,该属性可选
- 3.escapeXml属性:用于指定是否将>,<等特殊字符进行HTML编码转换后再进行输出,默认值为true
- 4.注意:只有当value属性值为null时,<c:out>标签才会输出默认值;如果没有指定默认值,则默认输出空字符串
- 5.<c:out>标签输出默认值方式(2种,效果相同)
- 1.通过使用<c:out>标签的dafault属性输出默认值
- 2.通过使用<c:out>标签的标签体来输出默认值
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试标签</title> </head> <body> <c:out value="${param.userName}" default="test1"/><br/> <c:out value="${param.userName}">test2</c:out> </body> </html>
- 6.语法说明:
- 1.由于在访问test.jsp页面时并没有传递userName参数,所以表达式${param.userName}值为null,因此<c:out>标签就会输出默认值
- 2.如果不想让<c:out>标签输出默认值,可以在客户端访问test.jsp页面时传递一个userName参数
- 7.<c:out>标签的escapeXml属性对特殊字符进行转义
- 1.<c:out>标签中的escapeXml属性可以将特殊的字符进行HTML编码转换后再输出
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试标签</title> </head> <body> <c:out value="${param.userName}" escapeXml="false"> <meta http-equiv="refresh" content="0,url=http://www.baidu.com"/> </c:out> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试标签</title> </head> <body> <c:out value="${param.userName}" escapeXml="true"> <meta http-equiv="refresh" content="0,url=http://www.baidu.com"/> </c:out> </body> </html>
- 8.语法说明:
- 1.如果设置escapeXml的属性值为false,<c:out>标签不会对输出的特殊字符进行HTML编码转换,标签便可以发挥作用,访问该页面时就会跳转到百度页面
- 2.如果设置escapeXml的属性值为true,<c:out>标签会对输出的特殊字符进行转义,标签便会被进行HTML编码转换,最终以字符串的形式输出
- 3.如果在<c:out>标签中不设置escapeXml属性,则该属性默认值为true
2.<c:set>标签
- 1.该标签用于定义和存储变量
- 2.该标签可以在页面中定义变量,而不用在JSP页面中嵌入Java代码
- 3.<c:set>标签有两种不同的设置:var和target
- 4.var用于设置作用域属性;target用于设置JavaBean或Map值
- 5.这两个版本都有两种形式:有标签体和无标签体,有标签体只是存入值的另一种途径,无标签体则需要使用value存入值
- 6.语法格式:
//var形式 //语法格式1:在 scope 指定的范围内将标签主体存储到变量中 <c:set var="name [scope="page|request|session|application"]> 标签体 </c:set> //语法格式2:在 scope 指定的范围内将变量值存储到变量中 <c:set var="name value="value"[scope="page|request|session|application"]/> //target形式 //语法格式1:在 scope 指定的范围内将变量值存储在 target 属性指定的目标对象的 propName 属性中 <c:set target="object" value="value" property="proName" property="propName" [scope="page|request|session|application"]/> //语法格式2:在 scope 指定的范围内将标签主体存储到 target 属性指定的目标对象的 propName 属性中 <c:set target="object" property="propName" [scope="page|request|session|application"]> 标签体 </c:set>
- 7.<c:set>标签属性
属性 类型 描述 引用EL value Object 将要存储的变量值 可以 var String 存储变量值的变量名称 不可以 target Object 存储变量值或标签主体的目标对象,可以是JavaBean或Map集合对象 可以 proerty String 可选,指定目标对象存储属性的属性名 可以 scope String 可选,指定变量存在于JSP的范围,如果没有使用则为默认值,默认值是page 不可以 - 8.语法说明:
- 1.如果value为null,var指定的属性将被删除
- 2.如果var指定的属性不存在,则会创建一个属性,但仅当value不为null时才会创建新属性
- 3.如果target表达式是一个Map,property指定的是该Map的一个键;如果target表达式是一个JavaBean,property指定的是该JavaBean的一个成员字段
- 4.如果target表达式为null,容器会抛出一个异常
- 5.如果target表达式不是一个Map或JavaBean,容器会抛出一个异常
- 6.如果target表达式是一个JavaBean,但是这个JavaBean没有与property匹配的成员字段,容器会抛出一个异常
- 7.scope属性是可选的,如果没有使用这个属性,则默认为页面作用域
- 8.当没有使用这个属性时,容器会依次在页面作用域、请求作用域、会话作用域、应用作用域查找,如果找不到“var”指定名字的作用域属性,容器就会在页面作用域新建一个属性;如果找不到“target”指定的对象,容器会抛出一个异常。
package javaBean; public class Notice { private int n_id=5; private String title="sssda"; private String details; private String n_time; public Notice() { } }
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试标签</title> </head> <body> <c:set var="allCount" value="${allCount+1}" scope="application"/> <c:set var="count" scope="session">${count+1}</c:set> 今天访问本网站总人数为${allCount}<br/> 今天您访问了此网站次数为${count}<br/> <hr/> <% request.setAttribute("notice",new javaBean.Notice()); request.setAttribute("map", "ceshi"); %> <c:set target="${notice}" property="n_id">18</c:set> ${notice.n_id}<br/> <%-- <c:set target="${map}" property="name" value="测试"/> ${map.name}<br/> --%> </body> </html>
3.<c:if>标签
- 1.该标签专门用于完成JSP页面中的条件判断
- 2.语法格式:
//语法1:没有标签体的情况 <c:if test="testCondition" var="result" [scope="{page|request|session|application}"]/> //语法2::有标签体的情况,在标签体中指定要输出的内容 <c:if test="testCondition" var="result" [scope="{page|request|session|application}"]> body content </c:if>
- 3.语法说明:
- 1.test属性:设置逻辑表达式
- 2.var属性:指定逻辑表达式中变量的名字
- 3.scope属性:指定var变量的作用范围,默认值为page;如果属性test的计算结果为true,那么标签体将被执行,否则标签体不会被执行而输出空字符串
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试标签</title> </head> <body> <c:set var="visitCount" value="1"/> <c:if test="${visitCount==1}"> This is you first visit<br/> Welcome to here </c:if> </body> </html>
4.<c:choose>标签
- 1.该标签可以在JSP页面中完成if-else语句的功能
- 2.该标签用于指定多个条件选择的组合边界,它必须与<c:when>,<c:otherwise>标签一起使用
- 3.<c:choose>标签没有属性,它的标签体中只能嵌套一个或多个<c:when>标签和零个或一个<c:otherwise>标签,并且同一个<c:choose>标签中所有的<c:when>子标签必须出现在<c:otherwise>子标签之前
<c:choose> Bodycontent (<when> and <otherwise> subtags) </c:choose>
- 4.<c:when>标签只有一个test属性,该属性的值为布尔类型,test属性支持动态值,其值可以是一个条件表达式,如果条件表达式的值为true,就执行这个<c:when>标签体的内容
<c:when test="testCondition"> Bodycontent </c:when>
- 5.<c:otherwise>标签没有属性,它必须作为<c:choose>标签最后分支出现;当所有的<c:when>标签的test条件都不成立时,才执行和输出<c:otherwise>标签体的内容
<c:otherwise> conditional block </c:otherwise>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试标签</title> </head> <body> <c:set var="count" value="${count+1}" scope="session"/> <c:choose> <c:when test="${count==5}"> 这是您第${count}次访问页面 </c:when> <c:when test="${count==8}"> 这是您第${count}次访问页面 </c:when> <c:otherwise> 这是otherwise测试 </c:otherwise> </c:choose> </body> </html>
5.<c:forEach>标签
- 1.该标签用于迭代集合对象中的元素(例:Set,List,Map,数组等),并且能重复执行标签体中的内容
- 2.基本语法:
//语法1:迭代包含多个对象的集合 <c:forEach items="collection" [var="varName"] [varStatu="varStatusName"] [begin="begin"] [end="end"] [step="step"]> body content </c:forEach> //语法2:迭代指定范围内的集合 <c:forEach [var="varName" [varStatus="varStatusName"] begin="begin" end="end" [step="step"]> body content </c:forEach>
- 3.语法说明:
- items属性:指定将要迭代的集合对象
- var属性:指定将当前迭代到的元素保存到page域中的名称
- varStatus属性:指定当前迭代状态信息的对象保存到page域中的名称
- begin属性:指定从集合中第几个元素开始进行迭代,begin的索引值从0开始;如果没有指定items属性,就从begin指定的值开始迭代,直到迭代结束为止
- end属性:指定从集合中第几个元素迭代结束
- step属性:指定迭代的步长,即迭代因子的增量
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试标签</title> </head> <body> <% String[] fruits = {"apple","orange","grape","banana"}; %> String数组中的元素 <br/> <c:forEach var="name" items="<%=fruits%>"> ${name}<br/> </c:forEach> <hr/> <% Map userMap = new HashMap(); userMap.put("Tom", "123"); userMap.put("Make","123"); userMap.put("Lina","123"); %> HashMap集合中的元素 : <br/> <c:forEach var="entry" items="<%=userMap%>"> ${entry.key} : ${entry.value}<br/> </c:forEach> </body> </html>
- 4.标签中的begin,end,step属性分别用于指定循环的起始索引,结束索引和步长;使用这些属性可以迭代集合对象中的某一范围内的元素
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试标签</title> </head> <body> colorsList集合(指定迭代范围和步长):<br/> <% List colorsList = new ArrayList(); colorsList.add("red"); colorsList.add("yellow"); colorsList.add("blue"); colorsList.add("green"); colorsList.add("black"); %> <c:forEach var="color" items="<%=colorsList%>" begin="1" end="3" step="2"> ${color}<br/> </c:forEach> </body> </html>
- 5.<c:forEach>标签的varStatus属性用于设置一个
javax.servlet.jsp.jstl.core.LoopTagStatus
类型的变量,这个变量包含了从集合中取出元素的状态信息- 6.使用varStatus属性可以获取以下信息:
- 1.count:表示元素在集合中的序号,从1开始计数
- 2.index:表示当前元素在集合中的索引,从0开始计数
- 3.first:表示当前是否为集合中的第一个元素
- 4.last:表示当前是否为集合中的最后一个元素
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试标签</title> </head> <body style="text-align:center"> colorsList集合(指定迭代范围和步长):<br/> <% List colorsList = new ArrayList(); colorsList.add("red"); colorsList.add("yellow"); colorsList.add("blue"); colorsList.add("green"); colorsList.add("black"); %> <table border="1" align="center"> <tr> <td>序号</td> <td>索引</td> <td>是否为第一个元素</td> <td>是否为最后一个元素</td> <td>元素的值</td> </tr> <c:forEach var="color" items="<%=colorsList%>" varStatus="status"> <tr> <td>${status.count}</td> <td>${status.index}</td> <td>${status.first}</td> <td>${status.last}</td> <td>${color}</td> </tr> </c:forEach> </table> </body> </html>
更多推荐
所有评论(0)