1 J2EEJ2EEJ2EEJ2EE 郭庆 编著 2009-2-12009-2-12009-2-12009-2-1 2 目录 第1章 J2EE 概述............................................................................................................................. 6 1.1、J2EE 的概念...................................................................................................................... 6 1.2、J2EE 四层模型.................................................................................................................. 6 1.3、J2EE 的核心 API与组件..................................................................................................8 1.4、J2EE 应用服务器和搭建 J2EE 开发环境....................................................................... 9 1.4.1 J2EE 应用服务器...................................................................................................... 9 1.4.2 J2EE 开发环境搭建.................................................................................................. 9 第2章 JDBC 初步..........................................................................................................................16 2.1 常用 SQL 语句.................................................................................................................. 16 2.2 JDBC 简介..........................................................................................................................17 2.2.1 JDBC 概念...............................................................................................................17 2.2.2 JDBC 驱动类型.......................................................................................................18 2.3 JDBC 使用准备工作..........................................................................................................19 2.4 JDBC 使用步骤..................................................................................................................21 2.5 JDBC 实现 CRUD 操作.....................................................................................................23 第3章 JDBC 进阶..........................................................................................................................27 3.1 DBConnection 类................................................................................................................27 3.2 PreparedStatement 对象..................................................................................................... 29 3.3 JDBC 事务..........................................................................................................................32 第4章 Servlet..................................................................................................................................36 4.1 Servlet 概述........................................................................................................................ 36 4.1.1 Servlet 的概念:..................................................................................................... 36 4.1.2 Servlet 的功能......................................................................................................... 36 4.1.3 Servlet 优点............................................................................................................ 37 4.2 Servlet 的生命周期............................................................................................................ 37 4.3 J2EE Web 应用的目录结构...............................................................................................38 4.4 第一个 Servlet HelloWorldServlet....................................................................................39 4.6 Servlet 处理客户端请求实现用户注册............................................................................43 第5章 JSP.......................................................................................................................................46 5.1 JSP 简介..............................................................................................................................46 5.1.1 什么是 JSP?..........................................................................................................46 5.1.2 第一个 JSP..............................................................................................................46 5.1.3 JSP 的优点。...........................................................................................................47 5.1.4 JSP 执行过程。.......................................................................................................47 5.2 JSP 结构..............................................................................................................................48 5.3 JSP 注释..............................................................................................................................49 5.4 JSP 指令..............................................................................................................................49 5.4.1 page 指令语法格式:.............................................................................................49 5.4.2 包含指令 include....................................................................................................50 5.4.3 taglib 指令................................................................................................................51 5.5 JSP 脚本元素......................................................................................................................51 5.6 JSP 动作元素......................................................................................................................52 3 5.6.1 ...........................................................................................................52 5.6.2 ............................................................................................................53 5.7 JSP 内建对象......................................................................................................................54 5.7.1 out 对象....................................................................................................................54 5.7.2 request 对象.............................................................................................................55 5.7.3 response 对象...........................................................................................................62 5.7.4 session 对象.............................................................................................................67 5.7.5 application 对象.......................................................................................................68 5.7.6 pageContext 对象.................................................................................................... 68 5.8 JSP 四种属性范围..............................................................................................................69 第6章 JavaBean..............................................................................................................................72 6.1 JavaBean 的编写规范........................................................................................................ 72 6.2 在MyEclipse 中如何快速创建 JavaBean........................................................................73 6.3 JSP 中访问 JavaBean......................................................................................................... 75 6.3.1 通过脚本段代码访问 JavaBean.............................................................................75 6.3.2 使用脚本段代码将页面提交的数据放入 JavaBean 的属性中...........................75 6.3.3 通过动作元素..................................................................................76 6.4 JavaBean 的范围:............................................................................................................ 78 6.4.1 page(默认范围)....................................................................................................... 78 6.4.2 request 范围.............................................................................................................79 6.4.3 session 范围.............................................................................................................80 6.4.4 application 范围.......................................................................................................80 第7章 JSP+JavaBean 开发模式....................................................................................................82 7.1 数据库设计.........................................................................................................................82 7.2 JavaBean 设计.................................................................................................................... 82 7.3 JavaBean 的业务方法设计................................................................................................ 83 7.4 用户登录流程与页面设计与实现................................................................................... 88 7.5 普通用户修改个人信息功能的设计与实现................................................................... 91 7.6 普通用户注册功能的设计与实现................................................................................... 93 7.7 管理员用户管理功能的设计与实现............................................................................... 96 7.8 管理员删除用户功能的设计与实现............................................................................... 97 7.9 管理员用户模糊查询功能的设计与实现....................................................................... 99 第8章 分页技术实现...................................................................................................................102 8.1 设计分页显示组件..........................................................................................................102 8.2 使用 jsp:include 包含分页显示组件..............................................................................105 8.3 使用 jsp:include 包含分页显示组件..............................................................................106 第9章 使用 SmartUpload 上传下载文件...................................................................................109 9.1 使用 smartupload 进行文件上传.....................................................................................109 9.2 使用 smartupload 时处理文件改名上传.........................................................................109 9.3 使用 smartupload 得到文件扩展名.................................................................................109 9.4 使用 smartupload 下载文件.............................................................................................110 第10 章 Tomcat 数据源配置........................................................................................................111 10.1 JNDI 介绍....................................................................................................................... 111 10.2 JNDI 的常用类和接口...................................................................................................112 4 10.3 JNDI 数据源................................................................................................................... 113 10.4 配置 Tomcat 的JNDI 数据源.......................................................................................114 10.5 测试数据源....................................................................................................................115 第11 章 过滤器解决中文乱码及登录验证.................................................................................118 11.1 Servlet 过滤器简介.........................................................................................................118 11.2 创建 Servlet 过滤器.......................................................................................................118 11.3 创建设置请求编码格式过滤器....................................................................................123 11.4 创建登录验证的过滤器................................................................................................125 11.4 串联过滤器....................................................................................................................127 第11 章 JSP+Servlet+JavaBean 开发模式.................................................................................. 129 11.1 用户登录........................................................................................................................129 11.2 修改用户信息................................................................................................................131 第12 章 表达式语言 EL..............................................................................................................135 12.1 EL简介...........................................................................................................................135 12.1.1 什么是 EL...........................................................................................................135 12.2 EL语法...........................................................................................................................135 12.2.1 EL主要语法结构................................................................................................135 12.2.2 .与 [] 运算符.....................................................................................................136 12.2.3 存取变量.............................................................................................................136 12.2.4 JSP 隐含对象.......................................................................................................137 第13 章 JSTL................................................................................................................................ 138 13.1 JSTL 介绍.......................................................................................................................138 13.2 核心标签库....................................................................................................................138 13.2.1 ................................................................................................................. 139 13.2.2 ..................................................................................................................141 13.2.3 .......................................................................................................... 142 13.2.4 ..............................................................................................................144 13.2.5 ....................................................................................................................144 13.2.6 ..................................................................145 13.2.7 ..........................................................................................................146 13.3 JSTL 和EL在MVC 中的主要应用.............................................................................147 13.3.1 创建 ListUsers Servlet........................................................................................148 13.3.2 l配置 ListUsers Servlet.......................................................................................148 13.3.3 listUsers.jsp..........................................................................................................149 第14 章 JSP+DAO........................................................................................................................151 14.1 JSP+DAO 完成用户登录功能.......................................................................................152 14.1.1 创建 POJO User..................................................................................................152 14.1 创建数据库连接类 DBConnection...................................................................... 153 14.1.3 创建数据访问抽象层接口 UserDAO...............................................................153 14.1.4 创建数据访问实现类 UserImpl........................................................................ 153 14.1.5 创建登录需要的 JSP 页面................................................................................ 154 14.2 JSP+DAO 完成用户注册功能.......................................................................................155 14.2.1 UserDAO 中添加注册方法 register()................................................................ 155 14.2.2 UserDAOImpl 实现类中添加方法 register().....................................................155 5 14.2.3 创建注册需要的 JSP 页面................................................................................ 156 第15 章 Struts2+DAO.................................................................................................................. 158 15.1 MVC 设计模式简介.......................................................................................................158 15.2 Struts2 简介.................................................................................................................... 158 15.2.1 视图.....................................................................................................................158 15.2.2 控制器.................................................................................................................159 15.2.3 模型.....................................................................................................................159 15.3 准备工作........................................................................................................................160 15.4 Struts2+DAO 完成用户登录案例................................................................................. 161 15.4.1 创建登录所需页面.............................................................................................161 15.4.2 创建 Action.........................................................................................................162 15.4.2 创建 struts.xml 配置 UserAction.......................................................................163 15.4.3 创建 DAO...........................................................................................................164 6 第1111章 J2EE J2EE J2EE J2EE 概述 本章主要介绍 J2EE 的概念和由来,J2EE 四层模型,J2EE 的核心 API与组件;应用服 务器与开发环境的搭建。 JavaJavaJavaJava 2222平台的3333个版本介绍 目前,Java 2平台有 3个版本,它们是适用于小型设备和智能卡的 Java 2平台 Micro 版 (Java 2 Platform Micro Edition,J2ME)、适用于桌面系统的 Java 2平台标准版(Java 2 Platform Standard Edition,J2SE)、适用于创建服务器应用程序和服务的 Java 2平台企业版(Java 2 Platform Enterprise Edition,J2EE)。 1.11.11.11.1、、、、J2EE J2EE J2EE J2EE 的概念的概念的概念的概念 J2EE 全称 Java2 Platform ,Enterprise Edition,是面向企业的分布式、多层应用的开发与 部署的标准(规范)。J2EE 不是凭空出现的,它的出现是为了解决传统 2层应用模型的一些 缺点。 传统的 2层结构应用中,如下图 1-1 所示,C/S(客户端/服务器)应用是典型的二层化 结构。 图1-1 2层应用模型 传统的 2层结构应用的特点:整个系统由服务器和客户端组成,客户端除了包含显示逻 辑还有业务逻辑和数据访问逻辑。 优点:client/server 结构通常在第一次部署的时候比较容易; 缺点:升级或维护困难;而且经常基于某种专有的协议―通常是某种数据库协议。它使 得重用业务逻辑和界面逻辑非常困难。 为了解决 2层模型的缺点,出现了多层应用模型。其中以 Sun 公司为核心许多大公司如 Oracle、IBM 等提出了多层应用模型解决方案得到了广泛应用,迅速占领了市场,得到了业 界的认可。 1.21.21.21.2、、、、J2EE J2EE J2EE J2EE 四层模型四层模型四层模型四层模型 J2EE 明确表示支持四层,如图 1-2 所示,由客户层、web 层、业务逻辑层、EIS 层组成 。 7 根据业务逻辑层提供服务的类别,可进一步将三层结构划分成 N层。 图1-2 J2EE 分层模型图 J2EE 的web 层与业务逻辑层通常在一台物理主机上,有时候这 2层(web 层与业务逻 辑层)被称为中间层,故 J2EE 此时被称为 3层应用(客户层、中间层、EIS 层 )。 J2EE 的客户层可以是基于 web 的也可以是非 web 的:例如可以是单独的 Java 应用 (Application);也可以是 Applet。 应用客户端程序和 applets 是客户层组件;Java Servlet 和JavaServer Pages(JSP)是web 层组件;Enterprise JavaBeans(EJB)是业务层组件;EIS 层上通常是数据库服务器。 J2EE 构建在 J2SE 之上(图 1-3 所 示 )。J2EE 是一种利用 Java 2平台来简化企业解决方 案的开发、部署和管理相关的复杂问题的体系结构。J2EE 技术的基础就是核心 Java 平台或 Java 2平台的标准版,J2EE 不仅巩固了标准版中的许多优点,例如"编写一次、随处运行" 的特性、方便存取数据库的 JDBCAPI、CORBA 技术以及能够在 Internet 应用中保护数据的 安全模式等等,同时还提供了对 EJB(Enterprise JavaBeans)、Java Servlets API、JSP(Java Server Pages)以及 XML 技术的全面支持。其最终目的就是成为一个能够使企业开发者大幅 缩短投放市场时间的体系结构。 图1-3 J2EE 构建在 J2SE 之上 多层应用模型的特点: 低的部署费用:应用程序部署在服务器上,不像 2层应用需要在许多客户端进行部署; 低的数据库转变费用:客户端通过中间层访问数据库,当数据库需要改变,仅仅改变服 务器上数据访问代码和数据库即可; 每层独立变化、性能降低和错误的局部化; 通讯性能恶化:层与层之间需要通信,层数变多自然影响性能; 维护费用高:与 2层对比,层数增多,当程序维护改动时维护成本增加。 8 1.31.31.31.3、、、、J2EE J2EE J2EE J2EE 的核心的核心的核心的核心API API API API 与组件与组件与组件与组件 J2EE 平台由一整套服务(Services)、应用程序接口(APIs)和协议构成,它对开发基 于Web 的多层应用提供了功能支持,下面对 J2EE 中的 13 种技术规范进行简单的描述(限于 篇幅,这里只能进行简单的描述): JDBCJDBCJDBCJDBC(Java Database Connectivity):JDBCAPI为访问不同的数据库提供了一种统一的 途径,与 ODBC 一样,JDBC 对开发者屏蔽了一些细节问题,另外,JDCB 对数据库的访问 也具有平台无关性。 JNDIJNDIJNDIJNDI(Java Name and Directory Interface): JNDIAPI被用于执行名字和目录服务。它提供 了一致的模型来存取和操作企业级的资源如 DNS和LDAP,本地文件系统,或应用服务器 中的对象。 EJBEJBEJBEJB(Enterprise Java Bean): J2EE 技术之所以赢得广泛重视的原因之一就是 EJB。它们提 供了一个框架来开发和实施分布式业务逻辑,由此很显著地简化了具有可伸缩性和高度复杂 的企业级应用的开发。EJB 规范定义了 EJB 组件在何时如何与它们的容器进行交互作用。 容器负责提供公用的服务,例如目录服务、事务管理、安全性、资源缓冲池以及容错性。但 这里值得注意的是,EJB 并不是实现 J2EE 的唯一途径。正是由于 J2EE 的开放性,使得有 的厂商能够以一种和 EJB 平行的方式来达到同样的目的。EJB 有3种类型:会话 Bean(分 无状态的会话 Bean、有状态的会话Bean)、消息驱动 Bean、实体 Bean。会话 Bean 用来实 现业务逻辑;实体 Bean 用来实现数据库访问;消息驱动 Bean 实现异步消息服务。 注意:虽然 EJB 是J2EE 的重要组件,但是使用 EJB 的场所如分布式系统不多,故我们不作 为重点。 RMIRMIRMIRMI(Remote Method Invoke): 正如其名字所表示的那样,RMI 协议调用远程对象上方 法。它使用了序列化方式在客户端和服务器端传递数据。RMI 是一种被 EJB 使用的更底层 的协议。 JavaJavaJavaJava IDL/CORBAIDL/CORBAIDL/CORBAIDL/CORBA: 在Java IDL 的支持下,开发人员可以将 Java 和CORBA 集成在一 起。他们可以创建 Java 对象并使之可在 CORBAORB中展开, 或者他们还可以创建 Java 类 并作为和其它 ORB一起展开的 CORBA 对象的客户。后一种方法提供了另外一种途径,通 过它 Java 可以被用于将你的新的应用和旧的系统相集成。 JSP(JJSP(JJSP(JJSP(Java Server Pages): JSP 页面由 HTML 代码和嵌入其中的 Java 代码所组成。服务器 在页面被客户端所请求以后对这些 Java 代码进行处理,然后将生成的 HTML 页面返回给客 户端的浏览器。 ServletServletServletServlet: Servlet 是一种小型的 Java 程序,它扩展了 Web 服务器的功能。作为一种服务 器端的应用,当被请求时开始执行,这和CGI Perl 脚本很相似。Servlet 提供的功能大多与 JSP 类似,不过实现的方式不同。JSP通常是大多数HTML代码中嵌入少量的Java代码,而servlets 全部由 Java 写成并且生成 HTML。 XMLXMLXMLXML(Extensible Markup Language): XML 是一种可以用来定义其它标记语言的语言。它 被用来在不同的商务过程中共享数据。XML 的发展和 Java 是相互独立的,但是,它和 Java 具有的相同目标正是平台独立性。通过将 Java 和XML 的组合,您可以得到一个完美的具有 平台独立性的解决方案。 JMSJMSJMSJMS(Java Message Service): MS 是用于和面向消息的中间件相互通信的应用程序接口 (API)。它既支持点对点的域,有支持发布/订阅(publish/subscribe)类型的域,并且提供对下 列类型的支持:经认可的消息传递,事务型消息的传递,一致性消息和具有持久性的订阅者 支持。JMS 还提供了另一种方式来对您的应用与旧的后台系统相集成。 9 JTAJTAJTAJTA(Java Transaction Architecture): JTA 定义了一种标准的 API,应用系统由此可以访问 各种事务监控。 JTSJTSJTSJTS(Java Transaction Service): JTS 是CORBA OTS 事务监控的基本的实现。JTS 规定了 事务管理器的实现方式。该事务管理器是在高层支持 Java Transaction API(JTA)规范,并且 在较底层实现 OMGOTS specification 的Java 映像。JTS 事务管理器为应用服务器、资源管 理器、独立的应用以及通信资源管理器提供了事务服务。 JavaMailJavaMailJavaMailJavaMail: JavaMail 是用于存取邮件服务器的 API,它提供了一套邮件服务器的抽象类。 不仅支持 SMTP 服务器,也支持 IMAP 服务器。 JAF(JAF(JAF(JAF(JavaBeans Activation Framework): JavaMail 利用JAF 来处理 MIME 编码的邮件附 件。MIME 的字节流可以被转换成 Java 对象,或者转换自 Java 对象。大多数应用都可以不 需要直接使用 JAF。 1.41.41.41.4、、、、J2EE J2EE J2EE J2EE 应用服务器和搭建应用服务器和搭建应用服务器和搭建应用服务器和搭建J2EE J2EE J2EE J2EE 开发环境开发环境开发环境开发环境 1.4.11.4.11.4.11.4.1 J2EE J2EE J2EE J2EE 应用服务器 J2EE 应用可在不同厂家生产的符合 J2EE 规范的平台上移植。常见的符合 J2EE 规范的 产品如下: Tomcat:Web 服务器,又称为 Servlet 容器或 Servlet 引擎,因为 Tomcat 能解析执行 Servlet。 微软的 IIS 也是 web 服务器但是不能解析执行 Servlet。 JBoss:应用服务器,又称EJB 容器。可以执行 EJB 但是不能执行 Servlet。现在从 JBoss 官方网站下载的 JBoss 内部包含了一个类似 Tomcat 的web 容器,可以执行 Servlet。 BEA 公司的 Weblogic: 商业应用服务器,BEA 公司的收费的能执行 Servlet 和EJB 组 件的应用服务器。 IBM 公司的 Websphere:商业应用服务器,IBM 公司的收费的能执行 Servlet 和EJB 组 件的应用服务器。 1.4.21.4.21.4.21.4.2 J2EE J2EE J2EE J2EE 开发环境搭建 现在进行 J2EE 开发的主流 IDE 主要有 Eclipse+MyEclipse 插件、JBuilder 等。其中 Eclipse+MyEclipse 插件的 IDE 今年来使用者众多。Eclipse 是一个平台,该平台是基于插件 的可扩展的集成开发环境,核心的 Eclipse 可以进行 Java 开发,安装了 C语言的插件就能进 行C的开发甚至可以安装 C++插件进行 C++开发,安装了 MyEclipse 插件即可进行 J2EE 开 发。我们主要使用 MyEclipse 官方提供的将 Eclipse 和MyEclipse 插件打包的 MyEclipse6 进 行J2EE开发。 搭建集成开发环境的主要工作: JDK 的下载、安装、配置、测试; Tomcat 的下载、安装、配置、测试; 数据库服务器 SQLServer 2000 的安装配置; MyEclipse 的下载、安装、配置、测试。 10 1.4.2.11.4.2.11.4.2.11.4.2.1 JDK JDK JDK JDK 的下载、安装、配置、测试 的下载、安装、配置、测试 的下载、安装、配置、测试 的下载、安装、配置、测试 (1) JDK 的下载地址:http://java.sun.com;下载 Windows 版本的 JDK,因为我们是在 Windows 系统上进行 J2EE 开发。 (2)JDK 的安装:Windows 平台下双击下载后的 jdk-1_5_0_05-windows-i586-p.exe 进行安 装。 (3)JDK 的配置: ①新增系统变量 JAVA_HOME: 其值为 JDK 安装的主目录。默认 JDK 安装在 C:\Program Files\Java\jdk1.5.0_05 下。在 Windows XP下,鼠标右键单击我的电脑->属性->高级-环境变 量;在系统变量(S)中点击“新建“按钮”,新建 JAVA_HOME 变量,其值为 C:\Program Files\Java\jdk1.5.0_05。如图 1-4 所示。 图1-4 新增系统变量 JAVA_HOME ②编辑系统变量 Path: 选择系统变量下方窗口中的 Path 变量后,单击编辑按钮打开编辑系统变量对话框,在 Path 变量的变量值的行首键入 C:\Program Files\Java\jdk1.5.0_05 \bin;并单击确定。注意在 C:\JDK150\bin 后的“;”是第一个变量值与第二个变量值的分隔符。单击环境变量对话框中 的确定按钮、单击系统属性对话框中的确定按钮,完成 JDK150 的配置。 (4)测试 JDK 是否安装成功:在命令行窗口输入命令 javac 回车;出现 javac 使用帮助说 明JDK 安装成功了。 1.4.2.21.4.2.21.4.2.21.4.2.2 Tomcat Tomcat Tomcat Tomcat 的下载、安装、配置、测试 的下载、安装、配置、测试 的下载、安装、配置、测试 的下载、安装、配置、测试 (1) Tomcat 的下载地址:http://jakarta.apche.org 11 有2种下载文件:.exe 的是 Windows 下的可执行安装文件;.zip 的是绿色软件-不用安装、 解压后即可使用;我们下载的是 Tomcat 6.0.14。 (2) Tomcat 的安装:我们下载扩展名是.zip 的安装文件,将其解压到 d:\即可,即 Tomcat 的主目录为 d:\Tomcat5.0。如下图所示 (3)Tomcat 的配置:暂时不需要。 (4)测试 Tomcat 的安装是否成功: 首先到 Tomcat 的bin 目录,双击startup.batstartup.batstartup.batstartup.bat,即可启动Tomcat Tomcat Tomcat Tomcat 服务器。 接着再打开 IE 浏览器,输入 http://localhost:8080,如果出现以下画面说明 JDK、Tomcat 均 以安装成功。 现在如果要关闭TomcatTomcatTomcatTomcat,请执行 bin 目录下的 shutdown.batshutdown.batshutdown.batshutdown.bat。 1.4.2.31.4.2.31.4.2.31.4.2.3 数据库服务器 数据库服务器 数据库服务器 数据库服务器 SQLServerSQLServerSQLServerSQLServer 2000 2000 2000 2000 的安装配置 的安装配置 的安装配置 的安装配置 将SQLServer 2000 安装光盘装入光驱后,按照安装向导进行安装。需要注意几点:选 12 择开发版的数据库服务器;安装时记住配置的数据库用户帐号 sa 和及其密码(一般情况下 如果只是学习使用建议密码也用 sa,这样好记忆);登录验证模式选择混合验证。 安装完成后,下载 SQLServer 2000 的SP4 补丁包 SQL2000-KB884525-SP4-x86.EXE, 执行该 exe 文件,将进行解压,默认在 C盘下解压得到 SQL2KSP4 文件夹,如下图所示。 双击 setup.bat 文件按照向导完成升级 sp4 补丁的工作。注意:如果你的 SQLServer 2000 没 有安装 sp4 补丁,将不能正常访问数据库 SQLServer 2000。 测试:打开 SQLServer 2000 企业管理器,选择数据库结点,选择新建数据库, 新建数据库 j2ee,并在 j2ee 数据库中新建表 user,该表的字段如下: 1.4.2.41.4.2.41.4.2.41.4.2.4 MyEclipse MyEclipse MyEclipse MyEclipse 的下载、安装、配置、测试 的下载、安装、配置、测试 的下载、安装、配置、测试 的下载、安装、配置、测试 (1)MyEclipse 的下载 MyEclipse 6.6 GA开发环境是免费的,下载网址—— http://www.myeclipseide.com/ 。 该网站需要进行用户注册,注册后登录即可进行下载。下载版本选择 Windows 平台的 All in One 版本即可。 (2)安装 MyEclipse 6.6 GA。双击 MyEclipse 6.6 GA.exe 按照向导进行安装。 (3)配置 MyEclipse 6.6 GA。 配置Java Java Java Java 编辑器的行号显示:打开 MyEclipse,点击 Window->Preference,选择左方窗 口的 General->Editors->Text Editors,在右方窗口中选中 Show line numbers,开启编辑器行号 显示功能。如下图所示。 id (int 型) name (varchar 型) password (varchar 型) email (varchar 型) age (int 型) 13 这样每行代码前会有行号显示。 配置集成 TomcatTomcatTomcatTomcat:使 Eclispe 集成 Tomcat,在 Eclipse 中可以启动 Tomcat 进行 web 程 序调试。 鼠标点击 Eclipse 窗口的菜单 窗口->首选项->左方窗口的 MyEclipse->Application Server->Tomcat5,在右方窗口选中 Enable,将 Tomcat 主目录等 设置成如下图所示并点击应用按钮。 14 (4)测试 Eclipse 集成 Tomcat 是否成功 点击启动服务器按钮 Run/Stop/Restart MyEclipse Application Servers 按钮右方的下拉箭头;选择 Tomcat 5->Start 即可启动在 MyEclipse 中已经配置好的 Tomcat 服务器。 集成 Tomcat 并启动成功的图示如下: 在IE 浏览器输入 http://localhost:8080,出现以下画面说明集成 Tomcat 启动成功了。 在MyEclipse 中关闭 Tomcat ,请点击 Run/Stop/RestartRun/Stop/RestartRun/Stop/RestartRun/Stop/Restart MyEclipseMyEclipseMyEclipseMyEclipse ApplicationApplicationApplicationApplication ServersServersServersServers- >Tomcat5.xTomcat5.xTomcat5.xTomcat5.x->StopStopStopStop。 15 16 第2222章 JDBC JDBC JDBC JDBC 初步 应用程序常常需要和数据库交互,将数据保存到数据库,从数据库取出数据等等。应用 程序对数据库的操作主要是 4种:插入记录、删除记录、更新记录、查询符合条件的记录, 这4种操作常称为 CRUD。现在的数据库主要是关系数据库。常见的关系数据库有 Oracle、 DB2、Microsoft SQLServer 2000、MySql 等。 在介绍 JDBC 前我们先介绍在 SQL 常用的语句。 2.12.12.12.1 常用常用常用常用SQL SQL SQL SQL 语句语句语句语句 ①创建数据库语句如下: create database databaseName 上述语句会创建一个名字叫 databaseName 的数据库。 ②删除数据库语句如下: drop database databaseName 上述语句将删除数据库 databaseName 数据库。 ③创建表的语句格式如下: create table tableName (column1 datatype[column_constraint], column1 datatype[column_constraint], …… [Constrain primary key pk_table_name(column_n)] 以下 SQL 语句用于在 SQLServer2000 中创建用户表 user,该表有 id,name,password, email,age,birthday,money 字段,数据库中字段的数据类型分别是 int,varcher,varcher, varcher,int,datetime,float 型。由于在数据库 SQLServer2000 中user 是关键字,不允许用 户直接使用,故我们在 user 的两边加上[]。 create table [user](id int, name varchar(50), password varchar(50), email varchar(50), age int, birthday datetime); ④删除表的语句如下: drop table tableName; 例如,以下语句用于删除表 user: drop table [user]; ⑤插入一条记录的语句格式如下: insert into tableName(column1,column2,......) values(value1,value2,......); 例如往 user 表插入一条记录: insert into [user](name,password,email,age,birthday) values(‘zhangsan‘,’123‘,’zhangsan@126.com‘,23,’1981-12-06’,66.0); ⑥删除符合条件的一条或多条记录: delete from tableName [where ...]; 例如删除 user 表中 id 是1的记录: delete from user where id=1; 17 数 据 库J D B CJ D B CJ D B CJ D B CJ a v aJ a v aJ a v aJ a v a 应 用 程 序 如果去掉 where 子句,将删除 user 表中所有的记录。 ⑦更新一条或多条记录: update tableName set columnName=newColumnValue; 例如,以下语句更新 user 表的 id=1 的password 字段,字段原来的值是 123,更新后为456。 update [user] set password=’456’; 以上我们简要介绍了常用的 sql 语句,为了能在 Java 程序中操作数据库,我们需要使用 JDBC。 2.22.22.22.2 JDBC JDBC JDBC JDBC 简介简介简介简介 2.2.12.2.12.2.12.2.1 JDBC JDBC JDBC JDBC 概念 JDBCJDBCJDBCJDBC:全称是 Java Database Connectivity,是一个应用程序编成接口(API),包括了 许多类和接口,程序员通过使用 JDBC 可以方便的将 SQL 语句传送给几乎任何一种数据库。 Sun 公司的 JDBC 规范定义了如何操作数据库的一组标准,数据库厂商要要实现这些标 准来完成真正的数据库操作。这有的像我们在 Java 语言中的接口和实现类,Sun 公司的标准 类似接口,数据库厂商的实现类似实现类。接口只是定义如何做某件事,但是不能真正做; 实现类能真正能完成接口中定义的操作。这就是 JDBC 的体系结构。 我们在 Java 应用程序中使用 JDBC 的API来访问数据库时要在 classpath 中加载某个具 体的数据库的 JDBC 驱动,这样不管是什么数据库,只要有驱动,我们在 Java 程序中使用 统一的类和接口就能完成对数据库的操作了。 18 2.2.22.2.22.2.22.2.2 JDBC JDBC JDBC JDBC 驱动类型 JDBC 数据库驱动程序的 4种类型: JDBC-ODBC 桥; 部分 Java 驱动程序; 中间数据访问服务器 ; 纯Java 驱动程序。 第一种驱动类型:JDBC-ODBC JDBC-ODBC JDBC-ODBC JDBC-ODBC 桥:将 JDBC 操作转换为 ODBC 操作,因此在访问数据库 的每个客户端都必须安装 ODBC 驱动程序,这种方式不适合远程访问数据库。 缺点: 增加了 ODBC 层后导致效率低。 JDBC-ODBC 桥不支持分布式(除非 ODBC 驱动本身支持分布式)。 第二种驱动类型:部分 JavaJavaJavaJava 驱动程序:部分 Java 驱动程序直接将 JDBCAPI 翻译成具体 数据库的 API。 效率比第一种驱动高,缺点是客户端需要安装具体数据库的驱动。 第三种驱动类型:中间数据访问服务器:纯 Java 驱动程序,它将 JDBCAPI 转换成独立于 数据库的协议。 JDBC 驱动程序并没有直接和数据库进行通讯;它和一个中间件服务器通讯,然后这个中间 件服务器和数据库进行通讯。 第三种驱动程序是纯 Java 驱动程序,它将 JDBCAPI 转换成独立于数据库的协议。JDBC 19 驱动程序并没有直接和数据库进行通讯;它和一个中间件服务器通讯,然后这个中间件服务 器和数据库进行通讯。这种额外的中间层次提供了灵活性:可以用相同的代码访问不同的数 据库,因为中间件服务器隐藏了 Java 应用程序的细节。要转到不同的数据库,您只需在中 间件服务器上改变参数。(有一点需要注意:中间件服务器必须支持您访问的数据库格式。) 第三种驱动程序的缺点是,额外的中间层次可能有损整体系统性能。另一方面,如果应用程 序需要和不同的数据库格式进行交互,第三种驱动程序是个有效的方法,因为不管底层的数 据库是什么,都使用同样的 JDBC 驱动程序。另外,因为中间件服务器可以安装在专门的 硬件平台上,可以利用总的结果进行一些优化。BEA Weblogic 使用此种方式。 第四种驱动类型:纯 Java Java Java Java 驱动程序:它直接与数据库进行通讯。是最好的驱动程序,因为 它通常提供了最佳的性能,并允许开发者利用特定数据库的功能。本质是使用 Socket(套接 字)编程。目前几乎所有的数据库都提供纯 Java 驱动。建议使用该种驱动。我们的访问数 据库的例子就是使用该类型的驱动程序。 2.32.32.32.3 JDBC JDBC JDBC JDBC 使用准备工作使用准备工作使用准备工作使用准备工作 启动 SQLServer 2000 数据库系统,使用 SQLServer 2000 企业管理器创建 jdbc_test 数据库和 user 表。 ①新建数据库 打开企业管理器,点击 Microsoft SQL Servers->SQL Server 组->(local)(Windows NT)-> 数据库,鼠标右键单击‘数据库‘选择新建数据库命令。 在新建数据库窗口输入 jdbc_test,点击下方的确定按钮完成数据库新建工作。 ②新建表 点击 jdbc_test->表,在‘表‘结点上单击鼠标右键,选择新建表。 20 新建表的字段如下表所示: ③创建Eclipse Eclipse Eclipse Eclipse 项目 打开 MyEclipse,点击 File->new->选择 Java Project,输入项目名 jdbc,点击 Finish 按钮 完成创建 Java 项目工作。 ④配置项目构建路径添加 SQLSQLSQLSQL Server Server Server Server 的JDBC JDBC JDBC JDBC 驱动程序 右键单击项目 jdbc_test,依次选择 Build Path->Configure Build Path, 打开构建路径配置对话框,选择 Add External JARs… 浏览到 SQL Server 的JDBC 驱动目录,选择 JDBC 驱动后点击打开按钮, 字段名 id name password email age birthday money 描述 自增型 int varchar varchar varchar int datetime float 21 点击 Finish 按钮完成构建路径的 JDBC 驱动配置工作。 2.42.42.42.4 JDBC JDBC JDBC JDBC 使用步骤使用步骤使用步骤使用步骤 使用JDBC JDBC JDBC JDBC 访问数据库的步骤: ①加载驱动程序。 加载 MySql 数据库驱动: Class.forName(“com.mysql.jdbc.Driver”); 加载 sql server2005数据库驱动程序,该驱动适合 SQL Server 2005 和SQL Server 2000 数据 库,建议使用该驱动: Class.forName(“com.microsoft.sqlserver.jdbc.SQLServerDriver”);//使用 SQL Server2005 驱动 加载 sql server2000 数据库驱动程序: Class.forName(“com.microsft.jdbc.sqlserver.SQLServerDriver”); 加载 oracle 数据库驱动程序: Class.forName(“oracle.jdbc.driver.OracleDriver”); ②创建连接对象: Connection con=DriverManger.getConnection(url,user,password); 其中 url 是数据库的网络位置,user 和password 是访问数据库的用户名和密码。如果使用的 数据库在本机上,那么访问的数据库的 url 是: jdbc:sqlserver://localhost:1433;DataBaseName=jdbc_test" user 和password 分别是 sa 和sa。注意:password 与数据库 sa 帐号的密码设置有关,如果你 的sa 帐号的密码不是 sa 请更改。 JDBC 连接由数据库 URL标识;其一般形式如下: jdbc::// 协议是 jdbc:表示我们用 Java 程序连接数据库的协议是 jdbc;目前只能是 jdbc 协议。 子协议:主要用于识别数据库驱动程序,即不同数据库驱动程序的子协议不同。 数据源名(datasourcename):包括数据库的 IP 地址、端口号、数据库名称。 Mysql 数据库的 URL: jdbc:mysql://ip:端口号/databaseName jdbc:mysql://localhost:3306/testjdbc SQL Server2000 数据库的 URL jdbc:sqlserver://localhost:1433;DataBaseName=jdbc_test" 22 ③创建Statement Statement Statement Statement 对象或 PreparedStatement PreparedStatement PreparedStatement PreparedStatement 对象来执行 SQL SQL SQL SQL 语句 用executeQuery(String sql)方法进行查询即执行 select 语句,得到结果集 ResultSet 对象。 executeUpdate(sql)执行 insert、delete、update语句。下面我们列出了 Statement 接口的常用方法。 ④遍历结果集对象,输出记录 Oacle 数据库的 URL: jdbc:oracle:thin:@localhost:1521:sid java.sql.Statement 接口的常用方法 方法 描述 boolean execute(String sql) throws SQLException 执行给定的 SQL 语句 sql,单个 SQL 语句 可能返回多个结果集合和/或更新计数。 ResultSet executeQuery(String sql) throws SQLException 执行给定的 SQL select 语句,该语句返回 单个 ResultSet 对象。 int executeUpdate(String sql) throws SQLException 执行给定 SQL 语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句,或 者不返回任何内容的 SQL 语句(如 SQL DDL 语 句 )。 java.sql. ResultSet 接口的常用方法 方法 描述 boolean next() throws SQLException 将指针从结果集的当前位置下移一行。 ResultSet 指针最初位于第一行之前;第一次 调用 next 方法使第一行成为当前行;第二次 调用使第二行成为当前行,依此类推。 boolean previous() throws SQLException 将指针移动到此 ResultSet 对象的上一行。 int getInt(int columnIndex) throws SQLException 返回结果集中 columnIndex 位置的 int 类型的 值。 int getInt(String columnName) throws SQLException 返回结果集中 columnName 字段的 int 类型的 值。 String getString (int columnIndex) throws SQLException 返回结果集中 columnIndex 位置的 String 类型 的值。 String getString (String columnName) throws SQLException 返回结果集中columnName字段的String类型 的值。 Float getFloat(int columnIndex) throws SQLException 返回结果集中 columnIndex 位置的 Float 类型 的值。 23 ⑤依次关闭资源对象。注意关闭顺序与建立顺序相反。 2.52.52.52.5 JDBC JDBC JDBC JDBC 实现实现实现实现CRUD CRUD CRUD CRUD 操作操作操作操作 下面我们分别进行数据库常见的四种操作,即实现插入记录、查询、更新和删除记录。 我们创建类 CRUDTest,该类有 add、get、update、delete 方法,分别实现插入记录、查询、 更新和删除记录的操作。 Float getFloat(String columnName) throws SQLException 返回结果集中 columnName 字段的 Float 类型 的值。 packagepackagepackagepackagetest; importimportimportimportjava.sql.*; importimportimportimportjava.util.Date; publicpublicpublicpublicclassclassclassclassCRUDTest{ publicpublicpublicpublicstaticstaticstaticstaticvoidvoidvoidvoidmain(String[]args)throwsthrowsthrowsthrows ClassNotFoundException, SQLException{ //add(); //get(); //update(); delete(); } publicpublicpublicpublicstaticstaticstaticstaticvoidvoidvoidvoidadd()throwsthrowsthrowsthrowsClassNotFoundException, SQLException{ //定义数据库访问参数 StringdriverName= "com.microsoft.sqlserver.jdbc.SQLServerDriver"; Stringurl= "jdbc:sqlserver://localhost:1433;DataBaseName=jdbc_test"; Stringuser="sa"; Stringpassword="guoqing789"; //1、加载驱动 Class.forName(driverName); //2、创建连接对象 Connectionconn=DriverManager.getConnection(url,user, password); //定义sql语句 Stringsql="insertinto [user](name,password,email,age,birthday,money)" +"values('zhangsan','123','zhangsan@126.com',22,'1990- 12-31',500.0)"; 24 //3、创建语句对象 Statementst=conn.createStatement(); st.executeUpdate(sql); //4、遍历结果集:此处插入记录不需要 //5、关闭资源对象 st.close(); conn.close(); } publicpublicpublicpublic staticstaticstaticstatic voidvoidvoidvoid get()throwsthrowsthrowsthrows ClassNotFoundException, SQLException{ //定义数据库访问参数 StringdriverName= "com.microsoft.sqlserver.jdbc.SQLServerDriver"; Stringurl= "jdbc:sqlserver://localhost:1433;DataBaseName=jdbc_test"; StringdbUser="sa"; StringdbPassword="guoqing789"; //1、加载驱动 Class.forName(driverName); //2、创建连接对象 Connectionconn=DriverManager.getConnection(url,dbUser, dbPassword); //定义sql语句 Stringsql="selectid,name,password,email,age,birthday,money from[user]whereid=5"; //3、创建语句对象,执行sql语句并得到结果集 Statementst=conn.createStatement(); ResultSetrs=st.executeQuery(sql); //4、遍历结果集,显示记录的各个字段值 whilewhilewhilewhile (rs.next()){ intintintint id=rs.getInt("id"); Stringname=rs.getString("name"); Stringpassword=rs.getString("password"); Stringemail=rs.getString("email"); intintintint age=rs.getInt("age"); //Datebirthday=new Date(rs.getDate("birthday").getTime()); Datebirthday=rs.getDate("birthday"); floatfloatfloatfloat money=rs.getFloat("money"); System.out.println("id="+id+";"+"name="+name+";" +"password="+password+";"+"email="+email+ ";" 25 +"age="+age+";"+"birthday="+birthday+";" +"money="+money); } //5、关闭资源对象 rs.close(); st.close(); conn.close(); } publicpublicpublicpublicstaticstaticstaticstaticvoidvoidvoidvoidupdate()throwsthrowsthrowsthrowsClassNotFoundException, SQLException{ //定义数据库访问参数 StringdriverName= "com.microsoft.sqlserver.jdbc.SQLServerDriver"; Stringurl= "jdbc:sqlserver://localhost:1433;DataBaseName=jdbc_test"; Stringuser="sa"; Stringpassword="guoqing789"; //1、加载驱动 Class.forName(driverName); //2、创建连接对象 Connectionconn=DriverManager.getConnection(url,user, password); //定义sql语句 Stringsql="update[user]set name='lisi',password='111',email='lisi@126.com',age=22,birthday='1997 -12-08',money=1000.0whereid=4"; //3、创建语句对象 Statementst=conn.createStatement(); st.executeUpdate(sql); //4、遍历结果集:此处不需要 //5、关闭资源对象 st.close(); conn.close(); } publicpublicpublicpublicstaticstaticstaticstaticvoidvoidvoidvoiddelete()throwsthrowsthrowsthrowsClassNotFoundException, SQLException{ //定义数据库访问参数 StringdriverName= "com.microsoft.sqlserver.jdbc.SQLServerDriver"; Stringurl= "jdbc:sqlserver://localhost:1433;DataBaseName=jdbc_test"; 26 Stringuser="sa"; Stringpassword="guoqing789"; //1、加载驱动 Class.forName(driverName); //2、创建连接对象 Connectionconn=DriverManager.getConnection(url,user, password); //定义sql语句 Stringsql="deletefrom[user]whereid=20"; //3、创建语句对象 Statementst=conn.createStatement(); st.executeUpdate(sql); //4、遍历结果集:此处不需要 //5、关闭资源对象 st.close(); conn.close(); } } 27 第3333章 JDBC JDBC JDBC JDBC 进阶 上一章我们介绍了 JDBC 的基础知识,本章继续介绍 JDBC 的常用高级知识,包括实际 程序开发中的专门获得数据库连接 DBConnection 类、使用 PreparedStatement 对象、插入表 示时间日期的 Date 对象、JDBC 事务等。 3.13.13.13.1 DBConnection DBConnection DBConnection DBConnection 类类类类 在上一章的实现数据库的插入、更新、查询、删除记录的 CRUD 类程序代码中,有 4 个方法来实现 CRUD 操作;但是我们发现在每个代码中都存在设置访问数据库的参数、加 载驱动程序、获得连接对象的重复代码。在实际的程序开发中,我们常常创建一个获得实现 数据库连接的类 DBConnection,专门获得数据库连接。这样避免了代码重复,实现了代码 重用,实现了面向对象中的类的设计的高内聚。 package util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class DBConnection { private static String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; private static String url = "jdbc:sqlserver://localhost:1433;DataBaseName=jdbc_test"; private static String user = "sa"; private static String password = "guoqing789"; private DBConnection() { } static { try { Class.forName(driverName); } catch (ClassNotFoundException e) { e.printStackTrace(); throw new ExceptionInInitializerError(e.getMessage()); } } public static Connection getConnection() throws SQLException { 28 我们使用该类后,插入记录的程序如下。其他操作如更新、查询、删除记录的操作见本 课程的源代码。 return DriverManager.getConnection(url, user, password); } public static void close(ResultSet rs, Statement st, Connection conn) { try { if (rs != null) { rs.close(); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (st != null) { st.close(); } } catch (SQLException e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } } packagepackagepackagepackagetest; importimportimportimportjava.sql.Connection; importimportimportimportjava.sql.Date; importimportimportimportjava.sql.ResultSet; importimportimportimportjava.sql.SQLException; importimportimportimportjava.sql.Statement; importimportimportimportutil.DBConnection; publicpublicpublicpublicclassclassclassclassCRUDTestByDBConnection{ publicpublicpublicpublicstaticstaticstaticstaticvoidvoidvoidvoidmain(String[]args)throwsthrowsthrowsthrows ClassNotFoundException, SQLException{ //add(); //get(); 29 以后我们讲解使用 JDBC 获得连接时,均使用该类。 3.23.23.23.2 PreparedStatement PreparedStatement PreparedStatement PreparedStatement 对象对象对象对象 上一章我们介绍了 Statement 对象来执行 SQL 语句。在JDBC 中PreparedStatement 对象 也可以执行 SQL 语句,使用 PreparedStatement 对象可以避免 SQL 注入问题,并且如果多次 访问数据库的 SQL 语句只是参数不同时,该对象比 Statement 对象的效率高。 下面我们以上一章的插入记录为例,讲解 PreparedStatement 对象的使用。 //update(); delete(); } publicpublicpublicpublicstaticstaticstaticstaticvoidvoidvoidvoidadd()throwsthrowsthrowsthrowsSQLException{ Connectionconn=nullnullnullnull; Statementst=nullnullnullnull; ResultSetrs=nullnullnullnull; trytrytrytry{ //2、创建连接对象 conn=DBConnection.getConnection(); //定义sql语句 Stringsql="insertinto [user](name,password,email,age,birthday,money)" + "values('zhangsan','123','zhangsan@126.com',22,'1990-12-31',500.0)"; //3、创建语句对象 st=conn.createStatement(); st.executeUpdate(sql); //4、遍历结果集:此处插入记录不需要 }finallyfinallyfinallyfinally{ //5、关闭资源对象 DBConnection.close(rs,st,conn); } } } package test; import java.sql.*; import util.DBConnection; public class CRUDTestByPS { public static void main(String[] args) throws ClassNotFoundException, SQLException { //add(); // get(); update(); 30 //delete(); } public static void add() throws SQLException { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { // 2、创建连接对象 conn = DBConnection.getConnection(); // 定义 sql 语句 String sql = "insert into [user](name,password,email,age,birthday,money) values(?,?,?,?,?,?)"; // 3、创建语句对象 ps = conn.prepareStatement(sql); ps.setString(1, "psName"); ps.setString(2, "psPassword"); ps.setString(3, "psName@126.com"); ps.setInt(4, 21); ps.setDate(5, new java.sql.Date(new java.util.Date().getTime())); ps.setFloat(6, 600.0f); ps.executeUpdate(); // 4、遍历结果集:此处插入记录不需要 } finally { // 5、关闭资源对象 DBConnection.close(rs, ps, conn); } } public static void get() throws ClassNotFoundException, SQLException { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; Date birthday = null; try { // 2、创建连接对象 conn = DBConnection.getConnection(); // 定义 sql 语句 String sql = "select id,name,password,email,age,birthday,money from [user] where id=?"; // 3、创建语句对象,执行 sql 语句并得到结果集 ps = conn.prepareStatement(sql); ps.setInt(1, 5); rs = ps.executeQuery(); 31 // 4、遍历结果集,显示记录的各个字段值 while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); String password = rs.getString("password"); String email = rs.getString("email"); int age = rs.getInt("age"); // Date birthday = new Date(rs.getDate("birthday").getTime()); birthday = rs.getDate("birthday"); float money = rs.getFloat("money"); System.out.println("id=" + id + ";" + "name=" + name + ";" + "password=" + password + ";" + "email=" + email + ";" + "age=" + age + ";" + "birday=" + birthday + ";" + "money=" + money); } } finally { // 5、关闭资源对象 DBConnection.close(rs, ps, conn); } } public static void update() throws ClassNotFoundException, SQLException { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { // 2、创建连接对象 conn = DBConnection.getConnection(); // 定义 sql 语句 String sql = "update [user] set name=?,password=?,email=?,age=?,birthday=?,money=? where id=?"; // 3、创建语句对象 ps = conn.prepareStatement(sql); ps.setString(1, "lisi"); ps.setString(2, "111"); ps.setString(3, "lisi@126.com"); ps.setInt(4, 23); ps.setDate(5, new java.sql.Date(new java.util.Date().getTime())); ps.setFloat(6, 1000.0f); ps.setInt(7, 21); ps.executeUpdate(); // 4、遍历结果集:此处插入记录不需要 } finally { // 5、关闭资源对象 32 java.sql.PreparedStatement 接口的常用方法如下: 3.33.33.33.3 JDBC JDBC JDBC JDBC 事务事务事务事务 JDBC JDBC JDBC JDBC 事务含义:是指对数据库操作中,由一条或多条对数据库更新的 SQL 语句所组 成的一个不可分割的工作单元;具有原子性,要么全部成功执行完毕;要么执行失败--撤销 DBConnection.close(rs, ps, conn); } } public static void delete() throws ClassNotFoundException, SQLException { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { // 2、创建连接对象 conn = DBConnection.getConnection(); // 定义 sql 语句 String sql = "delete from [user] where id=?"; // 3、创建语句对象 ps = conn.prepareStatement(sql); ps.setInt(1, 4); ps.executeUpdate(); // 4、遍历结果集:此处插入记录不需要 } finally { // 5、关闭资源对象 DBConnection.close(rs, ps, conn); } } } java.sql.PreparedStatement 接口的常用方法 方法 描述 void setInt(int parameterIndex,int x) throws SQLException 这些方法称为 setXXX 方法;给 parameterIndex 位置的参数赋 值。 XXX指的是 int、float、double、 long、boolean、String 等类型。 void setString(int parameterIndex,String x) throws SQLException void setFloat(int parameterIndex, Float x) throws SQLException 33 事务。 比如银行转帐,现在需要把张三帐号上的 1000 元转到李四账户上, 这两条 sql 语句组成一项事务:即要么 2条sql 语句都成功执行,才能提交该事务;要 么虽然执行了一条,整个事务必须全部撤销。否则,假设第一条执行成功,第二条执行失败 : 这时张三账号上少了 1000 元,但是李四账号上却没有增加 1000 元。导致银行转帐混乱。 JDBC JDBC JDBC JDBC 事务管理 Connection 类有 3个控制事务的方法: setAutoCommit(boolean autoCommit):设置事务提交方式,该方法参数为 true 时表示事 务是自动提交的;JDBCAPI中默认:每条更新语句是一项事务,是自动提交事务;该方法 参数为 false 时表示手工提交事务,需要提交事务时应执行 commit()方法。 commit():在设置了 setAutoCommit(false)方法后应显示调用该 commit 方法。 rollback():如果执行事务时出错,应调用该方法进行数据库回滚,将执行过的事务中的 部分撤销。 银行转账的模拟代码如下,实际中银行转账的逻辑要比这复杂得多。 //银行转帐:张三把自己账号上的 1000 元转到李四账号上。 update account set money=money-1000 where name=‘张三’; update account set money=money+1000 where name=‘李四’; package test; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import util.DBConnection; public class TransactionTest { public static void main(String[] args) throws SQLException { transferTest2(); } public static void transferTest() throws SQLException { int id1 = 4; Float m1 = 100.0f; int id2 = 5; transfer(id1, m1, id2); } public static void transferTest2() throws SQLException { int id1 = 4; Float m1 = 100.0f; int id2 = 5; transfer(id1, m1, id2); 34 } // 以下方法进行转帐,从 id1 的帐号上把 m1 数转到 id2 上。 // 此处我们没有使用事务,如果程序执行中出现异常,那么导致转帐失败 public static boolean transfer(int id1, Float m1, int id2) throws SQLException { boolean flag = false; Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = DBConnection.getConnection(); String sql = "update [user] set money=money-? where id=?"; ps = conn.prepareStatement(sql); ps.setFloat(1, m1); ps.setInt(2, id1); ps.executeUpdate(); System.exit(-1); String sql2 = "update [user] set money=money+? where id=?"; ps = conn.prepareStatement(sql2); ps.setFloat(1, m1); ps.setFloat(2, id2); ps.executeUpdate(); } finally { DBConnection.close(rs, ps, conn); } return flag; } // 以下方法进行转帐,从 id1 的帐号上把 m1 数转到 id2 上 // 此处使用事务进行控制 public static boolean transfer2(int id1, Float m1, int id2) throws SQLException { boolean flag = false; Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = DBConnection.getConnection(); // JDBC 默认的是事务自动提交方式是一条 sql 语句;在此我们设置事务为手动提交 conn.setAutoCommit(false); 35 String sql = "update [user] set money=money-? where id=?"; ps = conn.prepareStatement(sql); ps.setFloat(1, m1); ps.setInt(2, id1); ps.executeUpdate(); // 此时数据库关闭; String sql2 = "update [user] set money=money+? where id=?"; ps = conn.prepareStatement(sql2); ps.setFloat(1, m1); ps.setFloat(2, id2); ps.executeUpdate(); // 此句为提交事务,即 2次数据库操作作为事务进行,要么成功,要么失败进 行数据库回滚 conn.commit(); } catch (SQLException e) { conn.rollback(); throw e; } finally { DBConnection.close(rs, ps, conn); } return flag; } } 36 第4444章 ServletServletServletServlet 4.14.14.14.1 Servlet Servlet Servlet Servlet 概述概述概述概述 4.1.14.1.14.1.14.1.1 Servlet Servlet Servlet Servlet 的概念: 我们将 Servlet 看作:server+let。我们都知道一个英文单词 booklet:book+let。let 表示 小的意思。Booklet 的含义就是小册子。那么 Servlet 的含义就是服务器端的小程序。 比较正规的说法,Servlet 是用 Java 编写的服务器端的组件(小程序),运行在 Servlet 容器中,和 JSP 通称为 web 层的 2大组件,Servlet 和客户的通信采用“请求/响应“模 式 , 即我们平时说的接收和处理客户端请求,并往客户端返回一个响应。J2EE Web 层除了 JSP 和Servlet 这2大组件,还有过滤器和监听器组件。 4.1.24.1.24.1.24.1.2 Servlet Servlet Servlet Servlet 的功能 Servlet 能根据客户的请求,动态创建并返回一个 HTML,处理客户的 HTML 表单输入 并返回适当的响应。这是 servlet 最初的用法,用于实现动态网站。 与服务器资源如数据库等交互:在 Servlet 中可以使用 JDBC 来访问数据库,把得到的 结果以 html 文档形式返回给客户端或将结果派发给 JSP; 与JAVABEAN 组件交互,调用 JavaBean 组件访问数据库; 视图派发功能:调用 JSP 或html 或Servlet 等。 处理来自许多客户的输入:一个 Servlet 实例可以为多个客户服务。这和以前的 CGI 不 同。 在Servlet 出现之前,实现动态网站的功能需要使用 CGI。CGI 的一个重要缺点是每对 一个客户请求会在服务器端创建一个 CGI 进程。如果请求的客户很多会导致服务器性能下 降甚至崩溃。 Servlet 一个 Servlet 实例可以为多个客户服务。在服务器端的内存中创建一个 Servlet 实 例后,Servlet 采用多线程的方式为多个客户服务。 现在,大型应用程序中 Servlet 常常用作控制器。 37 Web 客户端的请求由 Servlet 容器派发给某个具体的 Servlet 后->该Servlet 会预处理请求 ->Servlet 调用业务逻辑对象->再将需要显示的数据保存在某个属性对象(如request、session、 application)->然后调用一个包含数据的 JSP 页面->Servlet 容器解析 JSP 页面并发送 html 到 客户端。 4.1.34.1.34.1.34.1.3 ServletServletServletServlet 优点 可移植性:一次编写到处运行。由于 servlet 是由 Java 开发、符合规范定义的,故在各种服 务器和操作系统上有很强的可移植性;比如我们可以在运行 Tomcat 服务器的 WINNT上开 发一个 Servlet,然后到其他的应用服务器的高端 Unix 服务器上去运行。 功能强大:Java 语言能实现的功能 Servlet 基本都能实现(除了 AWT and SWING 图形界面 外 )。 高效耐久:Servlet 被载入后,作为单独的对象实例驻留在服务器内存中,服务器只需要简单 的方法就可激活 Servlet 来处理请求,不需要调用和解释过程,响应速度非常快。 安全:继承了 Java 语言强大的安全性、异常处理机制。 简洁:Servlet API本身带有许多处理复杂 Servlet 开发的方法和类,比如为 cookie 处理和会 话跟踪设计了方便的类。 集成性好:Servlet 有Servlet 容器管理, Servlet 容器位于 Servlet 服务器中,Servlet 和服务 器紧密集成,使 Servlet 和服务器密切合作。 4.24.24.24.2 Servlet Servlet Servlet Servlet 的生命周期的生命周期的生命周期的生命周期 Servlet 部署在 Servlet 容器中,由 Servlet 容器管理。 Servlet 生命周期分 3个阶段: 1、初始化阶段 2、响应客户请求阶段 3、终止阶段 javax.servlet.Servlet 接口中定义了 3个方法:init(),service(),destroy()。这三个方法在 Servlet 生命周期的三个阶段被分别调用。 1、初始化阶段:servlet 容器负责加载 Servlet、创建 Servlet 类的实例、调用 Servlet 实例的 init( )方法 。 2、响应客户请求阶段:容器收到客户请求后,将请求对象 ServletRequest 传递给 Servlet 实 例的 service( ) 方法。 service( ) 方法负责从请求对象 ServletRequest 中获得请求信息并处理 请求。 38 3、终止阶段:当 Web 应用被终止或 Servlet 容器停止运行或 Servlet 容器重新装载该 Servlet 时,Servlet 容器会调用 Servlet 的destroy( ) 方法释放 Servlet 所占的资源。 调用 service( ) 方法 服务器加载 Servlet 服务器创建Servlet类 的实例 Servlet 调用 Servlet 实例的 init( ) 方法 收到请求 service( ) 方法处理请求 并将输出结果返回客户端 Servlet 等待下一个请求 或由服务器卸载 Servlet 在服务器调用 destroy( ) 方法后被卸载 3种情况导致 Servlet 容器加载 Servlet: Servlet 容器启动时自动加载 Servlet,这需要在 web.xml 文件中的属性设置。 Servlet 容器启动后,客户首次请求该 Servlet,这时 Servlet 容器会加载该 Servlet。 Servlet 的类文件被更改,Servlet 容器重新加载更新的版本。 4.34.34.34.3 J2EEJ2EEJ2EEJ2EE Web Web Web Web 应用的目录结构应用的目录结构应用的目录结构应用的目录结构 在创建 Web 应用前,我们需要了解 J2EE 的Web 应用的目录结构如下图所示。 Assembly Root 目录:表示Web 应用根目录,下面有 WEB-INF 目录,JSP 文件和静态 HTML 文件及 Applet 类文件放在此; 39 Assembly Root\WEB-INF 目录:J2EE Web 组件的部署描述文件放在此; Assembly Root\lib 目录:存放该应用需要的第三方类库文件,类库文件通常是 jar 文件; Assembly Root\classes 目录:存放该 Web 应用的 Java 类文件; Assembly Root\tags 目录:存放该 Web 应用的标签库描述文件。 如果我们使用 Tomcat Web 服务器,通常 Web 应用放在%Tomcat%\webapps\下 。webapps 目 录下的每个子目录都是一个 Web 应用程序。 4.44.44.44.4 第一个第一个第一个第一个ServletServletServletServlet HelloWorldServletHelloWorldServletHelloWorldServletHelloWorldServlet 下面我们将编写第一个 Servlet:HelloworldServlet。该 Servlet 向客户端返回一个 Html 页面, 显示 HelloWorld。 我们使用集成开发环境 MyEclipse 开发该 Servlet。 步骤 1、打开MyEclipse,创建Web Project。鼠标左键单击 MyEclipse 菜单栏 File->New->Web Project,在创建 Web Project 对话框中输入项目名 servlet,点击 Finish 按钮完成项目创建工 作。 步骤 2、创建并配置 HelloWorldServlet。鼠标左键单击项目中的 src 选择 New->Servlet, 40 在Package 后输入包名 servlet,Name后输入类名 HelloWorldServlet,Which method stubs would you like to create?下面选择 doGet(),其他不选。点击 next 进入 Servlet 配置窗口; 在如下图的配置窗口中选择 Finish 完成 HelloWorldServlet 的创建工作。 41 这时 MyEclipse 自动打开了 2个文件:HelloWorldServlet.java文件和 web.xml文 件 。 HelloWorldServlet.javaHelloWorldServlet.javaHelloWorldServlet.javaHelloWorldServlet.java文件:是Servlet的类文件源代码,我们在其中的 doGet()中 修改为如下所示: 从HelloWorldServletHelloWorldServletHelloWorldServletHelloWorldServlet的类文件不难看出,该 ServletServletServletServlet是向客户端返回一个 HtmlHtmlHtmlHtml,会在 浏览器中显示 HelloWorld!字样。 web.xml文件:J2EE的Web层的部署描述文件,该文件是 web项目必须有的,用来配置 publicpublicpublicpublicvoidvoidvoidvoiddoGet(HttpServletRequestrequest,HttpServletResponse response) throwsthrowsthrowsthrowsServletException,IOException{ response.setContentType("text/html"); PrintWriterout=response.getWriter(); out .println(""); out.println(""); out.println("AServlet"); out.println(""); out.print("out.print("out.print("out.print("HelloWorld!HelloWorld!HelloWorld!HelloWorld!");");");");////////修改后的 out.println(""); out.println(""); out.flush(); out.close(); 42 Servlet和JSP等web组件。创建 Servlet后必须在 web.xml文件中进行配置; 打开该文件,点击 web.xml文件编辑窗口左下方的“Source“按钮,切换到 web.xml文件源 代码窗口。下面是 web.xml文件的源代码: 现在里面有 2对标签:标签:定义一个Servlet,该标签的子标签 不是必须的,分别用来描述该 web组件和该组件的展示名。是必须的,分别用来定义该 Servlet的别名和该 Servlet的全限定类名(即 包名. 类名)。如果在 web.xml文件其他地方引用该 Servlet,那么必须使用在此配置的 Servlet 别名:HelloWorldServlet标签:用来配置 web组件的 url路径。其子标签分别用来说明要配置哪个 Servlet和要配置的 Servlet的url映射路径。 步骤 3、将该项目部署到 Tomcat 下。单击菜单栏下的如下快捷图标(Deploy MyEclipse J2EE Project to Server )打开项目部署对话框, ThisisthedescriptionofmyJ2EE component ThisisthedisplaynameofmyJ2EE component HelloWorldServlet servlet.HelloWorldServlet HelloWorldServlet /servlet/HelloWorldServlet index.jsp 43 点击 Add 按钮,再点击 Server 右边的下拉按钮选择 Tomcat 6.x,点击下方的 Finish 按钮进行 部署。 这时回到 Project Deploy 窗口点击 OK按钮完成项目部署工作。 步骤 4、启动 Tomcat,测试结果。 点击服务器启动图标右方的下拉箭头后选择 Tomcat 6.x->Start 来启动 Tomcat; 打开 IE 浏览器在地址栏中输入:http://localhost:8080/servlet/servlet/HelloWorldServlet,出现 下图说明 web 应用部署测试成功了。 地址栏中 url 地址解释如下: http://localhost表明Tomcat是本机安装的;8080是默认 Tomcat 服务器的端口号;第一个 servlet 是web 应用的名字,在 MyEclipse 中默认项目名是 web 应用程序的名字;后面的 servlet/HelloWorldServlet 是我们在 web.xml 中配置的 HelloWorldServlet 的url 映射路径。 4.54.54.54.5 Servlet Servlet Servlet Servlet 处理客户端请求实现用户注册处理客户端请求实现用户注册处理客户端请求实现用户注册处理客户端请求实现用户注册 我们准备编写用户注册案例,该案例用 Servlet 实现。用户注册需要一个 Html 页面 register.html 和接收用户注册信息并将注册信息插入数据库 user 表。 步骤 1、编写 register.html。 我们在 servlet 项目下的 WebRoot 下新建文件夹 register,并在该文件夹下新建 register.html。 44 在register.html 中编写代码如下: 步骤 2、创建 RegisterServlet,用来接收注册信息并插入数据库 user 表。 其代码如下: Register
用户注册
姓名:
密码:
年龄:
packageregister; importjava.io.IOException; importjava.sql.Connection; importjava.sql.PreparedStatement; importjava.sql.ResultSet; importjava.sql.SQLException; importjavax.servlet.ServletException; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importutil.DBConnection; publicclassRegisterServletextendsHttpServlet{ publicvoiddoPost(HttpServletRequestrequest,HttpServletRespons 45 步骤 3、修改 web.xml 文件配置 RegisterServlet。 对应的代码如下: eresponse) throwsServletException,IOException{ //设置接收请求信息的编码格式 request.setCharacterEncoding("UTF-8"); //接收register.html的注册信息 Stringname=request.getParameter("name"); Stringpassword=request.getParameter("password"); Stringsage=request.getParameter("age"); //访问数据库将注册信息插入user表 //使用原来的DBConnection类来获得连接 Connectionconn=null; PreparedStatementps=null; ResultSetrs=null; try{ conn=DBConnection.getConnection(); Stringsql="insertinto[user](name,password,age) values(?,?,?)"; ps=conn.prepareStatement(sql); ps.setString(1,name); ps.setString(2,password); ps.setInt(3,Integer.parseInt(sage)); ps.executeUpdate(); }catch(SQLExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }finally{ DBConnection.close(rs,ps,conn); } } } Register register.RegisterServlet Register /register/Register 46 第5555章 JSPJSPJSPJSP 5.15.15.15.1 JSP JSP JSP JSP 简介简介简介简介 5.1.15.1.15.1.15.1.1 什么是 JSPJSPJSPJSP? JSP:全称是 Java Server Pages;是 Web 层组件;用来创建动态网页。如网上购物等等, 可以用 JSP 实现。 我们前面学过 Servlet,知道Servlet 可以实现动态网站。那么为什么不用 Servlet?Servlet 刚出现时确实是用作表示的组件。 但是 Servlet 有2个重要缺点: (1)进行前台--表示层设计的人员主要是美工,美工熟悉 html,但是对 Java 不 熟 悉 ; Servlet 要求熟练掌握 Java 编程; (2)另外,Servlet 不适合作为表示组件。为什么?大量的 out.println()语句很难维护。 5.1.25.1.25.1.25.1.2 第一个 JSPJSPJSPJSP 下面我们在 MyEclipse 中创建第一个 JSP,文件名是 helloworld.jsp,客户端浏览器访问 该文件会显示 HelloWorld! 在MyEclipse 中创建 web 项目jsp,鼠标右键单击 WebRoot,选择 New->Other, 打开新建向导对话框,选择 Web->JSP(Basic Templates)后点击 Next, 47 接着在新建 JSP 窗口输入文件名 helloworld.jsp 后点击 Finish。 MyEclipse 会将新建的 helloworld.jsp 文件自动打开,我们在代码的和之间输 入HelloWorld!。将程序部署到 Tomcat 下,启动 Tomcat,打开浏览器 IE,在地址栏输入: http://localhost:8080/jsp/helloworld.jsp,浏览器显示如下图: 5.1.35.1.35.1.35.1.3 JSP JSP JSP JSP 的优点 Write once,run anyweher; 强大的组件(Java Bean)支持功能; 多操作系统支持:Unix,linux,windows; 可伸缩性好:能够进行 web 应用的服务器集群和负载均衡; 强大的 IDE 支持:如Eclipse+MyEclipse/lomboze 和Jbuilder 集成开发工具对快速开 发JSP 支持很好。 5.1.45.1.45.1.45.1.4 JSP JSP JSP JSP 执行过程 客户端浏览器能解释 HTML 标记,不能直接解释执行 JSP 文件。那么就存在一个服务 器端的从 JSP 到HTML 的转化。实际上 Web 服务器如 Tomcat 是将 JSP 翻译成 Servlet 源文 件(.java 文件),再将 Servlet 源文件编译成类文件(.class 文件);最后加载类文件创建 Servlet 48 实例为客户提供服务。如果客户访问某个 JSP 那么 Web 服务器将会将该 JSP 最后以 Html 格式发送到客户端浏览器中。 *.jsp *.java *.class request response 执 行 jsp parser JSDK servlet servlet 分析器 JSP 到.java 到.class 的演示。 5.25.25.25.2 JSP JSP JSP JSP 结构结构结构结构 helloworld.jsp 代码如下: <%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"%> 49 从上述代码看出,JSP 原始代码中包含了 JSP 元素和 Template(模板) 元素两类;Template 元素指标记<%……%>以外的部分,例如代码中的 HTML 的内容等。JSP 元素则是指将由 JSP 引擎直接处理的部分,这一部分必须符合 JSP 语法,否则会导致编译错误。 HTML 元素大家请自己参考相关书籍或文档,我们主要讲解 JSP 元素。 JSP 元素分为 4大类:注释;指令;脚本元素;动作元素。后面我们一一讲解主要部分 。 5.35.35.35.3 JSP JSP JSP JSP 注释注释注释注释 注释有 3种:HTML 注释;HTML 结合 JSP 表达式的注释;JSP 注释。 下面是 3个对应的例子。 前2种注释会发送到客户端,即我们在浏览器中单击鼠标右键选择源文件可以看到注释 内容;第3种注释不会发送到客户端,我们在浏览器中单击鼠标右键选择源文件不能看到注 释内容。 5.45.45.45.4 JSP JSP JSP JSP 指令指令指令指令 JSP 指令分 3种:页面指令即 page 指令;包含指令即 include 指令;标签库指令即 taglib 指令。这三种指令格式是:<%@ XXX 指令属性……%>。XXX是page、include、taglib 之 一。 5.4.15.4.15.4.15.4.1 page page page page 指令语法格式: “page”指令用于定义 JSP 文件的全局属性。 <%@ page [ language="java" ] [ extends="package.class" ] [import="{package.class | package.*},..." ] [ session="true | false" ] [ buffer="none | 8kb | sizekb" ] [ autoFlush="true | false" ] [ isThreadSafe="true | false" ] [ info="text" ] Insert title here HelloWorld! <%-- This comment will not be visible in the page source --%> 50 [ errorPage="relativeURL" ] [ contentType="mimeType [;charset=characterSet]" | "text/html; charset=ISO-8859-1" ] [ isErrorPage="true | false" ] page page page page 指令属性: language="java" 声明 jsp 中可以使用的脚本语言的种类,目前只能用"java" 。 import="{package.class | package.* },..." 需要导入的 Java 包的列表,这些包作用于程序段,表达式,以及声明。下面的包在 JSP 编译时已经导入了,所以就不需要再指明了: java.lang.* javax.servlet.* javax.servlet.jsp.* javax.servlet.http.* errorPage="relativeURL" 设置处理异常事件的 JSP 文件。 isErrorPage="true | false" 设置此页是否为出错页,如果被设置为 true,你就能在该页面使用 exception 对象。 <%@ page language=“java” pageEncoding=“UTF-8”%> ---以UTF-8 编码来存储当前的 jsp 文件。Eclipse 会根据这个编码格式保存文件。并编译 jsp 文件,包括里面的汉字。 autoFlush=“true|false“--指定是否当缓存填满时自动刷新,输出缓存中的内容。 如果为 true,则自动刷新; 否则,当缓存填满后,可能会出现严重的错误。当你把 buffer 设置为 none 时,你就不能将 autoFlush 设置为 false。 info=“text“---指定一段字符,并插入到 JSP 文件中,并可以通过 Servlet.getServletInfo()方 法得到。 isThreadSafe=“true|false“---指定 JSP 页面是否支持多线程访问。默认值是 ture,表示可以 同时处理多个客户请求,;如果设置为 false,JSP 页面在一个时刻就只能响应一个请求。 5.4.25.4.25.4.25.4.2 包含指令 includeincludeincludeinclude include 指令:向当前页中插入一个静态文件的内容。 JSP 语法格式如下: <%@ include file="relativeURL" %> 或<%@ include file="相对位置"%> 被包含的文件在翻译阶段时被包含进当前的 jsp 文件--即在.java 文件中把被包含的文件包含 进来。 relativeURL 与当前的 jsp 页面有关:如果被包含的 jsp 文件是以文件名/目录名开头, 那么路径就是正在使用的当前 jsp 文件的路径;如果以/开头,表示的是当前应用路径即 webapps/xxx 应用。 一个包含指令的例子:主文件是 include.jsp,被包含的文件是 included.jsp。 “<%@ page %>”指令作用于整个 JSP 页面,同样包括静态的包含文件。但是“<%@ page %>” 指令不能作用于动态的包含文件,比如 “”。 可以在一个页面中用上多个“<%@ page %>”指令,但是其中的属性只能用一次,不过也 有例外,那就是 import 属性。因为 import 属性和 Java 中的import 语句类似(参照Java Language,import 语句引入得是 Java 语言中的类),所以此属性就能多用几次。 无论把“<%@ page %>”指令放在 JSP 的文件的哪个地方,它的作用范围都是整个 JSP 页 面。不过,为了JSP 程序的可读性,以及好的编程习惯,最好还是把它放在 JSP 文件的顶部 。 51 执行完包含指令后,即被包含的文件执行完毕,主 jsp 文件继续执行下一行。 5.4.35.4.35.4.35.4.3 taglib taglib taglib taglib 指令 使用标签库指令的 JSP 语法 <%@ taglib uri="URIToTagLibrary" prefix="tagPrefix" %> 用于引入定制标签库。我们会在以后使用标签库时讲解。 5.55.55.55.5 JSP JSP JSP JSP 脚本元素脚本元素脚本元素脚本元素 脚本元素分为 3种:脚本段;表达式;声明。 ①脚本段就是 Java 代码片段,不是完整的类文件而是类文件的一部分。语法格式如下: ②表达式:是符合 Java 语法的合法表达式,作用:在当前位置显示表达式的结果。语法格 式如下: ③声明:在 JSP 中,声明是一段 Java 代码,用来声明变量和方法,声明后的变量和方法可 在该 JSP 文件的任何地方使用 注意:声明的变量属于实例变量。 JSP 语法格式如下: 下面的例子使用了脚本元素。 test include The current date and time are <%@ include file=“included.jsp" %>
执行完了 include 后执行本行。
<%@ page import="java.util.*" %> <%=(new java.util.Date() ).toLocaleString() %> <% Java code fragment %> 或<% 代码 %> <%= expression %> 或<%= 表达式 %> <%! declaration; [ declaration; ]... %> 或<%! 声明;[声明;]... %> <%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"%> 52 5.65.65.65.6 JSP JSP JSP JSP 动作元素动作元素动作元素动作元素 JSP 动作元素有很多,常用的有: 后3种在 JSP 使用 JavaBean 时讲解。下面我们先看看。 5.6.15.6.15.6.15.6.1 :将请求转发到另外的 jsp、Sevlet、或静态资源文件如 html 等。 语法格式如下: scripttest <%--以下分别声明了一个实例变量和一个方法 --%> <%!intintintinti=5;%> <%! intintintintadd(intintintinta,intintintintb){ returnreturnreturnreturna+b; } %> <%--使用表达式输出声明的实例变量--%> i=<%=i%>
<%--使用脚本段调用声明的方法并用表达式输出结果 --%> <% intintintintx=4,y=5,z; z=add(x,y); %> z=<%=z%> 1."} /> 2."} > [] (“[]”指可以有多个“”标 记 。) 53 page="{relativeURL | <%= expression %>}" 这里是一个表达式或是一个字符串用于说明你将要定向的文件或 URL。这个文件可以是 JSP, 程序段,或者其它能够处理 request 对象的文件(如Servlet,jsp,asp,cgi,php)。 向一个动态文件发送一个或多个参数,这个文件必须是动态文件。如果想传递多个参数,可 以在一个 JSP 文件中使用多个“”;“name”指定参数名,“value”指定参数值。 “”属于服务器端的跳转,从一个 JSP 文件向另一个文件传递一个包含用户 请求的 request 对 象 。“”标签以后的代码,将不能执行。 下面的例子使用“”标签从当前页面 original.jsp 跳转到另一个页面 destination.jsp。 5.6.25.6.25.6.25.6.2 功能:元素允许你包含动态和静态文件,这两种产生的结果是不尽相同的。如 果包含进来的只是静态文件,那么只是把静态文件的内容加到 JSP 网页中;如果包含进来的 为动态文件,那么这个被包含的文件也会被 JSP Container 编译执行。一般而言,你不能直 接从文件名称上来判断一个文件是动态的还是静态的,但是能够自行判断此文 件是动态的还是静态的,于是能同时处理这两种文件。 语法: }” flush=“true | false ”/> 或 }” flush=“true | false” > }”/> * <%@ page contentType="text/html;charset=gb2312" %> test <%@ page contentType="text/html;charset=gb2312" %> <% String useName=request.getParameter("userName"); String outStr= "谢谢光临!"; outStr+=useName; out.println(outStr); %> 54 属性说明:有两个属性:page 和flush。 page 的值可以代表一个相对路径,即你所要包含进来的文件位置或是经过表达式所运算出 的相对路径。 flush 接受的值为 boolean,假若为 true 表示缓冲区满了后缓冲区中的数据被发送到客户端。 它的默认值为 false。 ”用来传递一个或多个参数到指定的动态文件,能在一个页面中使用多个 “”来传递多个参数。 以下是对 include 两种用法的区别,主要有两个方面的不同; 一是执行时间上 <%@ include file=”relativeURI”%>是在翻译阶段执行 在请求处理阶段执行。 二是引入内容的不同: <%@ include file=”relativeURI”%> 引入静态文本(html,jsp),在 JSP 页面被转化成 servlet 之前和它融和到一起。 引 入执行页面或 Servlet 所生成的应答文本。 5.75.75.75.7 JSP JSP JSP JSP 内建对象内建对象内建对象内建对象 为了简化页面的快速开发,JSP 提供了许多内容对象如 request 等,这些对象不需要 JSP 编 程者实例化,它们是由容器实现和管理的,我们称为内建对象。常用的内建对象有 request 对象、response 对象、out 对象、pageContext 对象、session 对象、application 对象、config 对 象 、page 对 象 、exception 对象。所有的隐含对象只能用于脚本段代码或表达式,不能在 JSP 声明中使用。 5.7.15.7.15.7.15.7.1 out out out out 对象 out 对象用于向客户端输出数据。它有多个重载的方法可以输出基本数据类型(boolean、char、 char[]、double、float、int、long)、String 类型、Object 类型等。使用格式: out.print(boolean)或out.println(boolean);这两个方法的区别是第一个只是输出数据,第二个 输出数据后会再后面加上一个换行符。但是该换行符不能被浏览器解析,要真正换行需要使 用out.println(“
”)来实现。 out 对象使用案例。 <%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"%> useOut <% out.println("输出String"); 55 以上代码使用 out 对象输出了 String 对象、boolean 对象和 int 对象。 5.7.25.7.25.7.25.7.2 request request request request 对象 request 对象代表请求对象,客户端的请求信息被 Web 容器封装到该对象中。 我们用 MyEclipse 创建如下 useRequst.jsp 列出了其常用方法,案例代码如下: out.println(truetruetruetrue); out.println(123); %> <%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"%> useRequest <% //request.setCharacterEncoding("gbk"); out.println(request.getAttribute("name"));//得到请求对象中的一个叫name 的对象的值 out.print("
"); out.println(request.getParameter("name"));//得到请求参数为name的值 out.print("
"); out.println(request.getRemoteAddr());//得到客户端的ip地址 out.print("
"); out.println(request.getRequestURL());//得到请求资源的uri out.print("
"); out.println(request.getRemoteHost());//得到发出请求的客户端的主机名 out.print("
"); out.println(request.getServerPort());//得到服务器的端口号 out.print("
"); out.println(request.getMethod());//获得客户端向服务器传输数据的方法如get、 post out.print("
"); out.println(request.getServerName());//得到服务器的名字 //定义一个对象,将其放在request中 Stringname="guoqing"; request.setAttribute("userName",name); //从request中取出并打印输出该对象 StringuserName=(String)request.getAttribute("userName"); out.print("
"); 56 启动 Tocmat,进行项目部署后,打开 IE 浏览器,在地址栏输入: http://localhost:8080/jsp/useRequest.jsp?name=guoqing,进行测试。 一、 一、 一、 一、 request request request request 对象获取表单数据介绍 对象获取表单数据介绍 对象获取表单数据介绍 对象获取表单数据介绍 在JSP 编程中,为了实现用户和网站之间的信息交互,通常我们都要在网页上设计表单 , 然后使用特定方法收集表单数据信息并进行处理。 大家应该对表单很熟悉,随便进入一个网站,如果你想在线注册成为某网站的会员,就 必须填写一张表单,然后提交给服务器处理。下图显示的是 QQ聊天网站的会员注册表单。 表单在 HTML 页面中起着非常重要作用,它是实现与用户信息交互的重要手段。如图 所示,一个表单至少应该包括说明性文字、用户填写的表格、提交和重填按钮等内容。用户 填写了所需的资料之后,按下“提交资料”按钮,所填资料就会通过一个专门的接口传到 Web 服务器上。经服务器处理后反馈给用户结果,从而完成用户和网络之间的交流。 一般情况下,表单设计时使用的标记包括:
、< input>、
<% } %> 页 <% } %>
<%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"import="splitPages.User,java.util.List"%> listUsers_split.jsp
<% Useruser=(User)session.getAttribute("user"); ifififif(user!=nullnullnullnull&&user.getName().equals("admin")){ %> 管理员用户管理
管理员姓名:<%=user.getName()%>
用户列表 id姓名操作 <% 107 大家可以发现,在需要进行分页显示的 listUsers_split.jsp 中我们仅仅使用 <<</>/>/> 即可完成工作。 8.3 8.3 8.3 8.3 分页处理页面设计分页处理页面设计分页处理页面设计分页处理页面设计 分页处理的 JSP:listUsers_do_split.jsp 代码如下: Listall=(List)request.getAttribute("all"); ifififif(all.size()>0){ forforforfor(intintintinti=0;i <%=u.getId()%><%=u.getName()%> ">删除 <% } %> <% }elseelseelseelse{ %> 没有任何记录 <% } } %>
返回到登录成功页面

<%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"import="splitPages.User,java.util.List"%> listUsers_do_split.jsp <% //进行乱码处理 108 request.setCharacterEncoding("gbk"); Useruser=(User)session.getAttribute("user"); ifififif(user!=nullnullnullnull&&user.getName().equals("admin")){ //定义当前页,默认是第1页 intintintintcurrentPage=1; //定义查询关键字 StringkeyWord=""; //定义全部记录数 intintintintallRecorders=0; //定义每页要显示的记录数 intintintintlineSize=5; //从split_page.jsp中接收参数查询关键字和当前页 ifififif(request.getParameter("kw")==nullnullnullnull){ keyWord=""; }elseelseelseelse{ keyWord=request.getParameter("kw"); } ifififif(request.getParameter("cp")==nullnullnullnull||"".equals(request.getParameter(" cp"))){ currentPage=1; }elseelseelseelse{ currentPage=Integer.parseInt(request.getParameter("cp")); } Listall=nullnullnullnull; ifififif(keyWord==nullnullnullnull||"".equals(keyWord)){ //查询全部 allRecorders=user.getAllCount(); all=user.listAll(currentPage,lineSize); }elseelseelseelse{ allRecorders=user.getByLikeCount(keyWord); all=user.listByLike(keyWord,currentPage,lineSize); } //将数据保存到request中以便在页面listUsers_split.jsp中显示这些数据 request.setAttribute("all",all); request.setAttribute("allRecorders",allRecorders); request.setAttribute("currentPage",currentPage); request.setAttribute("keyWord",keyWord); request.setAttribute("lineSize",lineSize); request.setAttribute("searchFlag","T"); request.setAttribute("jspUrl","/splitPages/listUsers_do_split.jsp"); 109 request.getRequestDispatcher("listUsers_split.jsp").forward(request,r esponse); } %> 110 第9999章 使用SmartUpload SmartUpload SmartUpload SmartUpload 上传下载文件 文件上传和下载是许多 Web 网站的常用功能。在 Java 开源社区有许多开源的上传和下 载组件,其中常常使用的 SmartUpload 组件。该组件能够满足一般的上传和下载任务,不足 之处是对中文支持不好并且通常上传文件的大小最好不要超过 200M。 下面我们开始使用 SmartUpload 组件。 9.1 9.1 9.1 9.1 使用使用使用使用smartupload smartupload smartupload smartupload 进行文件上传进行文件上传进行文件上传进行文件上传 ①新建 upload.html,并创建一个 form 表单,关键代码如下: ②新建 doUpload.jsp,进行上传处理,关键代码如下: ③部署 web 应用程序到 tomcat 中,启动 tomcat 进行测试。 9.2 9.2 9.2 9.2 使用使用使用使用smartupload smartupload smartupload smartupload 时处理文件改名上传时处理文件改名上传时处理文件改名上传时处理文件改名上传 上传文件改名为指定的名字后上传到某个 web 应用下的 upload 目录下。 问题:form 表单封装了多媒体数据时,用 request 无法得到请求参数的名字 例子:mixedupload.html 和domixedupload.jsp //String name=request.getParameter("name"); 解决方案,使用 SmartUpload 中的 Request 对象,该对象实现了 HttpServletRequest 接口: String name=smart.getRequest().getParameter("name"); 9.3 9.3 9.3 9.3 使用使用使用使用smartupload smartupload smartupload smartupload 得到文件扩展名得到文件扩展名得到文件扩展名得到文件扩展名 解决了取得 request 中的文件名问题,那么上传文件的扩展名如何取得?
选择要上传的图片:
<% //1、上传初始化 smart.initialize(pageContext); //2、准备上传 smart.upload(); //3、保存上传的文件 smart.save("/upload"); %> 111 注意:上传文件的扩展名是不能改变的。如果改变会导致无法打开即不能用合适的软件 打开该文件。 9.4 9.4 9.4 9.4 使用使用使用使用smartupload smartupload smartupload smartupload 下载文件下载文件下载文件下载文件 ①创建下载文件页面:download.jsp 代码如下: ②创建执行下载任务页面:do_download.jsp 代码如下: 注意:在执行下载任务的页面,在%><%的中间不能有任何空格、字符、html 标签。否则无 法实现下载功能。 //取得后缀 String ext=smart.getFiles().getFile(0).getFileExt(); <% smart.initialize(pageContext); smart.upload(); //取得扩展名 String ext=smart.getFiles().getFile(0).getFileExt(); String name=smart.getRequest().getParameter("name"); String newName=name+"."+ext; //上传后换名存储在/upload/ smart.getFiles().getFile(0).saveAs("/upload/"+newName); %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="GB18030"%> Insert title here 文件下载 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="GB18030"%><%@ page import="com.jspsmart.upload.*" %><% SmartUpload smart=new SmartUpload(); smart.initialize(pageContext);smart.setContentDisposition(null); //smart.downloadFile("/upload/J2EE.doc"); //smart.downloadFile("/upload/1.png"); %> 112 第10101010章 Tomcat Tomcat Tomcat Tomcat 数据源配置 本章学习 JNDI 和Tomcat 6下数据源的配置。 10.110.110.110.1 JNDI JNDI JNDI JNDI 介绍介绍介绍介绍 ①JNDI:Java 命名和目录接口的 API。全称是 Java Naming and Directory Interface; 借助于 JNDIAPI,为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口。 开发者能通过名字访问用户、机器、网络、对象、服务。比如可以访问公司内网的打印机、 访问 Java 对象、关系数据库等。 类似 JDBC 都是构建在抽象层上,我们在 Java 程序中使用 JNDIAPI,底层的实现我们 不用关心。 J2EE 中的 EJB、JDBC 等常常使用 JNDI 获取数据源等。 ②命名和目录服务。 命名即名字,类似引用,能标识对象访问对象。 如 String s=“abc”;真正的对象是“abc”,s是引用即名字,我们通过名字访问对象。 正在上课的每个同学,每个人都有名字;当我喊道张三去做某事时,张三同学会站起来 。 ③命名服务。 命名服务类似于话务员,给某个打电话的客户提供转接号码或其他解释工作。 命名服务能完成如下任务:将名字和对象进行绑定;根据名字查找对象。 现实生活中的命名服务有 DNS,如下: 将域名翻译成 IP 地址 www.sdjzu.edu.cn -> 202.194.86.140 通过域名得到 IP 地址去访问因特网上的主机。 113 文件系统中,也是通过文件名访问文件(通过文件命名系统将文件名转换成文件对象)。 ④目录对象。 可以存储属性;类似于 RDBMS,目录可以存储数据。 ⑤在JNDI 中存在多种名字。 原子名:不可再分割的名字; /etc/fstab/中,etc 和fstab 都是原子名。 复合名:由 0个或多个原子名组成; /etc/fstab/是复合名,由 2个原子名和”/”构成。 绑定:是将名字和对象关联起来的操作。 C:\11.txt 这一文件名字与硬盘中的文件数据绑定。 上下文(Context) 上下文是一组名称-对象的绑定。每种上下文都有一个对应的命名规则。任何一个上下 文都将提供返回需要的对象的查询(或解释)操作,或者还可能提供类似绑定名称、取消绑定 名称和列举绑定的名称的操作。一个上下文对象中的名称又能够被绑定到其他的具有相同命 名规则的上下文中(称之为子上下文)。 举例来说,一个 UNIX 文件系统中的目录/usr 就是一个上下文。一个相对于另外一个文件 目录命名的文件目录就是子上下文。(一些 UNIX 用户称其为一个子目录)。在一个文件目录 /usr/bin 中, 目录 bin 是usr 的子上下文。另外一个例子,比如 COM这样的一个 DNS领域是 一个上下文。一个相对于另一个 DNS域命名的 DNS域是一个子上下文。举例来说,在DNS 域Sun.COM 中,DNS域Sun 是COM 的子上下文。 最后,一个 LDAP 入口,比如 c=us,就是一个上下文。一个相对于另一个 LDAP 入口 命名的 LDAP 入口是上下文。举例来说,在 LDAP 入口 o=sun,c=us 中,o=sun 是c=us 的子 上下文。 上下文由 0个或多个绑定组成。如: /etc/fstab :/etc 是上下文,fstab 是原子名。 10.210.210.210.2 JNDI JNDI JNDI JNDI 的常用类和接口的常用类和接口的常用类和接口的常用类和接口 我们需要掌握 Context 接口的 lookup 方法,该方法的作用是得到方法参数所对应的对象 。 举例如下: javax.naming.Context 接口 javax.naming.InitialContext 类 <% try { Context initCtx = new InitialContext(); DataSource ds = (DataSource) initCtx.lookup("java:comp/env/ jdbc/SQLServer "); Connection conn = ds.getConnection(); out.println("data from database:
"); Statement stmt = conn.createStatement(); ResultSet rs = stmt .executeQuery("select * from student"); while (rs.next()) { out.println(rs.getInt("id")); out.println(rs.getString("name")); 114 10.310.310.310.3 JNDI JNDI JNDI JNDI 数据源数据源数据源数据源 数据库连接的建立和关闭是极其耗费系统资源的,在很多情况下是系统的瓶颈。下面我 们介绍了数据库连接池和数据源的概念,提出了 Tomcat6.0 下配置数据源,并给出了使用数 据源的案例。 对于共享资源,有一个著名的设计模式:资源池(Resource Pool)。该模式正是为了解 决资源的频繁分配﹑释放所造成的问题。数据库连接池的基本思想就是为数据库连接建立一 个“缓冲池”,预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓 冲池”中取出一个,使用完毕之后再放回去。可以通过设定连接池的最大连接数以防止系统 与数据库间的无限连接;更为重要的是我们可以通过连接池的管理机制监视数据库的连接的 数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。连接池的基本工作原理如图2 所示。 管理连接 释放连接 DBMS 连接池 request request 用户 1 用户 2 线程 1 线程 2 Servlet/JSP 建立连接 图2 数据库连接池工作原理 JDBC3.0 规范规定了用以下的类和接口支持数据库连接池的实现: javax.sql.ConnectionEvent:连接事件; javax.sql.ConnectionPoolDataSource:连接池数据源; javax.sql.PooledConnection:池化连接; javax.sql.ConnectionEventListener:连接事件监听器。 JDBC2.0 引入了数据源(DataSource)的概念,该数据源对应于 javax.sql.DataSource 接 口 。DataSource 对象除了将数据库和专门的 JDBC 驱动程序信息封装到一个标准化的对象中 out.println(rs.getString("password")); } rs.close(); stmt.close(); } catch (Exception e) { e.printStackTrace(); } %> 115 之外,还存储了数据库联机的所有信息,可以作为创建 Connection 的工厂。 10.410.410.410.4 配置配置配置配置Tomcat Tomcat Tomcat Tomcat 的的的的JNDI JNDI JNDI JNDI 数据源数据源数据源数据源 Tomcat 服务器实现了 JNDI 接口,我们可以在程序中访问 Tomcat JNDI 数据源。 需要工作如下: ①配置 context.xml 文件。 找到路径:%TOMCAT6%\conf\context.xml 在文件里的元素中加入如下内容: Tomcat 配置说明如下: 注意:红色部分配置的是数据库的是用户名和密码。大家用的时候可能要根据自己使用 的数据库的情况进行更改。 ②配置%TOMCAT6%\webapps\jsp\WEB-INF\web.xml 文件。 找到 jsp 目录,该目录是我们的 web 应用目录的根目录,我们配置的是该应用的 JNDI 数据源,只有该应用可以使用该数据源。 在这对元素中加入如下内容: * name - 数据源的 JNDI 名字。 * auth - 数据源的管理方式;此处是用容器管理数据源。 * type – 配置的资源类型,此处指定配置 JDBC 中的数据源。 * driverClassName - 所使用的 JDBC 驱动类全称。 * maxActive - 同一时刻可以自数据库连接池中被分配的最大活动实例数。 * maxIdle - 同一时刻数据库连接池中处于非活动状态的最大连接数。 * maxWait - 当连接池中没有可用连接时,连接池在抛出异常前将等待的最大时间,单位毫 秒。 *password - 传给 JDBC 驱动的数据库密码。 * url - 传给 JDBC 驱动的连接 URL。 * username- 传给 JDBC 驱动的数据库用户名。 * validationQuery - 一个 SQL 查询语句,用于在连接被返回给应用前的连接池验证。 * 如果指定了 validationQuery 属性,则必为至少返回一行记录的 SQL SELECT 语句。 DB Connection jdbc/SQLServer javax.sql.DataSource Container 116 这样就为 ROOT 项目配置好了数据源。大家为自己项目配置数据源时,就更改相应的 项目下的 web.xml 文件就行了。 ③将SQLServer2000 的JDBC 驱动程序 jar 包放到%TOMCAT6%\lib\下。 重启 Tomcat6 。 10.510.510.510.5 测试数据源测试数据源测试数据源测试数据源 接下来,我们根据项目中的 util 包中的DBConnection 类,创建一个新类 DBConnectionByDS,使用 JNDI 数据源来获得连接对象。 DBConnectionByDS 代码如下: package util; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; public class DBConnectionByDS { private static String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; private static String url = "jdbc:sqlserver://localhost:1433;DataBaseName=jdbc_test"; private static String user = "sa"; private static String password = "guoqing789"; private static DataSource ds = null; private DBConnectionByDS() { } /* *// 以下 static 块和 getConnection 方法是手动获得数据库连接即每次都需要创建到数 据库的连接 static { try { * Class.forName(driverName); } catch (ClassNotFoundException e) { * e.printStackTrace(); throw new * ExceptionInInitializerError(e.getMessage()); }} * * public static Connection getConnection() throws SQLException { return 117 增加新包中 jndiDS,复制 splitPages 包中的 User 类到 jndiDS 包中,并将 jndiDS.User 类 * DriverManager.getConnection(url, user, password); } */ // 以下我们使用 Tomcat JNDI 数据源来获得连接 static { try { Context initCtx = new InitialContext(); ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/SQLServer"); } catch (NamingException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return ds.getConnection(); } public static void close(ResultSet rs, Statement st, Connection conn) { try { if (rs != null) { rs.close(); } } catch (SQLException e) { e.printStackTrace(); } finally { try { if (st != null) { st.close(); } } catch (SQLException e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } } 118 中的 DBConnection 名字全部替换成 DBConnectionByDS。 在WebRoot 下建立新文件夹 jndiDS,将 splitPages 文件夹中的文件全部拷贝到 jndiDS 中,并修改 jndiDS 文件夹中的 JSP 文件中使用的 DBConnection 为DBConnectionByDS;将 splitPages.User 改为 jndiDS.User 类。 启动 Tomcat,打开 IE 进行测试。在地址栏输入: http://localhost:8080/jsp/jndiDS/login.jsp,输入用户名密码进行程序测试。 119 第11 11 11 11 章 过滤器解决中文乱码及登录验证 前面讲过 J2EE 的Web 层的组件主要是 JSP 和Servlet,除此之外还有过滤器和监听器。 Servlet 过滤器是在 Java Servlet 规范 2.3 中定义的。因此所有实现这一规范的 Servlet 容 器都支持 Servlet 过滤器。 Servlet 过滤器能够对 Servlet 容器的请求和响应对象进行检查和修改。本章首先介绍 Servlet 过滤器的概念,然后以解决中文乱码问题为例介绍 Servlet 过滤器的创建和发布过程, 最后讲解 Servlet 过滤器实现登录验证并将与实现中文乱码的 Servlet 过滤器串联起来进行工 作。 11.111.111.111.1 Servlet Servlet Servlet Servlet 过滤器简介过滤器简介过滤器简介过滤器简介 Servlet 过滤器在 Java Servlet 规范 2.3 中定义的,它能够对 Servlet 容器的请求和响应对 象进行检查和修改。Servlet 过滤器本身并不生成请求和响应对象,它只是提供过滤作用。 Servlet 过滤器可以过滤的 Web 组件可以是 Servlet、JSP、或 Html 这些资源文件。如果某个 资源文件设置了过滤器,那么该资源文件被使用之前过滤器将检查 request 对象、修改request Header 和request 内容;在该资源文件被调用之后检查 response 对象、修改 response Header 和response 内容。Servlet 过滤器的过滤过程如下图所示。 过滤器的主要应用是:保护页面不能被非法访问、设置统一的请求编码格式、登录验证 、 过滤请求中的非法内容。 11.211.211.211.2 创建创建创建创建Servlet Servlet Servlet Servlet 过滤器过滤器过滤器过滤器 所有的过滤器类必须实现 javax.servlet.Filter 接口。该接口有 3个必须实现的方法: ● public void init (FilterConfig filterConfig) throws ServletException 这是 Servlet 过滤器的初始化方法。当 Web 应用需要使用一个 Servlet 过滤器时,Servlet 容器负责创建 Servlet 过滤器的实例、Servlet 容器接着调用 init 方法,init 方法类似普通 Java 类的构造方法,只会在创建实例时被调用一次。 在init 方法中可以通过 FilterConfig 接口的实现类的对象 filterConfig 来读取 web.xml 文 120 件中过滤器的初始化参数。 ● public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain ) throws java.io.IOException,ServletException 该方法完成实际的过滤操作。当一个 Web 资源文件被设置使用了过滤器时,Servlet 容 器会首先调用该过滤器的 doFilter 方法。多个过滤器可以串联起来对资源文件进行过滤, FilterChain 参数用于访问后续的过滤器。 ● public void destory( ) 该方法用于释放 Servlet 过滤器占用的资源。Servlet 容器在销毁过滤器实例前会调用该 方法。 下面我们准备创建一个 Servlet 过滤器 RoleFilter。该过滤器对资源文件 filter.html 进行 过滤即进行页面保护;过滤规则是如果发送请求的用户名 userName 是admin,则允许访问 该admin.html;如果不是 admin 则向客户端发送一个页面 roleError.html 说明操作失败!您的 操作权限不允许访问该页面! ①创建 RoleFilter 过滤器。 打开 MyEclipse,找到 jsp Web 应用,在 src 下创建 filter 包和在 WebRoot 下创建 filter 文件夹; 鼠标右键单击 src 选择 New->Class 打开 Class 创建向导,在 New Java Class 窗口的输入 包名 filter 和类名 RoleFilter;在 Interface:右面点击 Add 添加并在 Choose interfaces 下面输 入RoleFilter 实现的接口 javax.servlet.Filter,点击下方的 OK返回到 New Java Class 窗口后点 击Finish。 MyEclipse 自动打开了 Java 编辑器窗口及 RoleFilter 类。代码如下: package filter; import java.io.IOException; import javax.servlet.Filter; 121 我们需要在实现 Filter 接口的 3个方法中添加代码,完成后的 RoleFilter 类代码如下: import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class RoleFilter implements Filter { public void destroy() { //TODO Auto-generated method stub } public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { //TODO Auto-generated method stub } public void init(FilterConfig arg0) throws ServletException { //TODO Auto-generated method stub } } package filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class RoleFilter implements Filter { private FilterConfig config = null; private String roleName = null; public void destroy() { config = null; System.out.println("in destroy() Method"); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { 122 ②配置过滤器。过滤器是 Web 组件,与 Servlet 一样必须在 web.xml 中进行配置。 配置代码如下: 元素:定义一个过滤器; 元素:过滤器的别名;以后可以在 web.xml 中别的地方使用该别名来引用该过 滤器类 filter.RoleFilter; 元素:指定过滤器的全限定名即包名.类名; 元素:配置过滤器的初始化参数; 元素:指定初始化参数的名字; 元素:指定初始化参数的值; 元素:将过滤器和指定的资源文件的 url 进行关联,即要访问该资源文件前 必须通过过滤器的过滤操作。上面我们指定要访问/filter/admin.html该url时必须通 过roleFilter过滤器。 String userName = ((HttpServletRequest) request) .getParameter("userName"); if (!userName.equalsIgnoreCase(roleName)) { ((HttpServletResponse) response).sendRedirect("roleError.html"); } System.out.println("before doFilter(request, response)"); filterChain.doFilter(request, response); System.out.println("after doFilter(request, response)"); } public void init(FilterConfig config) throws ServletException { this.config = config; roleName = config.getInitParameter("role"); System.out.println("in init(FilterConfig config) Method"); } } roleFilter filter.RoleFilter role admin roleFilter /filter/admin.html 123 ③在jsp 项目的 WebRoot\filter\创建 admin.html。代码如下: ④在jsp 项目的 WebRoot\filter\创建 roleError.html。代码如下: ⑤在jsp 项目的 WebRoot\filter\创建 login.jsp。代码如下: ⑥部署 jsp 项目到 Tomcat,启动 Tomcat 进行测试。 admin.html 这是管理员的页面。 thisisadmin's. error.html OperationError!youcannotaccessadmin.html! <%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"%> filter用户登录

用户登录
用户名:

124 11.311.311.311.3 创建设置请求编码格式过滤器创建设置请求编码格式过滤器创建设置请求编码格式过滤器创建设置请求编码格式过滤器 下面我们创建设置请求编码格式的过滤器 EncodingFilter 来解决 form 表单 post 提交的 中文乱码问题。注意,在 Tomcat 下此编码过滤器不能解决 get 提交的中文乱码,要解决 get 提交的中文乱码还是需要在%Tomcat%\conf\server.xml 中,在 encodingFilter filter.EncodingFilter encoding gbk ignore true
encodingFilter 126 11.411.411.411.4 创建登录验证的过滤器创建登录验证的过滤器创建登录验证的过滤器创建登录验证的过滤器 用户登录一个 web 系统后,通常在 session 对象中保存代表用户的 user 对象。在该 web 系统的其他页面可以从 session 中取出 user 对象,如果得到 user 对象,说明用户登录过,是 合法用户;否则说明没有登录,是非法用户,应当跳转的登录页面并在登录页面提示用户进 行登录。 用上述验证方法,需要在每个页面都进行从 session 中取出 user 进行判断,代码的可维 护性差、不易重用代码。 我们可以使用过滤器进行统一的验证: 客 户 端 IE 登 录 验 证 过 滤 器 login.jsp login_do.jsp admin.jsp user.jsp 其他需要验 证是否已经 登录的页面 在上图中,除了 login.jsp 和login_do.jsp 外,其他页面的验证登录代码全部去掉并使用 过滤器对这些页面进行验证保护。我们将其他页面在 WebRoot/filter/protectedResources/下放 置;login.jsp 和login_do.jsp 放置在 WebRoot/filter/下,这两个页面不需要使用过滤器否则会 无法访问即出现 404 错误; ①创建登录验证过滤器。 登录验证过滤器 LoginAuthenticationFilter 代码如下: /* package filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; 127 ②配置过滤器 LoginAuthenticationFilter 以上配置说明loginAuthenticationFilter 将会对所有的以 /protectedResources/开始的路径进行过滤。 ③修改 WebRoot/filter/protectedResources/login_do.jsp。代码如下: import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; //登录验证过滤器实现统一的用户验证 public class LoginAuthenticationFilter implements Filter { private FilterConfig config = null; public void destroy() { this.config = null; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpSession session = ((HttpServletRequest) request).getSession(); User user = (User) session.getAttribute("user"); if (user == null) { request.getRequestDispatcher("/filter/login.jsp") .forward(request, response); } else { chain.doFilter(request, response); } } public void init(FilterConfig config) throws ServletException { this.config = config; } } loginAuthenticationFilter filter.LoginAuthenticationFilter loginAuthenticationFilter /protectedResources/* <%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"%> 128 ④修改 WebRoot/filter/protectedResources/admin.jsp 的href 如下: ⑤修改 WebRoot/filter/protectedResources/user.jsp 的href 如下: ⑥部署 jsp Web 应用、启动服务器进行测试。 11.411.411.411.4 串联过滤器串联过滤器串联过滤器串联过滤器 多个过滤器可以串联起来一起对某个 web 资源进行过滤,过滤顺序是按照 web.xml 中 的配置过滤器顺序,即如编码设置的过滤器和登录验证的过滤器,如果在 web.xml 中编码过 滤器出现在登录验证过滤器之前,那么编码过滤器调用后接着调用登录验证过滤器。如下图 所示。 登录处理页面 <% user=user.login(); ifififif(user!=nullnullnullnull){//说明登录用户存在 //其他页面如果能从session中得到user说明是已经登录的合法用户 session.setAttribute("user",user); ifififif(user.getName().equals("admin")){ %> <% }elseelseelseelse{ %> <%} }elseelseelseelse{//说明登录用户不存在 %> <%} %> 信息系统用户管理 个人信息修改 129 客 户 端 编 码 设 置 过 滤 器 登 陆 验 证 过 滤 器 admin.jsp 等资源文 件 130 第12121212章 JSP+Servlet+JavaBean JSP+Servlet+JavaBean JSP+Servlet+JavaBean JSP+Servlet+JavaBean 开发模式 前面我们讲解了 JSP +JavaBean 开发模式,该模式的优点是开发速度快,适合小型的应 用;缺点是 JSP 负责显示和流程控制导致 JSP 的可维护性差。 JSP+Servlet+JavaBean 开发模式可以解决这些问题。在该模式中,JSP 负责显示;Servlet 负责流程控制、业务逻辑调用;JavaBean 负责业务逻辑实现。 本章主要讲解如何使用 JSP+Servlet+JavaBean 开发模式来完成用户登录、用户修改个人 信息。 此模式的优点:适合团队开发,应用的可维护性较好; 此模式的缺点:开发速度较慢。 11.111.111.111.1 用户登录用户登录用户登录用户登录 用户登录功能需要的组件有:login.jsp;LoginServelt;admin.jsp;user.jsp。流程图如下: 131 管 理 员 登录页面 login.jsp: 用户名:xxxx 密码 : xxxx 登录 user.jsp 1、显示网站 内容; 2、个人修改 信息的超链 接 admin.jsp 1、显示所有 用户; 2、每个用户 信息后有删 除用户的超 链接 LoginServlet.java 1、接收登录信息 2、调用 JavaBean User 实现查询数据库验证 该用户是否存在: ①用户存在且是普通 用户->跳转到 user.jsp 或者:用户存在且是管 理员-> 跳转到 admin.jsp ②用户不存在则返回 到登录页面 从上图可以看出,针对此应用,我们只需要将 login_do.jsp 的功能改为 LoginServlet 实 现即可。故,我们在 src 下新建包 jspservletjavabean,在jspservletjavabean 包中创 LoginServlet 并配置;在 WebRoot 下新建文件夹 jspservletjavabean,将除了 jsp/WebRoot/jspjavabean 中 xxx_do.jsp 之外的文件复制粘贴到 WebRoot/jspservletjavabean /下;将 src/jspjavabean/的 User.java 复制粘贴到 src/ jspservletjavabean /下。 一、创建 LoginServletLoginServletLoginServletLoginServlet 代码如下: package jspservletjavabean; import java.io.IOException; import java.sql.SQLException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 此Servlet 实现与 jsp+javabean 模式中 login_do.jsp 相同的功能 // 1、接收用户参数 String name = request.getParameter("name"); String password = request.getParameter("password"); //2、创建 JavaBean User,将接收的参数付给该对象的属性来保存; User user=new User(); user.setName(name); user.setPassword(password); 普 通 用 户 132 二、配置 LoginServletLoginServletLoginServletLoginServlet 在web.xml 中代码如下: 三、修改 jsp jsp jsp jsp 页面中的 User User User User 的包名 将 改为 四、部署程序测试 11.211.211.211.2 修改用户信息修改用户信息修改用户信息修改用户信息 修改用户信息的流程图如下,对应的 updateUser_do.jsp 改为 Servlet updateUser_do 即可 。 //调用 user 的login 方法验证用户是否存在 try { user = user.login(); if(user!=null){//说明用户存在,在 session 中保存 user request.getSession().setAttribute("user", user); if(user.getName().equals("admin")){ request.getRequestDispatcher("admin.jsp").forward(request, response); }else{ request.getRequestDispatcher("user.jsp").forward(request, response); } }else{//用户不存在则跳转到登录页面 request.getRequestDispatcher("login.jsp").forward(request, response); } } catch (SQLException e) { //TODO Auto-generated catch block e.printStackTrace(); } } } LoginServlet jspservletjavabean.LoginServlet LoginServlet /jspservletjavabean/LoginServlet import="jspjavabean.User"%> import="jspservletjavabean.User"%> 133 user.jsp: 个人信息修改 getUser_do.jsp 根据 id 查询数据库, 得到当前登录的 User 对象;并 跳转到 updateUserInfo.jsp updateUserInfo.jsp 姓名:xxxx 密码:xxxx 修改 取消 updateUser_do 访问数据库更新当前 User 对象对应的记录 一、创建 ServletServletServletServlet getgetgetgetUser_doUser_doUser_doUser_do 代码如下: packagepackagepackagepackagejspservletjavabean; importimportimportimportjava.io.IOException; importimportimportimportjava.sql.SQLException; importimportimportimportjavax.servlet.ServletException; importimportimportimportjavax.servlet.http.HttpServlet; importimportimportimportjavax.servlet.http.HttpServletRequest; importimportimportimportjavax.servlet.http.HttpServletResponse; importimportimportimportjavax.servlet.http.HttpSession; publicpublicpublicpublicclassclassclassclassGetUser_doextendsextendsextendsextendsHttpServlet{ publicpublicpublicpublicvoidvoidvoidvoiddoGet(HttpServletRequestrequest,HttpServletResponse response) throwsthrowsthrowsthrowsServletException,IOException{ HttpSessionsession=request.getSession(); Useruser=(User)session.getAttribute("user"); ifififif(user!=nullnullnullnull){ Stringsid=request.getParameter("id"); intintintintid=Integer.parseInt(sid); trytrytrytry{ user=user.get(id); }catchcatchcatchcatch(SQLExceptione){ //TODOTODOTODOTODOAuto-generatedcatchblock 134 二、配置 ServletServletServletServlet getgetgetgetUser_doUser_doUser_doUser_do 三、创建 ServletServletServletServlet UUUUpdateUser_dopdateUser_dopdateUser_dopdateUser_do 代码如下: e.printStackTrace(); } request.getRequestDispatcher("updateUserInfo.jsp").forward(reques t, response); } } } getUser_do jspservletjavabean.GetUser_do getUser_do /jspservletjavabean/getUser_do packagepackagepackagepackagejspservletjavabean; importimportimportimportjava.io.IOException; importimportimportimportjava.sql.SQLException; importimportimportimportjavax.servlet.ServletException; importimportimportimportjavax.servlet.http.HttpServlet; importimportimportimportjavax.servlet.http.HttpServletRequest; importimportimportimportjavax.servlet.http.HttpServletResponse; importimportimportimportjavax.servlet.http.HttpSession; publicpublicpublicpublicclassclassclassclassUpdateUser_doextendsextendsextendsextendsHttpServlet{ publicpublicpublicpublicvoidvoidvoidvoiddoPost(HttpServletRequestrequest, HttpServletResponseresponse) throwsthrowsthrowsthrowsServletException,IOException{ HttpSessionsession=request.getSession(); Useruser=(User)session.getAttribute("user"); ifififif(user!=nullnullnullnull){ Stringname=request.getParameter("name"); Stringpassword=request.getParameter("password"); user.setName(name); 135 四、配置 ServletServletServletServlet getgetgetgetUser_doUser_doUser_doUser_do user.setPassword(password); trytrytrytry{ user.update(); }catchcatchcatchcatch(SQLExceptione){ //TODOTODOTODOTODOAuto-generatedcatchblock e.printStackTrace(); } //session.setAttribute("user",user); request.getRequestDispatcher("user.jsp").forward(request, response); } } } updateUser_do jspservletjavabean.UpdateUser_do updateUser_do /jspservletjavabean/updateUser_do 136 第13131313章 表达式语言 ELELELEL 本章目标: 1、理解表达式语言在 JSP2.0 中的使用 2、掌握表达式语言在 MVC 设计模式中的主要作用 12.112.112.112.1 ELELELEL简介简介简介简介 12.1.112.1.112.1.112.1.1 什么是 ELELELEL 我们在使用 JSP 编程时,常听说 EL或表达式语言。那么什么是 EL或表达式语言呢? EL即Expression Language,动态网页编程时可以简化动态对象的访问。 EL的主要功能是结合 JSTL,方便的计算和存储在标准位置的 Java 对象的值;替代 JSP 中 的脚本代码。 到了 JSP 2.0 之 后 ,EL已经正式纳入成为标准规范之一。因此,只要是支持 Servlet 2.4 /JSP 2.0 的Container,就都可以在 JSP 网页中直接使用 EL了。 除了 JSP 2.0 建议使用 EL之外,JavaServer Faces( JSR-127 ) 也考虑将 EL纳入规范,由此可 知,EL如今已经是一项成熟、标准的技术。 12.212.212.212.2 ELELELEL语法语法语法语法 EL语法很简单,它最大的特点就是使用上很方便。接下来介绍 EL主要的语法结构: 12.2.112.2.112.2.112.2.1 ELELELEL主要语法结构 ${sessionScope.student.name} 所有 EL都是以${ 为起始、以} 为结尾的。上述 EL范例的意思是:从 Session 的范围中, 取得用户对象的姓名。假若依照之前 JSP Scriptlet 的写法如下: Student stu = (Student)session.getAttribute("stu"); String name = stu.getName(); 两者相比较之下,可以发现 EL的语法比传统 JSP Scriptlet 更为方便、简洁。 注意 假若您所用的 Container 只支持 Servlet 2.3/JSP 1.2,如:Tomcat 4.1.29,您就不能在 JSP 网页 中直接使用 EL,必须安装支持 Servlet 2.4 /JSP 2.0 的Container。 137 12.2.212.2.212.2.212.2.2 ....与 [[[[]]]] 运算符 EL提供 . 和 [] 两种运算符来存取数据。下列两者所代表的意思是一样的: ${sessionScope.user.sex}等于${sessionScope.user["sex"]} .和[] 也可以同时混合使用,如下: ${sessionScope.shoppingCart[0].price} 回传结果为 shoppingCart 中第一项物品的价格。 不过,以下两种情况,两者会有差异: (1) 当要存取的属性名称中包含一些特殊字符,如.或–等并非字母或数字的符号,就一定要 使用 [],例如:${user.My-Name } 上述是不正确的方式,应当改为:${user["My-Name"] } (2) 我们来考虑下列情况: ${sessionScope.user[data]} 此时,data 是一个变量,假若 data 的值为"sex"时,那上述的例子等于${sessionScope.user.sex}; 假若 data 的值为"name"时,它就等于${sessionScope.user.name}。因此,如果要动态取值时, 就可以用上述的方法来做,但....无法做到动态取值。 12.2.312.2.312.2.312.2.3 存取变量 EL存取变量数据的方法很简单,例如:${username}。它的意思是取出某一范围中名称 为username 的变量。因为我们并没有指定哪一个范围的 username,所以它会依序从 Page、 Request、Session、Application 范围查找 。假如途中找到 username,就直接回传,不再继续 找下去,但是假如全部的范围都没有找到时,就回传 null。 其中,pageScope、requestScope、sessionScope 和applicationScope 都是 EL的隐含对象,由 它们的名称可以很容易猜出它们所代表的意思,例如:${sessionScope.username}是取出 Session 范围的 username 变量。这种写法比之前 JSP 的写法: String username = (String) session.getAttribute("username"); 容易、简洁许多。 接下来分别对这四个隐含对象做简短的说明: ● pageScope 范围和 JSP 的Page 相同,也就是单单一页 JSP Page 的范围(Scope)。 ● requestScope 范围和 JSP 的Request 相同,requestScope 的范围是指从一个 JSP 网页请求 到另一个 JSP 网页请求之间,随后此属性就会失效。 ● sessionScope 范围和 JSP Scope 中的 session 相同,它的属性范围就是用户持续在服务器 连接的时间。 ● applicationScope 范围和 JSP Scope 中的 application 相同,它的属性范围是从服务器一开 始执行服务,到服务器关闭为止。 属性范围 在EL中的名称 Page PageScope Request RequestScope Request SessionScope Application ApplicationScope 138 12.2.412.2.412.2.412.2.4 JSP JSP JSP JSP 隐含对象 EL本身也有自己的隐含对象。EL隐含对象总共有 11 个(见下表): 类别 标识符 描述 JSP pageContextPageContext实例对应于当前页面的处理 作用域 pageScope与页面作用域属性的名称和值相关联的 Map类 requestScope与请求作用域属性的名称和值相关联的 Map类 sessionScope与会话作用域属性的名称和值相关联的 Map类 applicationScope与应用程序作用域属性的名称和值相关联的 Map类 请求参数 param按名称存储请求参数的主要值的 Map类 paramValues将请求参数的所有值作为 String数组存储的 Map 类 请求头 header按名称存储请求头主要值的 Map类 headerValues将请求头的所有值作为 String数组存储的 Map类 Cookie cookie按名称存储请求附带的 cookie 的 Map类 初始化参 数 initParam按名称存储 Web 应用程序上下文初始化参数的 Map 类 139 第14141414章 JSTLJSTLJSTLJSTL 在JSP 中使用脚本代码<% %>会导致 JSP 页面的复杂度,程序的可维护性降低,不利于 项目的角色分工(如一个项目可能有美工负责页面美化、java 程序员编码和连接数据库、数 据库开发者设计数据库等)。虽然,SUN 公司有了自定义标签可以使得程序员使用自定义标 签来替代脚本段代码,但是会导致不同程序员创建重复功能的自定义标签。于是,SUN 公 司推出了 JSTL,一个统一的官方的标准标签库,实现了常用功能,来解决替代脚本段的问 题。本章介绍 JSTL 标记库 1.1,要求掌握常用的标记。 本章的主要内容: 1、JSTL 介绍;2、核心标签库中的一般标签(包括输出、删除变量、设置变量、异常捕获)、 条件标签、迭代标签。 13.113.113.113.1 JSTL JSTL JSTL JSTL 介绍介绍介绍介绍 JSTL 是一个不断完善的开放源代码的 JSP 标签库,由 Apache 的Jakarta 小组开发和维 护。JSTL 在支持 JSP1.2 和Servlet2.3 以上版本的容器上运行,如 Tomcat5.028。JSTL 的最 新版本是 JSTL1.2。现在 JSTL 是JSP2.0 规范的一部分。 JSTL 的优点: 可移植性好:JSTL 规范要求实现了 JSTL 的容器必须实现其相应的接口,这样,JSTL 代码可以在应用服务器之间无缝移植。 最大限度的减少了 JSP 中的脚本代码,简化了 Web 程序的开发.. Sun 发布的标准 JSTL1.1 标签库有以下几个标签: q 核心标签库:包含 Web 应用的常见工作,比如:循环、表达式赋值、基本输入输出等 。 q 国际化标签库:用来格式化显示数据的工作,比如:对不同区域的日期格式化等。 q 数据库标签库:可以做访问数据库的工作。 q XML 标签库:用来访问 XML 文件的工作,这是 JSTL 标签库的一个特点。 q 函数标签库:用来读取已经定义的某个函数。 13.213.213.213.2 核心标签库核心标签库核心标签库核心标签库 核心标记库主要有:一般操作、流程控制操作、迭代操作、URL操作。详细分类如下 表所示,我们主要介绍前三种。 分类 功能分类 标签名称 一般操作 out set remove catch 流程控制操作 if choose when 140 在使用 Core Core Core Core 标记库前,必须使用<%@<%@<%@<%@ taglibtaglibtaglibtaglib %>%>%>%>指令,并指定 prefix prefix prefix prefix 和uri uri uri uri 的值。通常设 定如下: 13.2.113.2.113.2.113.2.1 语法格式 1:无 body 的情况。 语法格式 2:有 body 的情况。 bodyContent 的body 可以是 JSP 代码,标记的属性描述如下: 如果 escapeXml 的值是 true,那么下表的字符被转换成实体代码。 下面的例程罗列了相关的用法;注意:带 body 的输出不会发送到客户端。value 的值 可以是具体的字符串,也可是表达式。${}是EL用法,我们在 EL章节进行讲解。 Core otherwise 迭代操作 forEach forTokens URL操作 import param url param redirect param <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 属性名 属性类型 属性描述 value Object 将要计算的表达式 escapeXml Boolean 确定以下字符:<,>,&,’,”在结果集的字符串中是否被 转换成字符实体代码,默认是 true 即转换成实体代码 default Object 如果 value 是null,那么就输出 default 的值 字符 字符实体代码 < < > > && ‘' “" useCout.jsp <%@pagelanguage="java"contentType="text/html;charset=gbk" pageEncoding="gbk"%> <%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%> 141 在IE 浏览器执行结果如下图: useCOUT.jsp

1、使用c:out输出一个已定义的变量; <% StringuserName="黎明"; pageContext.setAttribute("userName",userName); %> 您好!
以上的c:out语句相当于调用了"<%=pageContext.getAttribute("userName") %>";结果是:您好! <%=pageContext.getAttribute("userName")%>
2、使用default,在value为null(不是空字符串:"")时会输出default的值; <%//Stringpassword=""; //request.setAttribute("password",password); %>
3、已定义的变量的存放范围可以是: pageContext,request,session,application。
下面我们在这四个范围内存放同名的对象,即每个范围内的对象名完全一样。分别注 释掉前3句代码,观察结果,分析容器查找变量的顺序。
<%//pageContext.setAttribute("test","testinpageContext"); request.setAttribute("test","testinrequest"); session.setAttribute("test","testinsession"); application.setAttribute("test","testinapplication"); %>
4、输出一个字符串;
5、c:out带有body时,body中的内容不输出到客户端;结果如下:
body内容不输出到客户端

142 13.2.213.2.213.2.213.2.2 该标签用于在四种属性范围(pageContext,request,session,application)中设置某个值,或者设 置某个对象(通常是 JavaBean)的属性。 语法格式 1:使用 value 设置一个特定范围内的变量,其值是 value。 语法格式 2:设置一个特定范围内的属性变量,其值是 body 的内容。 body content 语法格式 3:设置某个特定对象 target 的一个属性 propertyName 的值为 value。 语法格式 4:将 body 内容设置为某特定对象 target 的属性 propertyName 的值。 body content 属性说明如下表。 的使用见 c_set.jsp 。 属性名 属性类型 属性描述 value Object 待计算的表达式 var String 表示 value 属性值的变量名 scope String var 变量的范围 target String 被设置属性的对象,该对象是 JavaBean 或 java.util.Map 对象 property Object 待设定的对象的属性名 c_set.jsp <%@taglibprefix="c"uri="http://java.sun.com/jsp/jstl/core"%> <%@pagecontentType="text/html;charset=gb2312"language="java" %> 143 在IE 浏览器执行结果如下图: 13.2.313.2.313.2.313.2.3 该标签用于删除指定范围内的某个变量或者属性。 JSTL:的使用c:set
设置userName的属性为hellking,然后输出这个属性值:
设置password的属性,属性值在body中,然后输出这个属性值: 123456

设置javaBean的属性,然后输出这些属性值: sdf234sdfd
userName=, password=.
设置不同的属性,并且指定它们的范围: 144 语法格式: 属性说明如下表: 例子如下: IE 浏览器输出如下图: 属性名 属性类型 属性描述 scope String 待删除的变量的范围 var String 待删除的变量名 c_remove.jsp <%@taglibprefix="c"uri="http://java.sun.com/jsp/jstl/core"%> <%@pagecontentType="text/html;charset=gb2312"language="java" %> JSTL:c:remove的使用 在没有调用c:rmeove之前,有这些参数: maxUser=, maxIdelTime=, accountId=, nextPage=
调用c:remove... 调用了c:remove后,这些参数值为: maxUser=, maxIdelTime=, accountId=, nextPage=, 145 13.2.413.2.413.2.413.2.4 捕获该标签中脚本代码或其他标签抛出的异常。 语法格式: other tag or scriptlets 使用该标签的例子如下: 13.2.513.2.513.2.513.2.5 类似 java 语言的 if 语句,如果 test 属性是 true,输出标签体内容。 语法格式: 属性说明如下: 使用例子: 属性名 属性类型 属性描述 var String 捕获的异常对象的名字 c_catch.jsp 属性名 属性类型 属性描述 test boolean 条件表达式,结果是 true 或false var String 保存 test 属性运算后的结果,即 true 或false scope String var 的范围 c_if.jsp <%@pageimport="vo.Student"%><%@taglibprefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@pagecontentType="text/html;charset=gb2312"language="java" %> 146 13.2.613.2.613.2.613.2.6 这几个标签配合使用,相当于 java 语言中的 switch case default 。 相当于 switch,相当于 case,相当于 default。 所以,的body 只能是空、或是 0个或多个加上 1个,且 必须出现在之前。 中的 test 属性介绍: 具体例子 c_choose.jsp 如下: JSTL:c:if的使用 对不起,你还的年龄过小,不能范围这个网页◎! 语法格式: 当testCondition1 为true 时,执行此段代码; 当testCondition2 为true 时,执行此段代码; …(其他标记) 上面所有的均不满足条件时,此处代码执行。 属性名 属性类型 属性描述 test boolean 结果是 boolean 的表达式 c_choose.jsp <%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"%> <%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%> c_choose.jsp 147 13.2.713.2.713.2.713.2.7 该标签是迭代标签,类似 java 中的 for()循环语句。但是注意标签不是 java 代码,标签的使 用类似 html 代码,用在 html 代码的位置。 语法格式: 如果满足循环测试条件将执行 body 的内容。 该标签的属性说明如下:

jstl之c:choosec:whenc:otherwise的使用

学生年龄小于20!

=20&&student.age<30}">

学生年龄大于等于20且小于30

=30&&student.age<40}">

学生年龄大于等于30小于40

学生年龄是其他情况

148 使用例子如下: 属性名 属性类型 属性描述 var String 对集合对象中的多个元素进行迭代时,某次正在进行的 循环中的一个集合元素。 items Collection 或数组 迭代的集合对象 varStatus String 表示迭代的状态,可以访问迭代自身的信息。 begin int 表示从集合中第几个元素开始迭代 end int 表示集合中迭代时执行到该位置循环结束。 step int 迭代的步长。 c_forEach.jsp <%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030" import="java.util.Collection,java.util.ArrayList,vo.Student"%> <%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%> c_forEach.jsp <% Collectionall=newnewnewnewArrayList(); forforforfor(intintintinti=0;i<5;i++){ Studentstu=newnewnewnewStudent(); stu.setId(i); stu.setName("student"+i); all.add(stu); } request.setAttribute("all",all); %>

输出上述集合中的每个元素:
---

149 13.313.313.313.3 JSTL JSTL JSTL JSTL 和和和和ELELELEL在在在在MVC MVC MVC MVC 中的主要应用中的主要应用中的主要应用中的主要应用 用户列表案例。下面,我们 MVC 设计模式中使用用户列表案例说明 JSTL 和EL在MVC 中的主要应用。 案例说明:数据库有 user 表,我们需要将该表的所有信息显示在 listUsers.jsp 页面中,如下 图。 需要设计的页面有:listUsers.jsp;辅助页面:index.jsp; 需要的 Servlet 有:ListUsers.java; 13.3.113.3.113.3.113.3.1 创建ListUsersListUsersListUsersListUsers ServletServletServletServlet 代码如下: packagepackagepackagepackageel; importimportimportimportjava.io.IOException; importimportimportimportjava.sql.SQLException; importimportimportimportjava.util.List; importimportimportimportjavax.servlet.ServletException; importimportimportimportjavax.servlet.http.HttpServlet; importimportimportimportjavax.servlet.http.HttpServletRequest; importimportimportimportjavax.servlet.http.HttpServletResponse; publicpublicpublicpublicclassclassclassclassListUsersextendsextendsextendsextendsHttpServlet{ publicpublicpublicpublicvoidvoidvoidvoiddoGet(HttpServletRequestrequest,HttpServletResponse response) throwsthrowsthrowsthrowsServletException,IOException{ Useruser=newnewnewnewUser(); trytrytrytry{ Listall=user.listAll(); ifififif(all.size()>0){ request.setAttribute("all",all); } request.getRequestDispatcher("listUsers.jsp").forward(request, response); }catchcatchcatchcatch(SQLExceptione){ //TODOTODOTODOTODOAuto-generatedcatchblock e.printStackTrace(); } } } 150 13.3.213.3.213.3.213.3.2 llll配置ListUsersListUsersListUsersListUsers ServletServletServletServlet 配置代码如下: 13.3.313.3.313.3.313.3.3 listUsers.jsplistUsers.jsplistUsers.jsplistUsers.jsp 在listUsers.jsp 中使用 JSTL 和EL进行输出记录。代码如下: 将项目部署到 Tomcat 下进行测试。在浏览器地址栏输入: listUsers el.ListUsers listUsers /el/listUsers <%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"import="jspjavabean.User,java.util.List"%> <%@taglibprefix="c"uri="http://java.sun.com/jsp/jstl/core"%> listUsers.jsp 用户列表 id姓名 密码 ${user.id}${user.name}${user.password}
没有任何记录!
151 注意:根据您在数据库插入的记录不同,您的输出结果可能与上图不同。 http://localhost:8080/jsp/el/listUsers 152 第15151515章 JSP+DAOJSP+DAOJSP+DAOJSP+DAO 前面我们介绍了 JSP+JavaBean 的登录、注册、查询等功能的案例中访问数据库操作是 在JavaBean 中实现的,JavaBean 负责业务逻辑即主要是数据库操作。 能否将数据库操作从业务逻辑中取出形成单独的一层? 我们可以按照上图来设计,对数据库操作的类都有一个对应的接口,该类实现了该接口 。 这种设计称为 DAO模式。接口中定义方法,实现类完成具体操作,这样就把对数据的访问 划分成数据抽象层和数据实现层。 把数据访问划分为抽象层和实现层有什么好处? ● 业务层与数据访问的底层细节无关; ● 避免了业务逻辑层出现大量的 JDBC 代码; 下面我们开始使用 JSP+DAO 模式完成用户登录功能。 153 15.115.115.115.1 JSP+DAO JSP+DAO JSP+DAO JSP+DAO 完成用户登录功能完成用户登录功能完成用户登录功能完成用户登录功能 15.1.115.1.115.1.115.1.1 创建POJOPOJOPOJOPOJO UserUserUserUser POJO:全称是 Plain Old Java Object,意思是平凡古老的 Java 对象,是只有属性和对应 属性的 get 和set 方法的类。 POJO User 类代码如下: packagepackagepackagepackagejspdao; importimportimportimportjava.util.Date; publicpublicpublicpublicclassclassclassclassUser{ privateprivateprivateprivateintintintintid; privateprivateprivateprivateStringname; privateprivateprivateprivateStringpassword; privateprivateprivateprivateStringemail; privateprivateprivateprivateintintintintage; privateprivateprivateprivateDatebirthday; privateprivateprivateprivatefloatfloatfloatfloatmoney; publicpublicpublicpublicintintintintgetId(){ returnreturnreturnreturnid; } publicpublicpublicpublicvoidvoidvoidvoidsetId(intintintintid){ thisthisthisthis.id=id; } publicpublicpublicpublicStringgetName(){ returnreturnreturnreturnname; } publicpublicpublicpublicvoidvoidvoidvoidsetName(Stringname){ thisthisthisthis.name=name; } publicpublicpublicpublicStringgetPassword(){ returnreturnreturnreturnpassword; } publicpublicpublicpublicvoidvoidvoidvoidsetPassword(Stringpassword){ thisthisthisthis.password=password; } publicpublicpublicpublicStringgetEmail(){ returnreturnreturnreturnemail; } publicpublicpublicpublicvoidvoidvoidvoidsetEmail(Stringemail){ thisthisthisthis.email=email; } publicpublicpublicpublicintintintintgetAge(){ 154 15.1.215.1.215.1.215.1.2 创建数据库连接类 DBConnectionDBConnectionDBConnectionDBConnection 我们还用 util 包中原来的数据库连接类 DBConnection。代码见前面的章节。 15.1.315.1.315.1.315.1.3 创建数据访问抽象层接口 UserDAOUserDAOUserDAOUserDAO 该接口定义了 login 方法,用于访问数据库验证用户是否存在。代码如下: 15.1.415.1.415.1.415.1.4 创建数据访问实现类 UserDAOImplUserDAOImplUserDAOImplUserDAOImpl UserDAOImpl 类是 UserDAO 的实现类,必须实现 UserDAOImpl 的方法,完成实际数 据库访问验证用户是否存在。代码如下: returnreturnreturnreturnage; } publicpublicpublicpublicvoidvoidvoidvoidsetAge(intintintintage){ thisthisthisthis.age=age; } publicpublicpublicpublicDategetBirthday(){ returnreturnreturnreturnbirthday; } publicpublicpublicpublicvoidvoidvoidvoidsetBirthday(Datebirthday){ thisthisthisthis.birthday=birthday; } publicpublicpublicpublicfloatfloatfloatfloatgetMoney(){ returnreturnreturnreturnmoney; } publicpublicpublicpublicvoidvoidvoidvoidsetMoney(floatfloatfloatfloatmoney){ thisthisthisthis.money=money; } } packagepackagepackagepackagejspdao; publicpublicpublicpublicinterfaceinterfaceinterfaceinterfaceUserDAO{ publicpublicpublicpublicUserlogin(Useruser); } packagepackagepackagepackagejspdao; importimportimportimportjava.sql.Connection; importimportimportimportjava.sql.PreparedStatement; importimportimportimportjava.sql.ResultSet; importimportimportimportjava.sql.SQLException; importimportimportimportutil.DBConnectionByDS; 155 15.1.515.1.515.1.515.1.5 创建登录需要的 JSP JSP JSP JSP 页面 表示层的页面有:login.jsp、login_do.jsp、admin.jsp、user.jsp。流程图见 jspjavabean 章 节 。 我们可以从 jspjavabean 下拷贝上述页面到 jspdao 文件夹,修改有关的超链接的 url。 login_do.jsp 代码如下: publicpublicpublicpublicclassclassclassclassUserDAOImplimplementsimplementsimplementsimplementsUserDAO{ publicpublicpublicpublicUserlogin(Useruser){ Connectionconn=nullnullnullnull; PreparedStatementps=nullnullnullnull; ResultSetrs=nullnullnullnull; trytrytrytry{ conn=DBConnectionByDS.getConnection(); Stringsql="select*from[user]wherename=?and password=?"; ps=conn.prepareStatement(sql); ps.setString(1,user.getName()); ps.setString(2,user.getPassword()); rs=ps.executeQuery(); ifififif(rs.next()){ user.setId(rs.getInt("id")); user.setName(rs.getString("name")); user.setPassword(rs.getString("password")); user.setEmail(rs.getString("email")); user.setAge(rs.getInt("age")); user.setBirthday(rs.getDate("birthday")); user.setMoney(rs.getFloat("money")); } }catchcatchcatchcatch(SQLExceptione){ e.printStackTrace(); }finallyfinallyfinallyfinally{ DBConnectionByDS.close(rs,ps,conn); } returnreturnreturnreturnuser; } } <%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"import="jspdao.*"%> JSPJavaBean登录处理页面 156 15.215.215.215.2 JSP+DAO JSP+DAO JSP+DAO JSP+DAO 完成用户注册功能完成用户注册功能完成用户注册功能完成用户注册功能 15.2.115.2.115.2.115.2.1 UserDAO UserDAO UserDAO UserDAO 中添加注册方法 register()register()register()register() 代码如下: 15.2.215.2.215.2.215.2.2 UserDAOImpl UserDAOImpl UserDAOImpl UserDAOImpl 实现类中添加方法 register()register()register()register() 代码如下: <% UserDAOuserDao=UserDAOFactory.getUserDAOInstance(); user=userDao.login(user); ifififif(user!=nullnullnullnull){//说明登录用户存在 //其他页面如果能从session中得到user说明是已经登录的合法用户 session.setAttribute("user",user); ifififif(user.getName().equals("admin")){ %> <% }elseelseelseelse{ %> <%} }elseelseelseelse{//说明登录用户不存在 %> <%} %> public boolean register(User user); publicpublicpublicpublicbooleanbooleanbooleanbooleanregister(Useruser){ Connectionconn=nullnullnullnull; PreparedStatementps=nullnullnullnull; ResultSetrs=nullnullnullnull; booleanbooleanbooleanbooleanflag=falsefalsefalsefalse; 157 15.2.315.2.315.2.315.2.3 创建注册需要的 JSP JSP JSP JSP 页面 注册需要的 JSP 页面有:register.jsp、register_do.jsp、registerSuccess.jsp、registerFail.jsp。注 意修改拷贝的 jspjavabean 中的 JSP 页面的 URL。 register_do.jsp 代码如下: trytrytrytry{ conn=DBConnectionByDS.getConnection(); Stringsql="insertinto[user](name,password,age) values(?,?,?)"; ps=conn.prepareStatement(sql); ps.setString(1,user.getName()); ps.setString(2,user.getPassword()); ps.setInt(3,user.getAge()); ps.executeUpdate(); flag=truetruetruetrue; }catchcatchcatchcatch(SQLExceptione){ e.printStackTrace(); }finallyfinallyfinallyfinally{ DBConnectionByDS.close(rs,ps,conn); } returnreturnreturnreturnflag; } <%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"import="jspdao.*"%> 注册处理页面

使用脚本段代码接收注册信息

<% //对请求设置编码格式 request.setCharacterEncoding("gbk"); %> <% UserDAOuserDao=UserDAOFactory.getUserDAOInstance(); booleanbooleanbooleanbooleanb=userDao.register(user); ifififif(b){//如果注册成功即数据库插入数据成功 //在session中保存user说明是合法用户,不用再登录了 session.setAttribute("user",user); 158 request.getRequestDispatcher("registerSuccess.jsp").forward(request,r esponse); }elseelseelseelse{ session.removeAttribute("user"); request.getRequestDispatcher("registerFail.jsp").forward(request,resp onse); } %> 159 第16161616章 Struts2+DAOStruts2+DAOStruts2+DAOStruts2+DAO Struts 是Apache 组织提供的一项开发源代码的工程。它是 Java Model II 体系结构的实 现。Model II 体系结构采用 JSP+Servlet+JavaBean 或JSP+Servlet+DAO 来完成 Web 应用。 下图是 JSP+Servlet+JavaBean 的图示。 请求 应用服务器 响应 JSPJSPJSPJSP页面 页面 页面 页面 JavaBeJavaBeJavaBeJavaBe anananan ServletServletServletServlet 数据库 服务器 本章首先介绍 MVC 设计模式的概念,接着介绍 Struts 框架和工作原理,最后用 Struts2+DAO 来完成用户登录和注册功能。 15.115.115.115.1 MVC MVC MVC MVC 设计模式简介设计模式简介设计模式简介设计模式简介 MVC 是一种流行的软件设计模式,它把系统分为 3个 部 分 :模型(Model)、视 图( View)、 控制器(Controller)。各个模块的功能见下表。 15.215.215.215.2 Struts2 Struts2 Struts2 Struts2 简介简介简介简介 Struts 是一组相互协作的类、servlet 和 JSP 标记组成一个可重用的 MVC 2 设计。这 个定义表示 Struts 是一个框架,而不是一个库,但 Struts 也包含了丰富的标记库和独立于 该框架工作的实用程序类。 15.2.115.2.115.2.115.2.1 视图 Struts2 中视图可以是 JSP 文件或 FreeMarker 模板。在这些文件中没有业务逻辑和模型 信息。 MVC 模块 描述 模型(Model) 代表应用程序数据和业务逻辑 视图(View) 提供可交互的用户界面,供用户输入数据和向用户显示模型数据 控制器(Controller) 响应客户请求,根据客户请求来操纵模型,并把模型的响应结果通过 视图展示给客户 160 15.2.215.2.215.2.215.2.2 控制器 Struts2 中控制器由 FilterDispatcher 过滤器和 Action 组成(含 Action Proxy)。它是一个 Servlet 过滤器。当请求到来时,首先传递请求给该过滤器,然后由 FilterDispatcher 根据配置 文件决定调用某个具体的 Action 来处理当前的请求。 15.2.315.2.315.2.315.2.3 模型 Struts 本身并不提供模型组件,但是它可以支持 Spring、Hibernate 等框架,与其他框架 组成应用。 以下是 Struts2 的流程框架图。 从上面的流程图可以看出,整个流程分为以下几步: ⑴ 客户端发送请求到 Web 容器(如 Tomcat); ⑵ Web 容器将请求传递给 Struts2 的控制器 FilterDispatcher; ⑶ FilterDispatcher 接收到请求,根据请求的 URL在ActionMapper(struts2 的配置文件 的实例:struts.xml)中查找处理该请求的 Action; ⑷ 如果找到了 Action 的配置信息,ActionProxy 创建 Action 实例,Action 实例处理请 求;⑸ 如果该 Action 使用了拦截器,那么拦截器会在 Action 实例调用的前后各执行一次; ⑹ Action 处理完请求后返回一个逻辑视图,控制器根据该逻辑视图找到对应的物理视 图(可以是 JSP、FreeMarker 模板)并将视图发送给客户端。 161 15.315.315.315.3 准备工作准备工作准备工作准备工作 为了在项目中使用 Struts2,需要进行如下工作:下载 struts2,在 MyEclipse 中配置构建 路径添加 Struts2 支持; ㈠ 下载 struts2 struts2 下载地址:http://struts.apache.org/。打开该页面后找到如下图所示的某个 Struts2 版本的连接,点击该链接进入; ㈡ 选择 Full Distribution struts-2.0-xx(如11 或14)-all.zip 进行下载; ㈢ 将下载的 zip 文件解压; ㈣ 在MyEclipse 中新建 user library(用户库)并为该库添加解压得到的 Struts2 的jar 文 件 。 162 ㈤ 在jsp 项目的 web.xml 中配置过滤器 FilterDispatcher,代码如下: 15.415.415.415.4 Struts2+DAO Struts2+DAO Struts2+DAO Struts2+DAO 完成用户登录案例完成用户登录案例完成用户登录案例完成用户登录案例 下面我们使用 Struts2+DAO 完成用户登录功能,说明 Struts2 框架的使用。 15.4.115.4.115.4.115.4.1 创建登录所需页面 ㈠ 创建 login.jsp,代码如下: ㈡ loginSuccess.jsp 和loginFail.jsp 代码如下: struts2 org.apache.struts2.dispatcher.FilterDispatcher struts2 /* <%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"%> <%@taglibprefix="s"uri="/struts-tags"%> 用户登录

用户登录


<%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"%> 163 15.4.215.4.215.4.215.4.2 创建ActionActionActionAction 创建 Action 类UserAction,该类是 POJO,必须有一个方法 execute,代码如下: <%@taglibprefix="s"uri="/struts-tags"%> loginStruts2success

登录成功!您的用户名是

登录成功!您的用户名是${sessionScope.user.name}

<%@pagelanguage="java"contentType="text/html;charset=GB18030" pageEncoding="GB18030"%> <%@taglibprefix="s"uri="/struts-tags"%> loginStruts2success

登录失败!

packagepackagepackagepackageuseStruts2; importimportimportimportjava.util.Map; importimportimportimportcom.opensymphony.xwork2.ActionContext; publicpublicpublicpublicclassclassclassclassUserAction{ privateprivateprivateprivateStringname; privateprivateprivateprivateStringpassword; publicpublicpublicpublicStringgetName(){ returnreturnreturnreturnname; } publicpublicpublicpublicvoidvoidvoidvoidsetName(Stringname){ thisthisthisthis.name=name; } publicpublicpublicpublicStringgetPassword(){ returnreturnreturnreturnpassword; } publicpublicpublicpublicvoidvoidvoidvoidsetPassword(Stringpassword){ thisthisthisthis.password=password; 164 15.4.215.4.215.4.215.4.2 创建struts.xml struts.xml struts.xml struts.xml 配置UserActionUserActionUserActionUserAction (一) 创建 struts.xml 我们需要找到前面下载的 struts2.0 的文件,到如下路径 struts-2.0.11\src\apps\blank\src\main\resources 下找到 struts.xml struts.xml struts.xml struts.xml 文件,将 struts.xml 文件复制到 WEB-INF/下, (二) 配置 Action 进行修改 struts.xml 文件,代码如下: } publicpublicpublicpublicStringexecute()throwsthrowsthrowsthrowsException{ //登录验证 UserDAOuserDAO=UserDAOFactory.getUserDAOInstance(); Useruser=newnewnewnewUser(); user.setName(name); user.setPassword(password); Useru=userDAO.login(user); ifififif(u!=nullnullnullnull){ ActionContextac=ActionContext.getContext(); Mapsession=ac.getSession(); session.put("user",user); returnreturnreturnreturn"success"; }elseelseelseelse{ returnreturnreturnreturn"fail"; } } } /useStruts2/loginSuccess.jsp /useStruts2/loginFail.jsp 165 15.4.315.4.315.4.315.4.3 创建DAODAODAODAO 数据访问层我们还用以前的 DAO:主要有 POJO User.java、DAO接口 UserDAO.java、 DAO实现类 UserDAOImpl.java、DAO工厂 UserDAOFactory.java。 UserDAO.java 和UserDAOImpl.java 中的方法是 login 方法,用来访问数据库实现登录 判断。 UserDAOFactory.java 代码如下: UserDAO.java 和UserDAOImpl.java 代码如下: packagepackagepackagepackageuseStruts2; publicpublicpublicpublicclassclassclassclassUserDAOFactory{ publicpublicpublicpublicstaticstaticstaticstaticUserDAOgetUserDAOInstance(){ returnreturnreturnreturnnewnewnewnewUserDAOImpl(); } } packagepackagepackagepackageuseStruts2; publicpublicpublicpublicinterfaceinterfaceinterfaceinterfaceUserDAO{ publicpublicpublicpublicUserlogin(Useruser); publicpublicpublicpublicbooleanbooleanbooleanbooleanregister(Useruser); } package useStruts2; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import util.DBConnectionByDS; public class UserDAOImpl implements UserDAO { public User login(User user) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; User u = null; try { conn = DBConnectionByDS.getConnection(); String sql = "select * from [user] where name=? and password=?"; 166 ps = conn.prepareStatement(sql); ps.setString(1, user.getName()); ps.setString(2, user.getPassword()); rs = ps.executeQuery(); if (rs.next()) { u = new User(); u.setId(rs.getInt("id")); u.setName(rs.getString("name")); u.setPassword(rs.getString("password")); u.setEmail(rs.getString("email")); u.setAge(rs.getInt("age")); u.setBirthday(rs.getDate("birthday")); u.setMoney(rs.getFloat("money")); } } catch (SQLException e) { e.printStackTrace(); } finally { DBConnectionByDS.close(rs, ps, conn); } return u; } public boolean register(User user) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; boolean flag = false; try { conn = DBConnectionByDS.getConnection(); String sql = "insert into [user] (name,password,age) values(?,?,?)"; ps = conn.prepareStatement(sql); ps.setString(1, user.getName()); ps.setString(2, user.getPassword()); ps.setInt(3, user.getAge()); ps.executeUpdate(); flag = true; } catch (SQLException e) { e.printStackTrace(); } finally { DBConnectionByDS.close(rs, ps, conn); } return flag; } } 167 完成后,将项目部署到 Tomcat 上,启动 Tomcat 进行测试。
还剩166页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

fjyqlw

贡献于2016-06-27

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf