《深入体验Java Web开发内幕——核心基础》目录

第1章 XML基础…………………………………………………………………………………………………… 1

… 指点迷津:什么是配置文件

1.1 认知XML………………………………………………………………………………………………… 1

1.1.1 XML的起源与作用…………………………………………………………………………….. 1

1.1.2 XML文档结构…………………………………………………………………………………… 2

1.1.3 XML与HTML的比较…………………………………………………………………………. 4

1.1.4 XML与数据库的比较………………………………………………………………………….. 4

1.2 XML的基本语法………………………………………………………………………………………. 5

1.2.1 文档声明………………………………………………………………………………………….. 5

…… 动手体验:加深对encoding属性的理解

1.2.2 元素定义………………………………………………………………………………………….. 9

1.2.3 属性定义………………………………………………………………………………………… 10

1.2.4 注释………………………………………………………………………………………………. 11

1.2.5 空格和换行的处理……………………………………………………………………………. 11

1.2.6 CDATA区………………………………………………………………………………………… 11

1.2.7 特殊字符………………………………………………………………………………………… 12

… 动手体验:加深对特殊字符的了解

1.2.8 处理指令(processing instruction)………………………………………………………. 14

… 动手体验:使用CSS控制XML文档的显示

1.3 XML约束模式………………………………………………………………………………………… 15

1.3.1 格式良好的(Well-formed)XML…………………………………………………………. 15

1.3.2 XML的约束模式………………………………………………………………………………. 15

1.3.3 XML约束模式语言……………………………………………………………………………. 16

1.3.4 有效的(Valid)XML…………………………………………………………………………. 17

1.4 DTD……………………………………………………………………………………………………… 17

1.4.1 初识DTD……………………………………………………………………………………….. 17

1.4.2 在XML文档中引入外部DTD文件……………………………………………………… 18

1.4.3 在XML文档中直接嵌入DTD定义语句……………………………………………….. 20

1.5 DTD的语法细节……………………………………………………………………………………… 21

1.5.1 元素定义………………………………………………………………………………………… 21

1.5.2 属性定义………………………………………………………………………………………… 22

1.5.3 实体定义………………………………………………………………………………………… 27

… 动手体验:加深对引用实体的了解

1.6 XML Schema…………………………………………………………………………………………… 31

1.6.1 XML Schema与DTD的比较……………………………………………………………….. 31

1.6.2 一个XML Schema例子……………………………………………………………………… 32

1.7 名称空间……………………………………………………………………………………………….. 34

1.7.1 名称空间的概念……………………………………………………………………………….. 34

1.7.2 名称空间声明………………………………………………………………………………….. 34

1.7.3 默认名称空间………………………………………………………………………………….. 35

1.7.4 属性的名称空间问题…………………………………………………………………………. 36

1.7.5 xml:space和xml:lang属性…………………………………………………………………… 36

1.8 引入XML Schema文档…………………………………………………………………………….. 37

1.8.1 使用名称空间引入XML Schema文档…………………………………………………… 37

1.8.2 不使用名称空间引入XML Schema文档………………………………………………… 39

1.9 思考与实践…………………………………………………………………………………………….. 39

第2章用Tomcat构建WEB站点…………………………………………………………………………….. 41

2.1 WEB应用的相关知识……………………………………………………………………………….. 41

2.1.1 HTTP协议………………………………………………………………………………………. 41

2.1.2 URL……………………………………………………………………………………………….. 41

2.1.3 网站系统的组成……………………………………………………………………………….. 42

2.1.4 主要的WEB服务器软件……………………………………………………………………. 43

2.2 安装Tomcat……………………………………………………………………………………………. 44

2.2.1 Tomcat简介…………………………………………………………………………………….. 44

2.2.2 获取Tomcat安装程序包……………………………………………………………………. 44

2.2.3 使用zip和tar.gz包安装Tomcat…………………………………………………………… 44

2.2.4 使用exe程序安装Tomcat………………………………………………………………….. 46

2.3 Tomcat的启动与停止……………………………………………………………………………….. 50

2.3.1 使用Tomcat服务程序……………………………………………………………………….. 50

… 多学两招:查找网络服务程序监听异常的问题

2.3.2 使用Tomcat程序组中的快捷菜单……………………………………………………….. 53

… 多学两招:了解Tomcat 4.1.3的快捷启动菜单的工作原理

2.3.3 使用tomcat.exe程序…………………………………………………………………………. 56

… 指点迷津:tomcat5.exe启动的tomcat程序不一定是tomcat5.exe自身所在的目录

2.3.4 startup.bat批处理文件………………………………………………………………………… 58

2.3.5 catalina.bat批处理文件……………………………………………………………………….. 61

2.3.6 使用批处理程序及查找Tomcat的启动问题…………………………………………… 65

… 动手体验:练习查找tomcat的启动错误

2.4 配置WEB站点的虚拟目录………………………………………………………………………… 68

2.4.1 虚拟WEB目录的映射关系…………………………………………………………………. 68

2.4.2 设置WEB站点的根目录……………………………………………………………………. 69

… 动手体验:修改WEB站点的默认根目录

2.4.3 设置WEB站点的虚拟子目录……………………………………………………………… 71

… 动手体验:设置WEB站点的虚拟子目录

… 脚下留心:war文件的内部目录结构

2.4.4 部署描述符与目录的默认网页…………………………………………………………….. 73

… 动手体验:设置目录的默认网页

2.5 配置虚拟主机…………………………………………………………………………………………. 75

2.5.1 浏览器访问WEB资源的过程……………………………………………………………… 75

… 动手体验:用telnet程序分析浏览器访问WEB资源的过程

… 多学两招:打开telnet程序的本地回显功能

2.5.2 虚拟主机及实现原理…………………………………………………………………………. 77

2.5.3 基于主机名的虚拟主机……………………………………………………………………… 78

…… 动手体验:使用Tomcat建立基于主机名的虚拟主机

2.5.4 基于端口号的虚拟主机……………………………………………………………………… 82

… 动手体验:使用Tomcat建立基于端口号的虚拟主机

2.5.5 基于IP地址的虚拟主机…………………………………………………………………….. 83

2.6 与专用WEB服务器的集成………………………………………………………………………… 83

2.6.1 集成的考虑因素……………………………………………………………………………….. 84

2.6.2集成技术的选择………………………………………………………………………………… 85

2.6.3 JK插件…………………………………………………………………………………………… 86

… 动手体验:下载JK插件

2.6.4 Tomcat的体系结构与JK插件的工作原理………………………………………………. 89

… 动手体验:查阅JK连接器的帮助文档

2.6.5 Tomcat与IIS服务器集成…………………………………………………………………… 93

2.6.6 Tomcat与Windows系统下的Apache服务器集成…………………………………… 100

2.6.7 与专业WEB服务器集成的现实问题…………………………………………………… 103

2.7 思考与实践…………………………………………………………………………………………… 103

第3章 HTTP协议详解………………………………………………………………………………………. 105

3.1 了解HTTP……………………………………………………………………………………………… 105

3.1.1 HTTP简介……………………………………………………………………………………… 105

3.1.2 HTTP 1.0的会话方式……………………………………………………………………….. 105

3.1.3 HTTP 1.1与HTTP 1.0的比较…………………………………………………………….. 106

3.1.4 HTTP消息的格式……………………………………………………………………………. 108

3.2 请求行与状态行………………………………………………………………………………………. 110

3.2.1 请求行与状态行……………………………………………………………………………… 110

… 动手体验:借助telnet程序直观体验请求行和状态行

3.2.2 使用GET和POST方式传递参数……………………………………………………….. 112

… 动手体验:在telnet程序中使用GET与POST方式传递参数

3.2.3 响应状态码……………………………………………………………………………………. 117

3.3 通用信息头…………………………………………………………………………………………….. 120

3.3.1 Cache-Control………………………………………………………………………………….. 120

3.3.2 Connection……………………………………………………………………………………… 121

… 动手体验:Connection头字段的作用

3.3.3 Date………………………………………………………………………………………………. 121

3.3.4 Pragma………………………………………………………………………………………….. 122

3.3.5 Trailer……………………………………………………………………………………………. 122

3.3.6 Transfer-Encoding……………………………………………………………………………. 122

3.3.7 Upgrade…………………………………………………………………………………………. 122

3.3.8 Via………………………………………………………………………………………………… 123

3.3.9 Warning…………………………………………………………………………………………. 123

3.4 请求头…………………………………………………………………………………………………… 123

3.4.1 Accept…………………………………………………………………………………………… 123

3.4.2 Accept-Charset………………………………………………………………………………… 123

3.4.3 Accept-Encoding………………………………………………………………………………. 123

3.4.4 Accept-Language………………………………………………………………………………. 124

… 动手体验:Accept-Language头字段的作用

3.4.5 Authorization……………………………………………………………………………………. 125

3.4.6 Expect…………………………………………………………………………………………… 126

3.4.7 From…………………………………………………………………………………………….. 126

3.4.8 Host………………………………………………………………………………………………. 126

3.4.9 If-Match………………………………………………………………………………………… 126

3.4.10 If-Modified-Since……………………………………………………………………………. 127

3.4.11 If-None-Match……………………………………………………………………………….. 127

3.4.12 If-Range……………………………………………………………………………………….. 127

3.4.13 If-Unmodified-Since………………………………………………………………………… 127

3.4.14 Max-Forwards……………………………………………………………………………….. 127

3.4.15 Proxy-Authorization…………………………………………………………………………. 128

3.4.16 Range…………………………………………………………………………………………… 128

3.4.17 Referer…………………………………………………………………………………………. 128

3.4.18 TE………………………………………………………………………………………………. 128

3.4.19 User-Agent……………………………………………………………………………………. 129

3.5 响应头…………………………………………………………………………………………………… 129

3.5.1 Accept-Ranges…………………………………………………………………………………. 129

3.5.2 Age……………………………………………………………………………………………….. 129

3.5.3 Etag………………………………………………………………………………………………. 129

3.5.4 Location…………………………………………………………………………………………. 130

… 动手体验:Location头字段的作用

3.5.5 Proxy-Authenticate……………………………………………………………………………. 130

3.5.6 Retry-After……………………………………………………………………………………… 130

3.5.7 Server……………………………………………………………………………………………. 131

3.5.8 Vary………………………………………………………………………………………………. 131

3.5.9 WWW-Authenticate…………………………………………………………………………… 131

3.6 实体头…………………………………………………………………………………………………… 131

3.6.1 Allow…………………………………………………………………………………………….. 132

3.6.2 Content-Encoding……………………………………………………………………………… 132

3.6.3 Content-Language…………………………………………………………………………….. 132

3.6.4 Content-Length………………………………………………………………………………… 133

3.6.5 Content-Location………………………………………………………………………………. 133

3.6.6 Content-MD5…………………………………………………………………………………… 133

3.6.7 Content-Range…………………………………………………………………………………. 133

3.6.8 Content-Type…………………………………………………………………………………… 134

… 动手体验:了解WEB服务器设置实体内容的MIME类型的原理

3.6.9 Expires…………………………………………………………………………………………… 135

3.6.10 Last-Modified…………………………………………………………………………………. 135

3.7 扩展头…………………………………………………………………………………………………… 136

3.7.1 Refresh………………………………………………………………………………………….. 136

3.7.2 Content-Disposition…………………………………………………………………………… 136

3.8 思考与实践…………………………………………………………………………………………… 137

第4章 Servlet开发基础…………………………………………………………………………………… 138

4.1 Servlet的有关概念………………………………………………………………………………… 138

4.1.1 什么是动态网页……………………………………………………………………………… 138

… 指点迷津:区分动态网页与动态HTML页面的概念

4.1.2 动态网页程序与引擎……………………………………………………………………….. 139

4.1.3 Servlet技术简介………………………………………………………………………………. 140

4.1.4 B/S系统架构与C/S系统架构…………………………………………………………….. 141

4.1.5 相关知识………………………………………………………………………………………. 143

4.2 Servlet应用入门…………………………………………………………………………………… 143

4.2.1 Servlet API介绍………………………………………………………………………………. 143

… 动手体验:查看Tomcat提供的Servlet API帮助文档

4.2.2 编写与编译Servlet程序……………………………………………………………………. 145

… 指点迷津:如何快速入门新技术

… 动手体验:编写与编译Servlet程序的过程

4.2.3 Servlet的注册与运行………………………………………………………………………… 146

… 动手体验:注册与访问Servlet程序

… 照猫画虎:如何编写web.xml文件

4.2.4 Servlet激活器…………………………………………………………………………………. 150

… 动手体验:使用Servlet激活器

4.2.5 缺省Servlet……………………………………………………………………………………. 151

… 动手体验:缺省Servlet的作用

4.2.6 Servlet的类装载器…………………………………………………………………………… 152

… 动手体验:Tomcat如何完成类的加载

… 指点迷津:区分Servlet的编译和运行环境

4.2.7 编写一个自动编译工具……………………………………………………………………. 158

4.3 Servlet的特点及运行过程………………………………………………………………………. 158

4.3.1 Servlet的特点…………………………………………………………………………………. 158

4.3.2 Servlet的运行过程…………………………………………………………………………… 160

4.3.3 Servlet的线程安全问题…………………………………………………………………….. 164

… 动手体验:Servlet的并发访问与线程安全问题

… 指点迷津:哪些情况下要考虑线程安全问题

4.4 ServletConfig接口………………………………………………………………………………….. 167

4.4.1 getInitParameterNames方法……………………………………………………………….. 168

4.4.2 getInitParameter方法………………………………………………………………………… 168

4.4.3 getServletName方法…………………………………………………………………………. 168

4.4.4 getServletContext方法………………………………………………………………………. 168

4.4.5 GenericServlet类实现ServletConfig接口的目的……………………………………… 169

4.4.6 ServletConfig的应用举例…………………………………………………………………… 169

… 动手体验:ServletConfig对象的应用

4.5 GenericServlet与HttpServlet类……………………………………………………………….. 171

4.5.1 理解回调方法………………………………………………………………………………… 171

4.5.2 init方法…………………………………………………………………………………………. 172

… 指点迷津:覆盖无参数的init()方法来编写初始化代码的好处

4.5.3 service方法……………………………………………………………………………………. 174

4.5.4 destroy方法……………………………………………………………………………………. 175

4.5.5 getServletConfig方法………………………………………………………………………… 175

4.5.6 getServletInfo方法…………………………………………………………………………… 175

4.5.7 doXxx方法…………………………………………………………………………………….. 175

… 动手体验:doGet方法与doPost方法的作用

… 指点迷津:如何理解“在自己的程序代码中不能调用回调方法”

4.5.8 浏览器缓存内幕与getLastModified方法………………………………………………. 175

… 动手体验:揭开浏览器缓存的奥秘

4.6 ServletContext接口…………………………………………………………………………………. 179

4.6.1 获取WEB应用程序的初始化参数………………………………………………………. 179

… 动手体验:WEB应用程序的初始化参数的设置与应用

4.6.2 记录日志………………………………………………………………………………………. 181

… 动手体验:WEB应用程序的日志记录功能

… 多学两招:JDK中提供的日志记录模块

4.6.3 application域范围的属性…………………………………………………………………… 186

4.6.4 访问资源文件………………………………………………………………………………… 187

… 动手体验:在Servlet程序中使用FileInputStream类的问题

… 动手体验:使用ServletContext接口和ClassLoader类中的方法访问资源文件

4.6.5 获取虚拟路径所映射的本地路径……………………………………………………….. 191

4.6.6 WEB应用程序之间的访问…………………………………………………………………. 191

… 动手体验:访问其他WEB应用程序

4.6.7 ServletContext接口中的其他方法………………………………………………………… 193

4.7 思考与实践……………………………………………………………………………………………. 194

第5章 HttpServletResponse的应用……………………………………………………………………. 196

5.1 准备实验环境…………………………………………………………………………………………. 196

5.2 HttpServletResponse简介……………………………………………………………………….. 197

5.3 产生响应状态行……………………………………………………………………………………… 197

5.3.1 状态码常量……………………………………………………………………………………. 197

5.3.2 setStatus方法………………………………………………………………………………….. 198

5.3.3 sendError方法………………………………………………………………………………… 198

5.4 构建响应消息头……………………………………………………………………………………… 198

5.4.1 addHeader与setHeader方法……………………………………………………………….. 199

5.4.2 addIntHeader与setIntHeader方法………………………………………………………… 199

5.4.3 addDateHeader与setDateHeader方法……………………………………………………. 199

5.4.4 setContentLength方法……………………………………………………………………….. 199

5.4.5 setContentType方法…………………………………………………………………………. 200

5.4.6 setCharacterEncoding方法…………………………………………………………………. 200

5.4.7 setLocale方法…………………………………………………………………………………. 200

5.4.8 containsHeader方法………………………………………………………………………….. 201

5.5 响应消息头的实用案例…………………………………………………………………………….. 201

5.5.1 Servlet的中文输出问题…………………………………………………………………….. 201

… 动手体验:浏览器查看网页文档时怎样选择字符集编码

… 动手体验:Servlet的中文输出问题及解决之道

… 脚下留心:注意传递给setContentType方法的参数值的大小写

… 多学两招:修改某个Servlet将导致整个WEB应用程序被重新加载

5.5.2 让浏览器定时刷新网页或跳转至其他页面…………………………………………… 210

… 动手体验:Refresh头字段的作用效果

5.5.3 禁止浏览器缓存当前文档内容…………………………………………………………… 211

… 动手体验:浏览器的缓存问题和解决方案

5.5.4 使用标签模拟响应消息头……………………………………………………….. 213

… 动手体验:使用标签解决浏览器查看网页时的中文乱码问题

… 多学两招:网页文档应尽量采用UTF-8编码

5.6 创建响应正文…………………………………………………………………………………………. 215

5.6.1 getOutputStream与getWriter方法……………………………………………………….. 215

5.6.2 getWriter方法的一些相关小疑问………………………………………………………… 216

… 动手体验:getWriter方法的一些相关问题

5.6.3 输出缓冲区……………………………………………………………………………………. 218

… 动手体验:Servlet引擎处理输出缓冲区的细节

5.6.4 实现动态文件内容的下载…………………………………………………………………. 221

… 动手体验:实现动态文件内容的下载

5.6.5 图像访问计数器……………………………………………………………………………… 223

… 动手体验:使用标签实现静态HTML页面的访问次数统计和显示

… 多学两招:如何动态产生大小可变的图像

5.7 请求重定向与请求转发…………………………………………………………………………….. 230

5.7.1 RequestDispatcher接口……………………………………………………………………… 231

5.7.2 用include方法实现资源包含…………………………………………………………….. 231

… 动手体验:RequestDispatcher.include方法的应用细节

5.7.3 用forward方法实现请求转发……………………………………………………………. 237

… 动手体验:RequestDispatcher.forward方法的应用细节

… 动手体验:RequestDispatcher.forward方法的相对路径问题

5.7.4请求转发的运行流程………………………………………………………………………… 246

5.7.5 用sendRedirect方法实现请求重定向…………………………………………………… 250

… 动手体验:sendRedirect方法的应用

5.7.6请求重定向的运行流程…………………………………………………………………….. 252

5.7.7 请求重定向与请求转发的比较…………………………………………………………… 257

5.7.8 缺省Servlet的缓存问题……………………………………………………………………. 258

… 动手体验:缺省Servlet的缓存问题

5.8 思考与实践……………………………………………………………………………………………. 261

第6章 HttpServletRequest的应用……………………………………………………………………… 263

6.1 HttpServletRequest简介………………………………………………………………………….. 263

6.2 获取请求行的相关信息…………………………………………………………………………… 263

6.2.1 getMethod方法……………………………………………………………………………….. 263

6.2.2 getRequestURI方法………………………………………………………………………….. 263

6.2.3 getQueryString方法………………………………………………………………………….. 264

6.2.4 getProtocol方法………………………………………………………………………………. 264

6.2.5 getContextPath方法………………………………………………………………………….. 264

6.2.6 getPathInfo方法………………………………………………………………………………. 264

6.2.7 getPathTranslated方法………………………………………………………………………. 265

6.2.8 getServletPath方法…………………………………………………………………………… 265

6.2.9 获取请求行信息的综合实例……………………………………………………………… 265

… 动手体验:与请求行信息相关的各个方法的作用

6.3 获取网络连接信息…………………………………………………………………………………. 266

6.3.1 getRemoteAddr方法…………………………………………………………………………. 266

6.3.2 getRemoteHost方法………………………………………………………………………….. 267

6.3.3 getRemotePort方法………………………………………………………………………….. 267

6.3.4 getLocalAddr方法……………………………………………………………………………. 267

6.3.5 getLocalName方法…………………………………………………………………………… 267

6.3.6 getLocalPort方法…………………………………………………………………………….. 267

6.3.7 getServerName方法………………………………………………………………………….. 267

6.3.8 getServerPort方法……………………………………………………………………………. 267

6.3.9 getScheme方法……………………………………………………………………………….. 267

6.3.10 getRequestURL方法………………………………………………………………………… 268

6.4 获取请求头信息……………………………………………………………………………………. 268

6.4.1 getHeader方法………………………………………………………………………………… 268

6.4.2 getHeaders方法……………………………………………………………………………….. 268

6.4.3 getHeaderNames方法………………………………………………………………………… 268

6.4.4 getIntHeader方法…………………………………………………………………………….. 269

6.4.5 getDateHeader方法…………………………………………………………………………… 269

6.4.6 getContentType方法…………………………………………………………………………. 269

6.4.7 getContentLength方法………………………………………………………………………. 269

6.4.8 getCharacterEncoding方法…………………………………………………………………. 269

6.4.9 获取所有请求头的编程实例……………………………………………………………… 269

… 动手体验:获取请求消息中的所有请求头信息

6.4.10 利用Referer请求头阻止“盗链”…………………………………………………….. 272

… 动手体验:利用Referer请求头阻止“盗链”

6.4.11 利用Referer请求头隐藏JavaScript源码…………………………………………….. 273

… 动手体验:利用Referer请求头隐藏JavaScript源代码

6.4.12 BASE64编码及客户端身份认证………………………………………………………… 278

… 动手体验:BASIC验证的交互过程

6.5 浏览器传递参数信息的细节…………………………………………………………………….. 284

6.5.1 使用GET方式传递参数…………………………………………………………………… 285

… 脚下留心:不要使用GET方式提交包含口令的FORM表单

6.5.2 使用POST方式传递参数…………………………………………………………………. 285

6.5.3 提交、重置、普通按钮如何传送参数…………………………………………………. 286

… 动手体验:了解提交、重置、普通按钮的参数传递细节

6.5.4 单行与多行文本输入框如何传送参数…………………………………………………. 287

… 动手体验:了解单行与多行文本输入框的参数传递细节

6.5.5 单选按钮与复选框如何传送参数……………………………………………………….. 288

… 动手体验:了解单选按钮与复选框的参数传递细节

6.5.6 隐藏表单字段与图像字段如何传送参数………………………………………………. 289

… 动手体验:了解隐藏表单字段元素与图像字段元素的参数传递细节

6.5.7 列表框如何传送参数……………………………………………………………………….. 290

… 动手体验:了解列表框的参数传递细节

6.5.8 使用Javascript防止重复提交表单………………………………………………………. 290

… 动手体验:使用Javascript防止重复表单提交

6.6 获取请求参数……………………………………………………………………………………….. 293

6.6.1 getParameter方法…………………………………………………………………………….. 293

6.6.2 getParameterValues方法…………………………………………………………………….. 293

6.6.3 getParameterNames方法……………………………………………………………………. 293

6.6.4 getParameterMap方法……………………………………………………………………….. 294

6.6.5 获取请求参数的编程实例…………………………………………………………………. 294

… 动手体验:获取请求消息中的所有参数

6.6.6 一次性处理多个列表项的实用案例…………………………………………………….. 296

… 动手体验:一次性处理多个列表项

6.6.7单选列表框的处理经验…………………………………………………………………….. 300

6.7 获取请求消息的实体内容……………………………………………………………………….. 300

6.7.1 getInputStream与getReader方法…………………………………………………………. 301

… 多学两招:使用ServletInputStream对象读取文本格式的实体内容

6.7.2 分析文件上传的请求消息结构…………………………………………………………… 301

… 动手体验:分析文件上传的请求消息结构

6.8 利用请求域属性传递信息…………………………………………………………………………. 311

6.8.1 setAttribute方法………………………………………………………………………………. 311

6.8.2 getAttribute方法………………………………………………………………………………. 312

6.8.3 removeAttribute方法…………………………………………………………………………. 312

6.8.4 getAttributeNames方法……………………………………………………………………… 312

6.8.5 请求域属性的编程实例……………………………………………………………………. 312

… 动手体验:请求域属性的应用

… 多想一想:请求域属性与URL参数的应用区别

6.9 请求参数的中文读取问题……………………………………………………………………….. 317

6.9.1 了解中文字符的URL编码………………………………………………………………… 317

… 动手体验:中文字符的URL编码和解码

6.9.2 浏览器怎样进行URL编码………………………………………………………………… 318

… 动手体验:浏览器怎样对FORM表单内容进行URL编码

6.9.3 getCharacterEncoding方法…………………………………………………………………. 319

6.9.4 setCharacterEncoding方法…………………………………………………………………. 319

6.9.5 getParameter方法的中文问题…………………………………………………………….. 319

… 动手体验:使用getParameter方法读取请求参数时的中文乱码问题

6.9.6 一些参考经验………………………………………………………………………………… 332

6.10 思考与实践………………………………………………………………………………………….. 333

第7章 会话与状态管理……………………………………………………………………………………. 334

7.1 WEB应用中的会话与会话状态………………………………………………………………… 334

7.1.1 会话与会话状态简介……………………………………………………………………….. 334

7.1.2 如何实现有状态的会话……………………………………………………………………. 334

7.2 Cookie………………………………………………………………………………………………… 335

7.2.1 什么是Cookie………………………………………………………………………………… 335

7.2.2 Set-Cookie2响应头字段…………………………………………………………………….. 337

7.2.3 Cookie请求头字段…………………………………………………………………………… 338

7.3 在Servlet程序中使用Cookie………………………………………………………………….. 339

7.3.1 Cookie类……………………………………………………………………………………….. 339

7.3.2 HttpServletResponse.addCookie方法…………………………………………………….. 340

7.3.3 HttpServletRequest.getCookies方法………………………………………………………. 340

7.3.4 Cookie的综合实例…………………………………………………………………………… 341

… 动手体验:Cookie的工作细节

7.4 Session………………………………………………………………………………………………. 354

7.4.1 什么是Session……………………………………………………………………………….. 354

7.4.2 Session的跟踪机制………………………………………………………………………….. 354

7.4.3 Session的超时管理………………………………………………………………………….. 355

7.4.4 HttpSession接口中的方法………………………………………………………………….. 356

7.4.5 HttpServletRequest接口中的Session方法……………………………………………… 357

… 多想一想:什么情况下该调用request.getSession(false)方法

7.4.6 application与session域范围的属性比较……………………………………………….. 358

… 动手体验:application和session域范围的属性的差异

7.4.7 利用Cookie实现Session跟踪……………………………………………………………. 364

… 动手体验:如何利用Cookie实现Session跟踪

7.4.8 利用URL重写实现Session跟踪………………………………………………………… 367

… 动手体验:利用URL重写实现Session跟踪

7.5 Session的典型案例………………………………………………………………………………. 368

7.5.1 使用Session实现购物车…………………………………………………………………… 368

… 动手体验:使用Session实现购物车功能

7.5.2 利用Session防止表单重复提交…………………………………………………………. 375

… 多学两招:MD5算法及其应用

… 动手体验:利用Session防止表单重复提交

7.5.3 利用Session实现一次性验证码…………………………………………………………. 382

… 动手体验:利用Session实现一次性验证码

… 多学两招:用时间间隔限制用户连续发帖

7.5.4 跟踪用户上次访问站点的时间及Cookie中文问题…………………………………. 387

7.6 Session的持久化管理……………………………………………………………………………. 389

7.6.1 Session的持久化……………………………………………………………………………… 389

7.6.2 Tomcat中的Session持久化管理…………………………………………………………. 390

… 动手体验:Tomcat的Session持久化

7.7 思考与实践………………………………………………………………………………………………….. 394

第8章 JSP……………………………………………………………………………………………………… 396

8.1 JSP入门………………………………………………………………………………………………. 396

8.1.1 建立对JSP的直观认识……………………………………………………………………. 396

… 动手体验:编写最基本JSP程序

8.1.2 JSP的运行原理………………………………………………………………………………. 399

… 多学两招:让JSP引擎不检测JSP页面是否发生修改

8.1.3 分析JSP所生成的Servlet代码………………………………………………………….. 402

… 指点迷津:out.print语句与out.write语句的区别

8.1.4 JSP隐式对象………………………………………………………………………………….. 407

… 多学两招:使用JSP页面学习Servlet API

8.1.5 注册与配置JSP页面的访问路径……………………………………………………….. 409

8.1.6 JSP与JavaScript的综合应用……………………………………………………………… 409

… 动手体验:JSP与JavaScript的综合应用

… 多学两招:降低代码的嵌套层次,提高程序的易阅读性

8.1.7 JSP与Servlet的应用比较………………………………………………………………….. 417

8.2 JSP基本语法………………………………………………………………………………………… 418

8.2.1 JSP模版元素………………………………………………………………………………….. 418

8.2.2 JSP表达式…………………………………………………………………………………….. 418

8.2.3 JSP脚本片断………………………………………………………………………………….. 418

8.2.4 JSP声明………………………………………………………………………………………… 420

8.2.5 EL表达式………………………………………………………………………………………. 422

… 动手体验:EL表达式将null输出为空字符串(“”)的好处

8.2.6 JSP注释………………………………………………………………………………………… 424

… 动手体验:JSP注释与JSP页面中的Java注释和HTML注释的区别

8.2.7 特殊字符序列的转义处理…………………………………………………………………. 425

8.2.8 如何查找JSP页面中的错误……………………………………………………………… 426

… 动手体验:查找JSP页面中的错误

8.3 JSP指令………………………………………………………………………………………………. 430

8.3.1 JSP指令简介………………………………………………………………………………….. 430

8.3.2 page指令……………………………………………………………………………………….. 430

… 动手体验:JSP页面中的异常处理

… 多学两招:在web.xml文件中设置全局错误处理

… 多学两招:如何识别web.xml文件所遵循的Servlet规范版本

8.3.3 include指令……………………………………………………………………………………. 435

… 动手体验:include指令的特性

8.4 out对象……………………………………………………………………………………………….. 438

… 动手体验:out对象的应用特性

… 指点迷津:将请求转发给静态HTML页面的实验现象为何不稳定

8.5 pageContext对象……………………………………………………………………………………. 441

8.5.1 pageContext对象简介……………………………………………………………………….. 441

8.5.2 获得其他隐式对象………………………………………………………………………….. 442

8.5.3 引入和跳转到其他资源……………………………………………………………………. 442

… 动手体验:PageContext.forward方法的应用细节

8.5.4 访问各个域范围中的属性…………………………………………………………………. 444

… 动手体验:存储在pageContext对象中的属性的作用域

8.5.5 pushBody与popBody方法…………………………………………………………………. 446

8.6 JSP标签………………………………………………………………………………………………. 448

8.6.1 标签…………………………………………………………………………….. 449

… 动手体验:标签的特性

8.6.2 标签……………………………………………………………………………. 451

… 动手体验:标签的特性

8.6.3 标签………………………………………………………………………………. 452

8.6.4 标签………………………………………………………………………………. 453

8.6.5 脚本元素标签………………………………………………………………………………… 454

8.6.6 指令标签………………………………………………………………………………………. 454

8.6.7 标签…………………………………………………………………………………. 454

8.6.8 完全使用标签编写JSP页面……………………………………………………………… 455

8.7 JSP的中文乱码问题…………………………………………………………………………………. 455

8.7.1 JSP中文乱码的根源………………………………………………………………………… 455

… 动手体验:JSP引擎翻译JSP页面时的中文乱码问题

8.7.2 静态引入的中文乱码问题…………………………………………………………………. 463

… 动手体验:静态引入时的中文乱码问题

8.7.3 标签传递中文参数时的问题……………………………………………….. 464

… 动手体验:标签传递中文参数时的问题

8.7.4 JSP中文乱码的总结………………………………………………………………………… 466

8.8 思考与实践…………………………………………………………………………………………………… 468

第9章 JavaBean在JSP中的应用………………………………………………………………………. 470

9.1 JavaBean简介………………………………………………………………………………………… 470

9.2 JavaBean的属性…………………………………………………………………………………….. 470

9.1.1 JavaBean的属性简介………………………………………………………………………… 470

9.1.2 简单属性………………………………………………………………………………………. 471

9.1.3 Indexed属性…………………………………………………………………………………… 472

9.3 JavaBean在JSP中的应用………………………………………………………………………… 473

9.3.1 在JSP中如何使用JavaBean………………………………………………………………. 473

9.3.2 标签……………………………………………………………………………. 474

… 动手体验:带标签体的标签的执行情况

9.3.3 标签……………………………………………………………………….. 477

… 动手体验:标签的应用

… 多学两招:利用JSP表达式对JavaBean的特殊类型的属性进行赋值

9.3.4 标签……………………………………………………………………….. 481

9.3.5 使用JavaBean的注意事项………………………………………………………………… 481

9.4 JSP开发模式…………………………………………………………………………………………… 482

9.4.1 MVC设计模式………………………………………………………………………………… 482

9.4.2 JSP开发模式………………………………………………………………………………….. 483

9.4.3 用模式一实现用户登录功能……………………………………………………………… 484

… 动手体验:用JSP模式一实现用户登录功能

9.4.4 用模式二实现用户注册功能……………………………………………………………… 493

… 动手体验:用JSP模式二实现用户注册功能

9.5 思考与实践…………………………………………………………………………………………….. 504

XML基础

XML作为一种通用的数据交换格式,应用越来越广泛。目前许多系统的配置文件都使用XML格式,本书中所涉及到的众多配置文件都是XML格式的,新的JSP规范也推出了采用XML语法的JSP文档,因此,要深入学习和掌握Java Web开发技术,必须有一些基本的XML语言知识。由于XML的通用性和广泛应用,在读者以后实际项目开发和应用中,很多地方都要用到XML方面的知识,所以,对XML知识的了解和掌握,已经是从事电子商务网站和相关系统开发的编程人员所必须掌握的基本知识。

F指点迷津:什么是配置文件

配置文件就是记录应用程序的配置信息的文件。例如,某个程序要连接网络上的数据库系统时,需要指定数据库服务器的ip地址、服务器的网络监听端口号、数据库的名称、用户名和密码等信息,这些信息可以作为应用程序的配置信息来对待,即不要将这些信息写死在源程序中,而是写在一个文本文件中。应用程序要连接数据库系统时,从该文本文件中读取所需要的信息,如果连接的数据库系统的信息发生了改变,则只需要修改该文本文件,而不用修改源程序,这个文本文件就是应用程序的配置文件。传统的配置文件通常采用如下格式:

#Db.Properties

DBServer=192.168.0.100

Port=1443

Database=emp

Username=zxx

Password=123

上面这种格式的配置文件只能表述一些简单的信息,而很难表达具有层次结构和数据项目要动态增加的信息。例如,如果要在一个文件中表达出“一个国家中的每个省及省长的名称、每个省下面的每个市及市长的名称、每个市下面的每个镇及镇长名称”,使用上面的格式就很难表达。采用XML格式的配置文件很容易表达出这种层次结构,具体细节请参看本章后面部分的讲解。

文档声明

在一个完整的XML文档中必须包含一个XML文档声明,该声明必须位于文档的第一行。这个声明表示该文档是一个XML文档,以及遵循的是哪个XML版本的规范。最简单的XML文档声明语法如下:

在“<”和“?”之间、“?”和“>”之间以及第一个“?”和xml之间不能有空格,这就是XML语法严格性的一个体现。在第二个“?”之前可以没有、也可以有一个或多个空格。声明语句中的version属性表示XML的版本,因为解析器对不同的版本的解析肯定会有区别,尽管目前只有1.0版本,但在声明中必须指定version属性。

由于人们可以采用不同的字符编码集来书写一个字符内容完全相同的XML文档,所以,XML软件工具(包括分析器)就需要知道该XML文档所使用的字符编码方式。这可以通过在XML文档声明中指定encoding属性来说明,例如,使用下面的语句来指明文档中的字符编码方式为GB2312编码。

W3C的XML1.0规范里规定,所有的XML解析器必须接受UTF-8和UTF-16编码的Unicode字符,所以,符合XML 规范的软件工具一定都支持这两种Unicode编码。如果XML声明中没有设置encoding属性来明确指定文档所用的字符编码方式,则一律以Unicode编码看待。XML解析器通过寻找XML文档开始处的字节顺序标记,能够自动检测出文档中的Unicode编码是UTF8,还是UTF16。也就是说,encoding属性默认的设置是Unicode编码,如果文档中的字符是以UTF-8或者是UTF-16作为编码,则可以不设置这个属性。

在XML文档声明语句中,还可以指定另外一个可选属性:standalone,例如:

standalone属性用于说明文档是否是独立的,如果将其设置为“yes”,则表示该文档没有依赖外面的任何文件而可以独立存在,即不需要DTD文件来验证其中的标识是否有效,也不需要XSL、CSS文件来控制其显示外观;将standalone属性设置为“no”时,则表示该文档依赖于外面的某个文件,例如,依赖于某个DTD文件或XSL、CSS文件。standalone属性的默认值为“yes”。

注意:如果同时设置了encoding和standalone属性,standalone属性要位于encoding属性之后。

:动手体验:加深对encoding属性的理解

对于含有中文字符的XML,其中的字符可以采用unicode来编码或GB2312(简体中文字符编码)编码来表示,如果文档中的字符使用的是GB2312编码,则必需设置为encoding属性为GB2312,下面通过一个实验来说明这个问题。

(1)用Windows自带的记事本程序创建一个名为book.xml的文件,文件内容如例程1-1所示。

例程1-1 book.xml

<?xml version="1.0" ?>
<书架>
    <书>
        <书名>Java就业培训教程</书名>
        <作者>张孝祥</作者>
        <售价>39.00元</售价>
    </书>
    <书>
        <书名>JavaScript网页开发</书名>
        <作者>张孝祥</作者>
        <售价>28.00元</售价>
    </书>
</书架>

(2)用IE5.0以上的浏览器打开book.xml文件,看到的结果如图1.2所示。

错误提示的信息是“文本内容中发现无效字符”,这就是因为在book.xml的XML文档声明语句中没有明确指定文档中的字符编码方式,浏览器就会用默认的Unicode编码来解析该文档,而该文档中的字符实际上使用的是GB2312编码,而非Unicode编码。

(3)单击浏览器的“查看”à“源文件”菜单,将打开的book.xml文件内容中的第一行修改成如下形式:

保存修改后,刷新显示book.xml文件的浏览器窗口,看到的结果如图1.3所示。单击某个标签前面的减号(-),嵌套在该标签中的所有内容将被折叠起来,标签前面的减号(-)也将变成加号(+)。单击某个标签前面的加号(+),嵌套在该标签中的所有内容将被展开,标签前面的加号(+)也将变成减号(-)。

(4)在上面打开book.xml文件的记事本程序中,单击“文件”à“另存为”菜单,在打开的“另存为”对话框中,选择“保存类型”为“所有文件”,编码为“UTF-8”,如图1.4所示。

以UTF-8编码保存book.xml文件后,尽管在记事本程序窗口中显示的效果没有任何变化,但是book.xml文件内部存储的数据已经改变,这通过比较book.xml保存前后的文件大小就可以看出来。刷新显示book.xml文件的浏览器窗口,看到的结果如图1.5所示。

因为现在的book.xml文件的字符编码已经转换为UTF-8,而文档的起始声明中指定encoding属性为GB2312,所以,浏览器在解析book.xml文件时会发生错误。

(5)将book.xml的文档起始声明的encoding属性修改为UTF-8,保存后刷新显示book.xml文件的浏览器窗口,就又可以看到类似图1.3所示的正常显示效果了。