XML

xml文件

概述

XML 即 Extensible Markup Language,是一种可扩展的标记语言,使用标签来描述数据,并且可以自定义标签

作用

存储、传输数据或者用于软件配置文件

标签

  • 标签由尖括号和合法标识
  • 标签必须成对出现,有些特殊的标签不成对但是必须有结束标记,如 <student></student></adderss>
  • 标签中可以定义属性,属性和标签名用空格隔开,属性值需要用双引号引起来,如 <student id="1"></student>
  • 一个 xml 文件有且仅有一个根标签,标签需要正确嵌套

语法

  • 文档声明必须是文件第一行第一列,格式如下

    1
    <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
  • version 属性:必选的

  • encoding 属性:可选的,指定打开该文件时使用的字符编码表,一般是 UTF-8

  • standalone 属性:可选的,指定该 xml 文件是否依赖其他的的 xml 文件,取值为 yes/no

注释

1
<!--注释-->

特殊字符

xml中的表示 字符 说明
&lt; < 小于号
&gt; > 大于号
&amp; & 与号
&apos; ‘’ 单引号
&quot; “” 双引号

CDATA区

1
<![CDATA[内容]]>

内容部分只会被当作文本看待

DOM 解析思想

  • DOM(Document Object Model) 是文档对象模型,将文档各个部分看成对应的对象

  • 将 xml 文件加载到内存中,形成一个树形结构,再获取对应的值

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8" ?>
<students>
<student id="1">
<name>张三</name>
<age>18</age>
</student>
<student id="2">
<name>李四</name>
<age>20</age>
</student>
</students>

属性 说明
Document对象 表示整个文档
Element对象 表示所有的标签
Attribute对象 表示所有属性
Text对象 表示所有文本内容

约束

约束用于限定 xml 文件中可以使用的标签以及属性

引入 DTD 约束的方式

  • 引入本地 DTD

    <!DOCTYPE 根元素名称 SYSTEM 'DTD文件路径'>

  • 在 xml 文件内部引入

    <!DOCTYPE 根元素名称 [DTD文件内容]>

  • 引入网络中的 DTD

    <!DOCTYPE 根元素名称 PUBLIC "DTD文件名称" "DTD文档的URL">

DTD 文档中语法规则

定义元素

语法:<!ELEMENT 元素名 元素类型>

  • 简单元素取值 :EMPTYANYPCDATA,分别表示 标签体为空可以为空可以不为空元素内容部分为字符串

  • 复杂元素则需要将该元素中的所有元素列出,规则是

    • 多个元素使用 ,| 隔开,, 表示定义子元素的顺序, | 表示子元素只能出现任意一个

    • 在子元素后面使用 ?+* 分别可以指定子元素出现的次数是 零次或一次一次或多次零次或多次

    • 如果不写则表示一次

      1
      2
      3
      4
      <!ELEMENT students (student+)>
      <!ELEMENT student (name,age)>
      <!ELEMENT name (#PCDATA)>
      <!ELEMENT age (#PCDATA)>

定义属性

语法:<!ATTLIST 元素名称 属性名称 属性类型 属性约束>

  • 元素名称:指出该属性属于哪个元素

  • 属性名称:指出属性的名称

  • 属性类型:CDATA 表示普通的字符串

  • 属性约束:有三个常用取值 REQUIREDIMPLIEDFIXED value,分别表示 必需的非必需的固定值的(value是指出的固定值)

    1
    <!ATTLIST student id CDATA #REQIRED>

Servlet技术

Servlet

概述

  • Servlet 是运行在 web 服务器端的应用程序,使用 Java 语言编写

  • Servlet 对象主要封装了对 HTTP 请求的处理,它的运行需要 Servlet 容器(如Tomcat)的支持

  • Servlet 由 Servlet 容器进行管理,Servlet 容器将 Servlet 动态加载到服务器上,与 HTTP 协议相关的 Servlet 使用HTTP请求和HTTP响应与客户端进行交互

Servlet 的请求首先会被 HTTP 服务器接收,HTTP 服务器只负责静态 HTML 界面的解析,而 Servlet 的请求则转交给 Servlet 容器,Servlet 容器会根据请求路径以及 Servlet 之间的映射关系,调用相应的 Servlet,Servlet 将处理的结果返回给Servlet 容器,并通过 HTTP 服务器将响应传输给客户端

Servlet接口

Servlet 就是实现了 Servlet 接口的类,它 由 Web 服务器创建并调用,用于接收和响应用户的请求

方法声明 说明
void init(ServletConfig config) Servlet实例化后,Servlet容器调用该方法完成Servlet的初始化工作
ServletConfig getServletConfig() 获取Servlet对象的配置信息
String getServletInfo() 返回包含Servlet信息的字符串,如作者,版权等
void service(ServletRequest req,ServletResponse resp) 负责响应用户的请求,当容器接收到客户端访问Servlet对象的请求时就会调用此方法。容器会构造一个表示客户端请求信息的ServletRequest对象和一个用于响应客户端的ServletResponse对象作为参数传递给service()方法,在service()方法中可以通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置相应信息
void destroy() 负责释放Servlet对象占用的资源,当服务器关闭或者Servlet对象被移除时会销毁Servlet对象,此时会调用此方法

编写的 Servlet 类必须实现 Servlet 接口或者继承 Servlet 接口的实现类,如GenericServletHttpServlet,这两个类都是抽象类并且HttpServlet继承了GenericServlet,其中GenericServlet有一个抽象方法service(),而HttpServlet没有抽象方法

编写 Servlet 类的三种方式

  1. 实现 Servlet 接口,需要重写Servlet接口里边的所有方法
  2. 继承 GenericServlet 抽象类,必须重写 service() 方法,其他方法也可以重写
  3. 通常情况下使用继承 HttpServlet 抽象类的方式编写 Servlet
1
2
3
4
5
6
7
8
9
10
11
public class ServletDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("方法执行了");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}

Servlet 线程安全问题

在实现Servlet的类中如果存在自定义的成员变量,并且在service()方法中操作这个变量时可能会出现线程安全问题

解决的办法是将成员变量改为定义在方法内部的局部变量,或者使用sychronized锁

HttpServlet 常用方法

方法 说明
protected void doGet(HttpServletRequest req,HttpServletResponse resp) 用户处理GET类型的HTTP请求
protected void doPost(HttpServletRequest req,HttpServletResponse resp) 用于处理POST类型的HTTP请求
protected void doPut(HttpServletRequest req,HttpServletResponse resp) 用于处理PUT类型的HTTP请求

Servlet 生命周期

初始化阶段

  • 当客户端向 Servlet 容器发出 HTTP 请求访问 Servlet 时,Servlet 容器首先解析请求,检查内存中是否已经有了该 Servlet 对象
  • 如果有,直接使用该 Servlet 对象;如果没有,就创建 Servlet 实例对象,然后通过调用 init() 方法完成 Servlet 初始化
  • 需要注意,在 Servlet 整个生命周期内,它的 init() 方法只被调用一次

运行阶段

  • Servlet 容器会为客户端请求创建代表HTTP请求的 ServletRequest 对象和代表 HTTP 响应的 ServletResponse 对象,然后将它们作为参数传递给 Servlet 的 service() 方法。

  • service() 方法从 ServletRequest 对象中获取客户端请求并处理该请求,通过 ServletResponse 对象生成响应结果。

  • 在 Servlet 整个生命周期内,对于 Servlet 的每一次访问请求,Servlet 容器都会调用一次 Servlet 的 service() 方法,并且创建新的 ServletRequest 和 ServletResponse 对象。
  • 即 service() 方法在Servlet整个生命周期中会被调用多次

销毁阶段

  • 当服务器关闭或者 Web 应用被移除出容器时,Servlet 随着 Web 应用的销毁而销毁。
  • 在销毁 Servlet 之前,Servlet容器会调用 Servlet 的 destroy() 方法,以便让 Servlet 对象释放它所占用的资源。

  • 在 Servlet 的 整个生命周期中,destroy()方法也只被调用一次。

  • 注意,Servlet 对象一旦创建就会驻留在内存中等待客户端的访问,直到服务器关闭或 Web 应用被移除出容器时 Servlet 对象才会销毁

Servlet 配置

使用 web.xml 配置 Servlet

在web.xml文件中,通过<servlet></servlet>标签进行注册,<servlet> 标签下包含若干个子元素,功能如下

元素 类型 描述
<servlet-name></servlet-name> String 指定Servlet名称,一般与Servlet类同名,要求唯一
<servlet-class></servlet-class> String 指定Servlet位置,一般是全类名
<description></description> String 指定Servlet的描述信息
<display-name></display-name> String 指定Servlet的显示名
1
2
3
4
5
6
7
8
9
10
11
12
<servlet>
<!--指出Servlet名称-->
<servlet-name>ServletDemo01</servlet-name>
<!--指出Servlet全类名-->
<servlet-class>com.demo.ServletDemo01</servlet-class>
</servlet>
<servlet-mapping>
<!--和servlet标签下的名称一致-->
<servlet-name>ServletDemo01</servlet-name>
<!--映射地址,必须加斜杠-->
<url-pattern>/ServletDemo01</url-pattern>
</servlet-mapping>
  • 把Servlet映射到URL地址,使用 <servlet-mapping></servlet-mapping> 进行映射,在 <servlet-mapping> 元素下使用 <servlet-name></servlet-name> 指出Servlet的名称,需要和之前在 <servlet> 标签下注册的相同
  • 使用<url-pattern></url-pattern>映射URL地址,地址前必须添加 /

使用注解配置 Servlet

  • @WebServlet 注解用于代替 web.xml 文件中的 <servlet><servlet-mapping> 等标签

  • 该注解会在项目部署时被容器处理,容器会根据具体的属性配置将相应的类部署为 Servlet

@WebServlet 注解常用属性如下:

属性声明 功能
String name 指定Servlet的name属性,等价于,如果没有显式指定则取值为类的全限定名
String[] value 等价于
String[] urlPatterns 和value功能一样,value和urlPatterns不能同时使用
int loadOnStartup 指定Servlet的加载时机,等价于
WebInitParam[] initParams 指定一组Servlet初始化参数,等价于,其中WebInitParam也是一种注解
1
2
3
4
5
6
7
8
9
10
11
12
@WebServlet(name = "ServletDemo01",urlPatterns = "/ServletDemo01",initParams = {@WebInitParam(name = "encoding",value = "UTF-8"),@WebInitParam(name = "desc",value = "this is ServletDemo01")})
public class ServletDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ServletDemo01运行了");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}

Servlet 创建时机

第一次访问时创建

优势:减少服务器内存的浪费

弊端:如果有一些需要在应用加载时就做的初始化操作,无法完成

服务器加载时创建

优势:提前创建好对象,提高首次执行时的效率,可以完成一些应用加载时要做的初始化工作

弊端:对服务器内存占用较多,影响服务器启动效率

修改 Servlet 创建时机

在 web.xml 文件的 <servlet> 标签中添加 <load-on-startup></load-on-startup> 标签,标签中间填写的是整数

  • 正整数表示在服务器加载时创建,值越小优先级越高
  • 负整数或者不填表示第一次访问时创建

默认 Servlet

  • 默认 Servlet 是服务器提供的一个 Servlet,它配置在 Tomcat 的 conf 目录中的 web.xml 文件中
  • 它的映射路径是 <url-pattern>/</url-pattern>,在接收请求时,首先会在项目中的 web.xml 文件查找映射配置,找到则执行,找不到时再去找默认的 Servlet,由默认 Servlet 处理

ServletConfig

概述

  • ServletConfig 是一个接口

  • 当 Tomcat 初始化一个 Servlet 时,会将该Servlet的配置信息封装到一个ServletConfig对象 中,通过调用 init(ServletConfig config) 方法将 ServletConfig 对象传递给 Servlet,ServletConfig 的生命周期与 Servlet 一样

  • ServletConfig 封装的配置信息是键值对的形式

常用方法

方法 说明
String getInitParameter(String name) 根据参数名返回对应的参数值
Enumeration getInitParameterNames() 返回一个Enumeration对象,其中包含了所有的参数名
ServletContext getServletContext() 返回代表当前web应用的ServletContext对象
String getServletName() 返回Servlet的名称

ServletConfig 配置

  • 配置 ServletConfig 也是在 web.xml 文件中的 <servlet></servlet> 标签下进行的
  • 需要使用 <init-param></init-param> 标签将参数名和参数值包住,表示一个键值对,其中使用 <param-name></para-name> 表示参数名,<param-value></param-value> 表示参数值
  • 一个 <init-param></init-param> 只能表示一个键值对
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<servlet>
<servlet-name>ServletConfigDemo</servlet-name>
<servlet-class>com.liaoxiangqian.ServletConfigDemo</servlet-class>
<!--配置encoding参数,使用一个init-param标签-->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!--配置desc参数,使用一个init-param标签-->
<init-param>
<param-name>desc</param-name>
<param-value>this is ServletConfigDemo</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ServletConfigDemo</servlet-name>
<url-pattern>/ServletConfigDemo</url-pattern>
</servlet-mapping>

ServletContext

概述

  • Servlet 容器启动时会为每个 Web 应用 创建一个唯一的 ServletContext 对象代表当前 Web 应用,ServletContext 对象 封装了当前Web应用的所有信息
  • ServletContext 可以配置和获得应用的全局初始化参数,可以实现多个 Servlet 之间的数据共享
  • 生命周期:应用加载则创建,应用停止则销毁

ServletContext配置

  • 在 web.xml 文件的 <web-app> 标签中,通过 <context-param> 标签来配置,其中他有两个子标签

  • 子标签 <param-name> 表示全局初始化参数的key

  • 子标签 <param-value> 表示全局初始化参数的value

1
2
3
4
5
6
7
8
<context-param>
<param-name>globalEncoding</param-name>
<param-value>UTF-8</param-value>
</context-param>
<context-param>
<param-name>globaleDesc</param-name>
<param-value>This is SevletContext</param-value>
</context-param>

ServletContext 作用

1.获取 Web 应用程序的初始化参数

  • Enumeration getInitParameterName() 方法用于返回包含所有参数名的 Enumeration 对象
  • String getInitParameter(String name) 方法用于根据参数名获取参数值

2.实现多个 Servlet 之间的数据共享

方法名 说明
Enumeration getAttributeNames() 返回包含所有域属性名的Enumeration对象
Object getAttribute(String name) 根据域属性名返回域属性值
void removeAttribute(String name) 根据域属性名从ServletContext中删除对应的域属性
void setAttribute(String name,Object obj) 设置ServletContext的域属性,其中name是域属性名,obj是域属性值

注意:域属性指的就是可以共享的数据,即可以被多个 Servlet 访问到

3.读取 Web 应用下的资源文件

实际开发中有时会需要读取Web应用中的一些资源文件,为此 ServletContext 接口定义了一些读取 Web 资源的方法,这些方法由依靠 Servlet 容器实现,可以根据资源文件相对 Web 应用的路径,返回关联资源文件的 IO 流、资源文件的绝对路径等

方法名 说明
Set getResourcePaths(String path) 返回一个Set集合,集合包含path指定路径下的子目录名称文件名称但是不包含子目录下的文件名称,path以斜杠/开头表示Web应用的根目录
String getRealPath(String path) 返回资源文件在服务器文件系统上的真实路径,参数path表示资源文件相对Web应用的路径,以斜杠/开头表示Web应用的根目录,如果不能将虚拟路径转为真实路径则返回null
URL getResource(String path) 返回映射到某个资源文件的URL对象,参数必须以斜杠/开头表示Web应用的根目录
InputStream getResourceAsStream(String path) 返回映射到某个资源文件的InputStream输入流对象,参数path的传递规则与getResource()一致

总结:这四个方法中的path其实就是相对于Web应用的路径,以斜杠 / 开头

HttpServletRequest

概述

  • HttpServletRequest 接口继承自 ServletRequest 接口
  • HttpServletRequest 专门用于封装 HTTP 请求消息
  • HttpServletRequest 提供了一些用于访问请求消息的方法,如获取请求行、获取请求头等

相关方法

获取请求行信息

方法 说明
String getMethod() 用于获取HTTP请求消息中的请求方式,如GETPost
String getRequestURI() 用于获取请求行中资源名称部分,即URL中主机名端口号之后和参数部分之前的部分
String getQueryString() 用于获取请求行中的参数部分,即资源路径?号后边的全部内容
String getProtocol() 用于获取请求行中的协议名和版本,如HTTP/1.0HTTP/1.1
String getContextPath() 用于获取URL中Web应用程序的路径,以/开头,结尾没有斜杠
String getServletPath() 用于获取Servlet映射的路径或者Servlet的名称
String getRemoteAddr() 用于获取发送请求的客户端的IP地址
String getRemoteHost() 用于获取发送请求的客户端的完整主机名,如果解析不到则返回IP地址
int getRemotePort() 用于获取发送请求的客户端的端口号
String getLocalAddr() 用于获取Web服务器上接收当前请求的网络的IP地址
String getLocalName() 用于获取Web服务器上接收当前请求的网络的IP地址对应的主机名
int getLocalPort() 用于获取web服务器上接收当前网络连接的端口号
String getServerName() 用于获取当前请求所指向的主机名,即HTTP请求消息中Host字段所对应的主机名部分
String getServerPort() 用于获取当前请求所连接的服务器端口号,即HTTP请求消息中Host字段所对应的端口号部分
String getSchema() 用于获取请求的协议名,如HTTP或HTTPS
StringBuffer getRequestURL() 用于获取客户端发出请求时的完整URL,包括协议、服务器名、端口号、资源路径等,但不包括后面的查询参数部分,StringBuffer类型方便修改

获取请求头信息

方法 说明
String getHeader(String name) 获取请求头中指定名称字段的值,如果没有该字段则返回null,如果有多个该指定名称的字段,则返回第一个字段的值
Enumeration getHeaders(String name) 返回一个Enumeration对象,该对象包含所有请求头中指定名称字段的值
Enumeration getHeaderName() 返回一个包含所有请求头字段的Enumeration对象
int getIntHeader(String name) 获取一个指定请求头字段的值,并将该字段的值转为int类型再返回,如果该字段不存在则返回-1,如果该字段的值不能转为int类型则抛出NumberFormatException异常
long getDateHeaders(String name) 获取一个指定请求头字段的值,并将其转为一个代表日期/时间的长整数,这个长整数是1970年1月1日0时0分0秒算起到现在的毫秒值
String getContentType() 获取Content-Type字段的值
int getContentLength() 获取Content-Length字段的值
String getCharacterEncoding() 获取请求消息的实体部分的字符集编码,通常从Content-Type字段中截取

获取相关请求参数

方法 说明
String getParameter(String name) 该方法获取指定名称参数的参数值,如果没有该参数则返回null,如果该参数没有设置值则返回空串,如果该参数有多个值则返回第一个
String getParameterValues(String name) 用于获取同一个参数名称的所有值
Enumeration getParameterNames() 用于返回包含所有参数名的Enumeration对象
Map getParameterMap() 将参数名和参数值装入一个Map对象中返回

HttpServletRequest 共享数据

HttpServletRequest 不仅可以获取一些列数据,还能通过属性共享、传递一些数据,比如运用在 请求转发请求包含

相关方法

方法 说明
void setAttribute(String name,Object obj) 用于定义一个属性,其中name是属性的名称,obj是属性值,如果原先已经存在相同名称的属性,则会将原来的属性删除再添加该属性,如果obj为null则会删除删除指定名称的属性
Object getAttribute(String name) 根据属性名获取属性值
void removeAttribute(String name) 删除指定名称的属性
Enumeration getAttributeNames() 返回一个包含所有属性名的Enumeration对象

需要注意同一个请求中的数据才能共享、传递

请求转发和请求包含

请求转发

Servlet 之间可以相互跳转,如果某个 Servlet 的功能 不能处理客户端的请求则可以使用跳转的方式将请求传递给另一个Servlet ,由另一个 Servlet 完成并响应给客户端

方法 说明
RequestDispatcher getRequestDispatcher(String path) 用于获取一个封装了某条路径所指定资源的RequestDispatcher对象,路径必须以斜杠 / 开头,即该路径就是需要转发到的某个Servlet的路径
void forward(ServletRequest req,ServletResponse resp) 由RequestDispatcher提供,用于将请求转发给另一个Web资源,如某个Servlet

请求包含

某个 Servlet 不能完全处理一个请求时可以将另一个 Servlet “包含”进来,实现功能合并然后响应给客户端,这时浏览器的地址栏不会发送改变,被包含的 Servlet 的响应头会丢失,因为是由第一个 Servlet 做出响应的

方法 说明
RequestDispatcher getRequestDispatcher(String path) 用于获取一个封装了某条路径所指定资源的RequestDispatcher对象,路径必须以斜杠/开头,即该路径就是需要转发到的某个Servlet的路径
void include(ServletRequest req,ServletResponse resp) 用于实现包含另一个Servlet的功能

流对象获取数据

方法 说明
BufferedReader getReader() 获取一个字符输入缓冲流
ServletInputStream getInputStream() 获取一个字节输入流

注意 这两个方法读取的数据来自 请求体,所以使用 GET 方式获取不到数据,而 POST 方法可以

中文乱码问题

在网页的表单中如果需要提交的数据存在中文时可能会出现乱码的情况

方法 说明
void setCharacterEncoding(String name) 用于设置Request对象的解码方式

GET 方式提交的请求不会出现乱码的问题,但是 POST 方式存在乱码问题

HttpServletResponse

概述

  • HttpServletResponse 接口继承自 ServletResponse 接口
  • 用于封装 HTTP 响应消息
  • HTTP 响应消息分为响应行,响应头,响应体三部分,所以 HttpServletResponse 中定义了向客户端发送 响应状态码、响应消息头、响应消息体 等方法

常见状态码

状态码 说明
200 成功
302 重定向
304 请求资源未改变,使用缓存
400 请求错误,常见于请求参数错误
404 请求资源未找到
405 请求方式不支持
500 服务器错误

发送状态码的方法

方法 说明
void setStatus(int status) 设置响应消息的状态码,并生成响应状态行
void sendError(int sc) 发送表示错误信息的状态码
void sendError(int sc,String message) 设置表示错误的状态码外还向客户端发送一条错误信息,其中包含message的内容

发送响应消息头的方法

方法 说明
void addHeader(String name,String value) 设置响应头指定名称字段的值,会覆盖掉原来该名称字段的值
void setHeader(String name,String value) 与addHeader()方法功能相同,但是不会覆盖原来的值而是添加一个值
void setContentLength(int len) 设置响应头的实体内容的大小,单位是字节
void setContentType(String type) 设置响应内容的类型,即Content-Type的值,并且响应内容为文本类型时还能指定字符集编码,如text/html;charset=UTF-8

发送响应消息体的方法

方法 说明
ServletOutputStream getOutputStream() 用于获取字节输出流对象
PrintWriter getWriter() 用于获取输出流对象
resp.setContentType(“text/html;UTF-8”) 注意:在使用这些输出流时可能会出现乱码的情况,所以在使用输出流时可以使用;来设置字符集编码,用来解决乱码问题

请求重定向

请求重定向是指服务器接收到客户端请求后,可能由于某些条件限制,不能访问请求指定的资源,让客户端去访问另一个指定的资源

方法 说明
void sendRedirect(String location) 用于生成304响应状态码和Location响应头,从而通知客户端重新访问Location响应头中指定的URL
  • location 可以使用相对路径重定向到同一个 Web 服务器的其他 Servlet,也可以绝对路径重定向到其他 Web 服务器
  • 注意:重定向时会重新生成另一个 HttpServletRequest 对象,所以不能实现 Servlet 的共享数据,如果需要共享数据那么可以使用请求转发

设置缓存时间

对于不经常变化的数据,可以设置缓存时间减少频繁访问服务器,提高效率

方法 说明
void setDateHeader(String name,long time) 置响应头
1
2
// 设置缓存时间为1个小时
resp.setDateHeader("Expires",System.currentTimeMills+1*60*60*1000)

设置定时刷新

定时刷新是指设置经过某个时间后自动跳转到某个页面

方法 说明
void setHeader(String name,String value)
1
resp.setHeader("Refresh","3;URL=/虚拟目录/demo.html")

文件下载

实现文件下载功能步骤

  1. 创建字节输入流,关联读取的文件
  2. 设置响应消息头支持的类型
  3. 设置响应消息头以下载方式打开资源
  4. 通过响应对象获得字节输出流对象
  5. 循环读写
  6. 释放资源

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@WebServlet("/ServletDownloadDemo")
public class ServletDownloadDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.创建字节输入流,关联读取的文件
String realPath = getServletContext().getRealPath("/img/ServletLive.png");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(realPath));
// 2. 设置响应消息头支持的类型
// Content-Type是消息头名称,表示支持的类型
// application/octet-stream是消息头参数,表示字节流
resp.setHeader("Content-Type","application/octet-stream");
// 3. 设置响应消息头以下载方式打开资源
// Content-Disposition是消息头名称,表示处理形式
// attachment;filename=ServletLive.png是消息头参数,表示附件形式处理,filename表示文件名称
resp.setHeader("Content-Disposition","attachment;filename=ServletLive.png");
// 4. 通过响应对象获得字节输出流对象
ServletOutputStream outputStream = resp.getOutputStream();
// 5. 循环读写
byte[] bytes = new byte[1024];
int len;
while((len = bis.read(bytes)) != -1){
outputStream.write(bytes,0,len);
}
// 6. 释放资源
bis.close();
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}

会话技术

概述

  • 会话 是指客户端和服务器之间的 多次请求和响应
  • 为了实现一些功能,浏览器和服务器可能会产生多次的请求和响应,从浏览器访问服务器开始,到访问服务器结束,这期间产生的多次请求和响应加在一起就称为浏览器和服务器之间的一次会话
  • 为了保存会话过程中产生的数据,我们可以通过会话技术(Cookie和Session)来实现
  • Cookie 是一种会话技术,可以将会话过程中的数据保存在用户的 浏览器 中,从而使浏览器和服务器之间更好的进行数据交互
  • 浏览器最多接收 20 个来自同一个网站的 Cookie,并且浏览器只允许存放 300个Cookie,每个 Cookie 的大小限制在4k以内

获取方式

方法 说明
void addCookie(Cookie cookie) 可以将Cookie添加到响应头中然后响应给浏览器
Cookie[] getCookie() 获取到一个Cookie数组,这些Cookie可能有相同的名称但是路径不同
public Cookie(String name,String value) name属性一旦创建将不能更改,但是value可以更改

常用属性

属性 作用 是否重要
name Cookie名称 必须属性
value Cookie的值(不支持中文) 必须属性
path Cookie的路径 重要
domain Cookie的域 重要
maxAge Cookie存活时间 重要
version Cookie版本号 不重要
comment Cookie描述 不重要

常用方法

Cookie 常用方法是对 Cookie 相关属性的 get 或者 set,但是 需要注意 name 属性没有 set 方法

setMaxAge(int expirt)getMaxAge() 方法解析

  1. 这两个方法用于设置和返回 Cookie 在浏览器上保持的有效秒数,其中设置的值有如下规则
  2. 正整数表示在没有超过指定秒数之前这个 Cookie 会一直存在
  3. 负整数表示当浏览器关闭时 Cookie 信息会被清除
  4. 0表示浏览器会立即删除这个 Cookie 信息
  5. 默认是 -1

setPath(String uri)getPath() 方法解析

  1. 这两个方法是针对 path 属性的设置和获取
  2. 如果创建的 Cookie 对象没有设置 path 属性的值,那么默认该 Cookie 只对 当前请求路径所属的目录以及子目录 有效
  3. 如果想让某个 Cookie 对象对站点的所有目录下的访问路径的都有效,那么可以设置为 "/"
  4. 设置 path 的格式是 contextPath+自定义路径

setDomain(String pattern)getDomain()

  1. 这两个方法是针对 domain 属性的设置和获取,domain 属性用于指定 Cookie 所在的域
  2. 默认为服务器主机地址,当浏览器想要访问该服务器的资源时会将该 Cookie 信息发送给服务器
  3. 如果想让不同的域之间都可以访问到某个 Cookie,那么 Cookie 的 domain 应该是这些域的相同后缀,而且必须以 . 开头

Session

  • Session 也是会话技术的一种,与 Cookie 不同的是,在客户端保存的是一个标识,而 会话产生的数据保存在服务器端

  • 当浏览器第一次请求服务器时,服务器会创建一个 Session 对象,该对象有唯一的一个标识,然后服务器将这个标识以 Cookie 的方式发送给浏览器

  • 当浏览器再一次请求服务器时会将这个标识发送过来,服务器根据这个标识就可以找到对应的 Session 对象了

  • Session 也是域对象之一,可以实现数据共享

  • 通过创建一个 HttpSession 对象来实现 Session,HttpSession 是一个接口,我们不直接创建这个对象而是服务器负责创建,我们使用的时候获取即可

获取方式

方法 说明
HttpSession getSession() 获取HttpSession对象
HttpSession getSession(boolean create) 获取HttpSession对象,未获取到是否创建

HttpSession常用方法

方法 说明
String getID() 返回与当前HttpSession对象关联的会话标识号
long getCreationTime() 返回Session创建时间
long getLastAccessedTime() 返回客户端最后一次发送与Session相关请求的时间
void setMaxInactiveInterval(int interval) 用于设置当前Session对象可空闲的最长时间,单位为秒
boolean isNew() 判断当前HttpSession对象是否是新建的
void invalidate() 强制使Session对象无效
ServletContext getServletContext() 返回当前HttpSession对象所属的ServletContext对象
void setAttribute(String name,Object value) 存储一个指定名称的数据对象,可以用于共享
String getAttribute() 用于从当前HttpSession对象中返回指定名称的属性值
void removeAttribute(String name) 用于从当前HttpSession对象中删除指定名称的属性值

Session生命周期

Session 生效

  1. Session 在用户第一次访问服务器时创建
  2. 只有访问 JSP、Servlet 等程序时才会创建 Session
  3. 只访问 HTML、IMAGE 等静态资源时 不会 创建 Session

Session 失效

  1. Web 服务器使用“超时限制”判断客户端是否还在继续访问
    • 在一定时间内,如果某个客户端没有请求访问,那么 Web 服务器认为该客户端已经结束请求,并且与该客户端会话所对应的HttpSession 对象会变成垃圾对象,等待垃圾收集器将其从内存中清除。
    • 如果超时后再次向服务器发出请求访问,那么 Web 服务器会创建一个新的 HttpSession 对象,并分配一个新的标识
  2. 使用 invalidate() 方法,可以强制使得 Session 失效
方法 说明
setInactiveInterval(int interval) 可以设置Session最长的空闲时间,当超过这个时间客户端没有请求访问则Session失效

Filter

概述

  • Filter 称为过滤器,位于客户端与处理程序之间,能够对请求和响应进行检查和修改
  • 当客户端对服务器资源发送请求时,服务器根据过滤规则进行检查,如果满足过滤规则,则对客户请求进行拦截,然后对请求头或请求数据进行修改或检查,并依次通过 Filter 链,最后将请求交给处理程序
  • 请求信息可以在过滤器中被修改,也可以根据请求条件不让请求发往处理程序

Filter 接口

编写一个 Filter 必须实现 Filter 接口

相关方法

方法名 说明
default void init(FilterConfig filterConfig) 创建Filter后用于初始化Filter,通过参数FilterConfig对象获取配置参数
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) 用于完成过滤的操作,其中Request对象和Response对象是由上一个过滤器或者Web服务器传递过来的请求和响应对象,FilterChain对象代表当前过滤链对象
default void destroy() 用于释放过滤器中占用的资源,在对象被销毁之前调用

Filter 接口提供了三个方法,其中 init() 方法和 destroy() 方法是默认方法不强制重写,而 doFilter() 方法是抽象方法,在实现 Filter 接口时必须重写

Filter 配置

web.xml 配置方式

1
2
3
4
5
6
7
8
9
<!--在web.xml文件的web-app标签下写入以下内容-->
<filter>
<filter-name>FilterDemo</filter-name>
<filter-class>com.cyan.filter.FilterDemo</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterDemo</filter-name>
<url-pattern>/ServletDemo</url-pattern>
</filter-mapping>

@WebFilter 注解配置方式

1
2
3
4
5
6
7
@WebFilter("/ServletDemo")
public class FilterDemo implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterDemo执行了");
}
}

@WebFilter 常用属性

属性名 类型 说明
filterName String 指定过滤器名称
urlPattren String[] 指定需要过滤的资源,如某个Servlet或Jsp
value String[] 等价于urlPattern,不能同时使用
servletNames String[] 指定过滤器将应用于哪些Servlet,取值是@WebServlet中name属性的取值
dispatcherTypes DispatcherType 指定过滤器转发模式,取值有ERROR、FORWARD、INCLUDE、REQUEST
initParams WebInitParam[] 指定过滤器的一组初始化参数

DispatcherType 是枚举类

类型 说明
DispatcherType.ERROR 表示过滤器拦截那些跳转到某个异常处理页面的请求
DispatcherType.FORWARD 表示过滤器拦截那些通过forward()方法来请求的转发的请求
DispatcherType.INCLUDE 表示过滤器拦截那些通过include()方法来请求包含的请求
DispatcherType.REQUEST 表示过滤器只会拦截普通的请求,而请求转发和请求包含类的请求不会拦截

如果需要拦截用户的所有请求,则可以使用 * 号通配符,如

1
<url-pattern>/*</url-pattern>
1
@WebFilter("/*")

FilterConfig 接口

FilterConfig 接口用于封装 Filter 的配置信息,在 Filter 初始化时,服务器将 FilterConfig 对象作为参数传递给 Filter 对象的 init() 方法

相关方法

方法名 说明
String getFilterName() 获取Filter的名称
ServletContent getServletContext() 获取ServletContext对象
String getInitParameter(String name) 根据名称获取初始化参数值
Enumeration getInitParameterNames() 返回一个包含所有初始化参数名的Enumeration对象

配置初始化参数的方式

在 web.xml 中配置,注意是在 <filter> 标签下方进行配置

1
2
3
4
<init-param>
<param-name>username</param-name>
<param-value>cyan</param-value>
</init-param>

@WebFilter 中使用 initParams 属性配置,注意 initParam 属性类型是注解型数组

1
@WebFilter(initParams = {@WebInitParam(name="username",value="cyan")})

添加初始化的参数后可以通过 FilterConfig 来获取这些参数

FilterChain 接口

FilterChain 对象表示当前过滤器所在的过滤链,一个 Web 应用程序中存在多个 Filter,每个 Filter 都可以对某个请求进行拦截,如果多个 Filter 都对同一个请求进行拦截,那么这些 Filter 就组成一个 Filter 链,使用 FilterChain 对象表示

方法 说明
void doFilter(ServletRequest var1, ServletResponse var2) FilterChain提供的doFilter()方法,作用是让Filter链上的当前过滤器放行,使请求进入下一个Filter

Filter 生命周期

  • Filter 生命周期可以分为 创建、执行、销毁 三个阶段
  • 创建阶段:Web服务器启动的时候会创建Filter对象,并调用 init() 方法,完成对象的初始化,在一次完整请求中 Filter 对象只会被创建一次, init() 方法只会被调用一次
  • 执行阶段:客户端发出请求时,服务器筛选出符合拦截条件的过滤器,按照类名的顺序依次执行 doFilter() 方法,doFilter()在一次完整请求中会执行多次
  • 销毁阶段:服务器关闭时,Web 服务器调用 destroy() 方法销毁对象

Listener

概述

  • Web 程序开发中,可以对对象的创建和销毁、域对象中属性的变化、会话相关内容进行监听
  • Servlet 中提供八个监听器,都是以接口的形式提供,具体功能需要自行完善

相关概念

  1. 事件:触发的动作
  2. 事件源:产生事件的对象
  3. 事件监听器:监听发生在事件源上的事件
  4. 事件处理器:监听器的成员方法,事件发生时会触发该方法

监听对象的创建和销毁的监听器

ServletContextListener 接口

用于监听 ServletContext 对象的创建与销毁

方法 说明
void contextInitialized(ServletContextEvent sce) ServletContext对象创建时执行
void contextDestroyed(ServletContextEvent sce) ServletContext对象销毁时执行

HttpSessionListener 接口

用于监听 HttpSession 对象的创建与销毁

方法 说明
void sessionCreated(HttpSessionEvent se) HttpSession对象创建时执行
void sessionDestroy(HttpSessionEvent se) HttpSession对象销毁时执行

ServletRequestListener 接口

用于监听 ServletRequest 对象的创建与销毁

方法 说明
void requestInitialized(ServletRequestEvent sre) ServletRequest对象创建时执行
void requestDestroyed(ServletRequestEvent sre) ServletRequest对象销毁时执行

监听域对象属性变化的监听器

ServletContextAttributeListener 接口

用于监听 ServletContext 中属性的变化

方法 说明
void attributeAdded(ServletContextAttributeEvent scae) 域中添加属性时执行
void attributeRemoved(ServletContextAttributeEvent scae) 域中移除属性时执行
void attributeReplaced(ServletContextAttributeEvent scae) 域中替换属性时执行

HttpSessionAttributeListener 接口

用于监听 HttpSession 中属性的变化

方法 说明
void attributeAdded(HttpSessionBindingEvent se) 域中添加属性时执行
void attributeRemoved(HttpSessionBindingEvent se) 域中移除属性时执行
void attributeReplaced(HttpSessionBindingEvent se) 域中替换属性时执行

ServletRequestAttributeListener 接口

用于监听 ServletRequest 中属性的变化

方法 说明
void attributeAdded(ServletRequestAttributeEvent srae) 域中添加属性时执行
void attributeRemoved(ServletRequestAttributeEvent srae) 域中移除属性时执行
void attributeReplaced(ServletRequestAttributeEvent srae) 域中替换属性时执行

监听会话相关的感知型监听器

HttpSessionBindingListener 接口

用于监听 JavaBean 对象绑定到 HttpSession 对像和从 HttpSession 对象解绑的事件

方法 说明
void valueBound(HttpSessionBindingEvent event) 数据绑定(添加)到会话域时执行
void valueUnbound(HttpSessionBindingEvent event) 数据从会话域解绑(移除)时执行

HttpSessionActivationListener 接口

用于监听 HttpSession 中对象活化(恢复到内存)和钝化(持久化到硬盘)的过程

方法 说明
void sessionWillPassivate(HttpSessionEvent se) 会话域中数据钝化时执行
void sessionDidActivate(HttpSessionEvent se) 会话域中数据活化时执行

监听器的实现

实现步骤

  1. 将监听器绑定到事件源,也就是注册监听器
  2. 监听器监听到事件发生时,将事件对象作为参数传给相关的成员方法
  3. 成员方法可以根据事件对象获取事件源,然后进行处理

通过web.xml注册监听器

1
2
3
4
<!--<listener-class>标签中写的是监听器的实现类的全限定名类名-->
<listener>
<listener-class>com.cyan.listener.MyListener</listener-class>
</listener>

通过注解注册监听器

1
2
//在监听器实现类上方使用该注解进行注册
@WebListener

JSP 技术

概述

JSP

  • JSP(Java Server Pages):是一种动态网页技术,是 Servlet 更高级别的扩展
  • JSP 文件中,HTML 代码与 Java 代码共同存在,HTML 用于实现静态内容的显示,Java 用于动态内容的显示
  • JSP 文件会被 Web 服务器编译成一个 Servlet,用于处理各种请求,然后将生成的网页响应给客户端

运行原理

过程

  1. 客户端发送请求,请求访问 JSP 文件
  2. JSP 容器将 JSP 文件转换成 Java 源文件(一个 Servlet 类),转换过程中发现语法错误会中断并向服务器和客户端返回出错信息,JSP 容器本身也是一个 Servlet
  3. 转换成功后,JSP 容器继续将这个 Java 源文件编译成相应的字节码文件(.class),该字节码文件就是一个 Servlet,Servlet 容器会像处理其他 Servlet 一样来处理它
  4. Servlet 容器根据这个字节码文件 创建出一个 Servlet 实例,并执行 jspInit() 方法完成初始化,这个 jspInit() 在 Servlet 的整个生命周期中只会执行一次,这个 Servlet 实例会常驻在内存中
  5. JSP 容器执行 jspService() 方法来处理客户端的请求,对于每个请求都会创建一个新的线程来处理它,多个客户端请求就会创建多个线程,每个线程对应每个客户端
  6. 如果 JSP 文件被修改,服务器根据设置会决定是否对该文件进行重新编译,如果重新编译则编译后的结果会取代内存中常驻的 Servlet 实例
  7. 由于系统资源不足等原因,JSP容器可能会以某种不确定的方式将 Servlet 实例从内存中移除,此时会调用 jspDestroy() 方法,然后 Servlet 实例被加入“垃圾收集”处理
  8. 请求处理完成后,响应的结果先由 JSP 容器接收,然后将 HTML 格式的信息发送回客户端

JSP 语法

JSP 脚本元素

  • JSP 脚本元素是指嵌套在<%%>中的一条或多条Java代码,通过JSP脚本元素来将Java代码嵌入HTML代码中,所有可以执行的Java代码都可以通过JSP脚本执行

  • JSP脚本元素分为3种类型,JSP Scriptlets、声明标识、JSP表达式

    JSP Scriptlets

    1. JSP Scriptlets是一段Java代码,可以定义变量、控制流程语句等

    2. 可以使用JSP内置对象在页面输出内容

    3. JSP Scriptlets中的代码位于JSP文件转换成的Servlet类中的jspService()方法,所以不能在里边定义方法,而在里边定义的变量都是局部变量

    4. 除了定义局部变量还可以处理请求和访问Session会话等

    5. 范例

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head>
      <title>第一个jsp页面</title>
      </head>
      <body>
      <h1>my first jsp page</h1>
      <%
      int a = 10;
      String s = "abc";
      %>
      </body>
      </html>

    声明标识

    1. 在JSP Scriptlets中可以定义属性也可以输出内容,但是不能定义方法,但是使用声明就能实现方法的定义和成员变量的定义

    2. 声明标识中的内容是位于JSP转换成的Servlet类中的成员位置,所以可以定义成员方法、成员变量

    3. 在声明标识中定义的方法和变量可以被整个JSP页面访问,所以通常使用该标识定义整个JSP页面需要引用的变量或方法

    4. 语法格式

      1
      2
      3
      <%!
      定义成员变量或方法
      %>
    5. 在声明标识中是用于定义变量和方法的,不能在此处用于输出内容

    JSP表达式

    1. JSP表达式用于向页面输出信息

    2. 语法格式

      1
      <%= expression %>

      expression可以是java语言中任意完成的表达式,最终运算结果会被转化成字符串

    3. 实例

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head>
      <title>jsp页面</title>
      </head>
      <body>
      <%!
      int a = 50;
      int b = 20;
      %>
      <%= a+b%>
      </body>
      </html>

JSP注释

  • JSP文件中如果需要注释Java代码,那么可以在Java代码处直接使用Java的注释语法

  • JSP文件中如果需要注释HTML代码,那么可以在HTML代码处使用HTML的注释语法

  • 使用HTML的注释后虽然在网页中看不到注释后的内容,但是通过查看源代码还是能看到注释信息的,这是因为Tomcat编译JSP文件时会将HTML注释当成普通文本发送给客户端

  • JSP提供了一种隐藏注释,使用这种注释的内容不会在网页源代码中显示,语法格式如下

    1
    <%-- 注释内容 --%>

JSP指令

为了设置JSP页面的一些信息,可以使用JSP指令,JSP中定义了page、include、taglib三种指令,每种指令都定义了各自的属性

page 指令

格式:

1
<%@ page 属性名1="属性值1" 属性名2="属性值2" %>

page 常用属性如下:

属性名 取值范围 描述
language java 指定jsp页面的脚本语言,默认为java
import 任何包名、类名 指定jsp转换成Servlet类时需要引入的包或者类
session true、false 指定jsp是否内置Session,如果true则内置Session对象,否则没有内置Session对象,默认为true
isErrorPage true、false 指定该页面是否为错误处理页面,如果是true则该jsp页面内置一个Exception对象exception,可以直接使用,默认取值为false
errorPage 某个jsp页面的相对路径 指定一个错误页面,如果该JSP页面抛出一个未捕获的异常,则转到这个属性指定的页面,指定的页面的isErrorPage取值为true并且内置的Exception对象就是这个未捕获的异常
contentType 有效的文档类型 指定当前jsp页面的MIME类型和字符编码,例如HTML格式为text/html、纯文本格式为text/plain、JPG图像为image/jpeg、GIF图像为image/gif、Word文档为application/msword
pageEncoding 当前页面 指定页面的编码格式

注意以上属性中,只有import属性可以出现多次,一个import也可以引入多个类,中间用英文逗号隔开,而其他属性只能出现一次

范例:

1
2
3
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page import="java.util.*" %>
<%@ page import="java.awt.*","java.util.*" %>

include 指令

格式:

1
<%@ include file="被包含的文件路径" %>

include 指令用于包含另一个jsp页面,只有一个file属性,用于指定被包含的页面,使用的是相对地址,不以 / 开头

注意在被包含的页面中需要将html、body等标签去掉,因为当前页面已经存在这些标签

taglib 指令

格式:

1
<%@ taglib prefix="tagPrefix" uri="tagURI" %>

taglib指令用于标识该页面所使用的标签库,同时引用标签库并指定标签的前缀,引入标签库后就可以通过前缀来引用标签库中的标签

属性说明:

  • prefix:用于指定标签前缀,不能命名为jsp、jspx、java、sun、servlet和sunw
  • uri:指定标签库文件的存放位置

引用 JSTL 中核心标签库的范例:

1
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

动作元素

包含文件元素

语法:

1
<jsp:include page="URL" flush="true|false" />

page:需要引入的页面相对路径

flush:是否将页面内容刷新到客户端,默认为false

原理:

  • 页面1使用该动作元素将页面2包含,当浏览器第一次请求页面1时,Web容器会先编译页面2,然后将编译结果包含在页面1中,之后再编译页面1,最终将两个页面组合的结果回应给浏览器
  • flush属性为flase时,服务器会等页面完全实现后才返回给浏览器显示,而true时当缓存累积到一定数据时会先将部分页面返回给浏览器显示并等待后续内容,即是否自动刷新页面

与include指令的区别:

  • include的file属性不支持jsp表达式,而<jsp:include>的page属性支持jsp表达式
  • include指令是将被包含的页面插入当前页面中再编译然后返回给浏览器,而<jsp:include>是将被包含的文件先编译返回给浏览器后再回到当前页面继续执行当前页面的内容
  • include指令包含页面是将两个页面合并在一起所以两个页面中的变量名和方法还有一些产生冲突的html标签不能产生冲突,而使用<jsp:include>时,因为每个文件是单独编译的,所以没有冲突问题

请求转发元素

语法:

1
<jsp:forward page="relativeURL" />

page:指定将请求转发到的页面的相对路径

原理:

  • <jsp:forward> 元素可以将当前请求转发到其他的Web资源,如HTML页面、JSP页面、Servlet等
  • 执行请求转发后当前页面将不再执行,但是地址栏中的资源路径不会改变

JSP 隐式对象

九大隐式对象

对象名 类型 说明
out javax.servlet.jsp.JspWriter 用于页面输出
request javax.servlet.http.HttpServletRequest 请求信息
response javax.servlet.http.HttpServletRequest 响应信息
config javax.servlet.ServletConfig 配置信息
session javax.servlet.http.HttpSession 会话信息
application javax.servlet.ServletContext 站点信息
page java.lang.Object 该页面转换成Servlet的实例
pageContext javax.servlet.jsp.PageContext JSP页面容器
exception java.lang.Throwable JSP中页面的异常,在错误页中起作用
  • JSP提供了上诉九个隐式(内置)对象,是JSP默认创建的,可以直接在JSP页面中使用
  • request、response、config、session、application对象的细节在前文已述

out对象

  • out对象是javax.servlet.jsp.JspWriter类的实例,用于向页面输出内容

  • out对象带有缓冲区,向页面中输出的内容会存入缓冲区中

  • 只有调用了ServletResponse的getWriter()方法才会将out对象缓冲区的内容写入Servlet引擎(容器)提供的缓冲区中

1
2
3
4
5
6
7
8
9
10
11
12
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp页面</title>
</head>
<body>
<%
out.println("first line <br/>");
response.getWriter().write("second line <br/>");
%>
</body>
</html>

pageContext对象

pageContext对象是javax.servlet.jsp.PageContext类的实例对象,代表当前jsp页面的运行环境

pageContext对象可以获取其他八个隐式对象:

方法 说明
JspWriter getOut() 获取out对象
Object getPage() 获取page对象
ServletRequest getRequest() 获取request对象
ServletResponse getResponse() 获取response对象
HttpSession getSession() 获取session对象
Exception getException() 获取exception对象
ServletConfig getServletConfig() 获取Config对象
ServletContext getServletContext() 获取application对象

pageContext对象可以设置和获取数据从而实现共享数据,但是需要指定范围:

方法 说明
void setAttribute(String name,Object value,int scope) 设置属性和对应的值,scope指定作用的范围
Object getAttribute(String name,int scope) 获取属性和对应的值,scope指定从哪个范围获取
void removeAttribute(String name,int scope) 从指定范围移除指定的属性
void removeAttribute(String name) 从所有范围移除指定的属性
Object findAttribute(String name) 从四个域中查找属性

scope有四个取值,分别是:

  • pageContext.PAGE_SCOPE,表示当前页面范围

  • pageContext.REQUEST_SCOPE,表示请求范围

  • pageContext.SESSION_SCOPE,表示会话范围

  • pageContext.APPLICATION_SCOPE,表示Web应用范围

findAttribute()方法从四个域中查找属性时顺序是page、request、session、application

pageContext实现了在当前页面中获取四大域对象进行数据共享的功能

四大域对象

域对象 范围
pageContext 最小,表示当前页面
ServletRequest 在请求转发时使用
HttpSession 多次请求时使用
ServletContext 最大,整个应用都能使用

EL表达式

概述

  • JSP开发中为了获取域对象中的数据,需要书写很多Java代码,造成了页面混乱
  • 使用EL表达式可以简化JSP开发中的对象引用,规范页面代码

EL表达式基本语法

格式:

1
${表达式}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>EL表达式</title>
</head>
<body>
<%
request.setAttribute("name","张三");
%>
<%--传统方式--%>
<%=request.getAttribute("name")%>
<%--使用EL表达式--%>
${name}
</body>
</html>

注意:使用EL表达式获取域对象中的数据时,如果对象中没有该数据则返回空字符串,而Java代码会返回null从而报空指针异常

EL访问数据

点运算符.

1
${student.name}

中括号运算符[]

1
${students[0]}
  • 点运算符和中括号运算符主要是用来访问对象、数组、集合中的数据

  • 某些属性名含有特殊符号时,只能用中括号运算符,如 ${student[“My-Name”]}

  • 点运算符和中括号运算符可以互换使用,也可以结合使用,如 ${users[0].userName}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    <%@ page contentType="text/html;charset=UTF-8" language="java"%>
    <html>
    <head>
    <title>EL表达式</title>
    </head>
    <body>
    <%--访问基本数据类型--%>
    <%request.setAttribute("age",18);%>
    ${age}

    <%--访问自定义类型数据--%>
    <%
    Student student = new Student("liaoxiangqian",21);
    request.setAttribute("student",student);
    %>
    ${student.name}<%--这里实际上是使用了student的getName()方法--%>

    <%--访问数组类型数据--%>
    <%
    int[] array = new int[]{1,2,3};
    request.setAttribute("array",array);
    %>
    ${array[0]}

    <%--访问List集合数据--%>
    <%
    ArrayList<String> list = new ArrayList<>();
    list.add("hello");
    list.add("JSP");
    request.setAttribute("list",list);
    %>
    ${list}
    ${list[1]}

    <%--访问Map集合数据--%>
    <%
    HashMap<String,String> map = new HashMap<>();
    map.put("map01","data01");
    map.put("map02","data02");
    request.setAttribute("map",map);
    %>
    ${map.map01}
    </body>
    </html>
  • 注意:

    • EL表达式没有空指针异常,没有索引越界异常,没有字符串拼接
    • 如果出现空指针和索引越界,只会返回空字符串
    • 用“+”进行字符串拼接,会抛出异常

EL运算符

算术运算符

运算符 说明 表达式
+ ${10+2}
- ${10-2}
* ${10*2}
/(或div) ${10/2}${10 div 2}
%(或mod) 取模 ${10%2}${10 mod 2}

比较运算符

运算符 说明 表达式
==(或 eq) 等于 ${10 == 2}${10 eq 2}
!=(或 ne) 不等于 ${10 != 2}${10 ne 2}
<(或 lt) 小于 ${10 < 2}${10 lt 2}
>(或 gt) 大于 ${10 > 2}${10 gt 2}
<=(或 le) 小于等于 ${10 <= 2}${10 le 2}
>=(或 ge) 大于等于 ${10 >= 2}${10 ge 2}

注意:上述比较运算符输出结果为true或false

逻辑运算符

运算符 说明 表达式
&&(或and) 逻辑与 ${true && false}${true and false}
\ \ (或or) 逻辑或 `${true \ \ false}${true or false}`
!(或not) 逻辑非 ${!true}${not true}

empty运算符

  • 格式

    1
    ${empty 变量/对象}
  • empty运算符用来判断一个对象或变量是否为空,这里的空是指空字符串、空指针null、空数组、空集合

  • 三元运算符

    1
    ${true == false ? "a" : "b"}
  • 注意:上述的运算符可以通过括号运算符()来改变运算优先级

EL隐式对象

EL提供11个内置对象,无需创建可以直接使用,11个隐私对象如下

对象名 说明
pageContext 与JSP中的pageContext对象功能相同
pageScope 保存page域中属性值的Map对象
requestScope 保存request域中属性值的Map对象
sessionScope 保存session域中属性值的Map对象
applicationScope 保存application域中属性值的Map对象
param 保存了所有请求参数的Map对象
paramValues 保存了所有请求参数的Map对象,一个参数对应一个String类型数组
header 保存了所有HTTP请求头字段的Map对象
headerValues 保持了所有HTTP请求头字段的Map对象,一个字段对应一个String类型数组
cookie 获取cookie的值,类型是Map
initParam 保存了所有Web应用初始化参数的Map对象

注意:不要和JSP中的隐式对象混淆,只有pageContext是相同的,其他的没有关系

pageContext对象: 可以使用pageContext对象来获取JSP页面中的其他8个隐私对象

1
2
3
${pageContext.request.getAttribute("username")}
<%--相当于--%>
<%=request.getAttribute("username")%>

域相关对象:

  • 域相关对象是指pageScope、requestScope、sessionScope、applicationScope这四个对象

  • 这四个对象与JSP隐式对象中的page、request、session、application相似

  • 这四个对象主要用于从它们对应的域中取出相关的属性值,而不采用默认的查找顺序去取值,如

    1
    2
    3
    <%--username是request域中的属性名--%>
    ${username}<%--这是默认的方式--%>
    ${requestScope.username}<%--这是用隐式对象的方式--%>
  • 如果不使用隐式对象而使用默认的方式会按照page、request、session、application的顺序查找

访问环境信息的隐式对象:

  • 访问环境信息的隐式对象有param、paramValues
  • 这两个对象用于获取表单信息中提交的成对参数,其中paramValues是用于获取一个参数对应的多个参数值

    访问HTTP请求头字段的对象:

  • 获取HTTP请求头字段的对象有header、headerValues

  • 这两个对象用于根据头字段的参数,获取参数对应的值,其中headerValues是用于获取一个头字段的多个值

    cookie对象:

  • cookie对象用于获取Cookie中的信息,然后存入一个Map集合中,其中键是Cookie的名称,值为Cookie对象

    1
    2
    3
    ${cookie.username}<%--返回的是一个Cookie对象,在页面中显示的是这个Cookie对象的地址--%>
    ${cookie.username.name}<%--返回的是Cookie对象的name属性的值--%>
    ${cookie.username.value}<%--返回的是Cookie对象的value属性的值--%>

initParam对象:

  • initParam对象用于获取Web应用初始化参数的值

    在web.xml文件中存在一个初始化参数:

    1
    2
    3
    4
    <context-param>
    <param-name>author</param-name>
    <param-value>cyan</param-value>
    </context-param>

    jsp文件中使用initParam对象获取author这个参数的值

    1
    ${initParam.author}<%--在页面中会输出cyan--%>

JSTL

概述

  • 使用JSTL可以取代传统JSP开发中嵌入Java代码的做法,提高程序可维护性
  • 需要使用taglib指令定义引用标签库和访问前缀
  • 包含5类标准标签库,分别是核心标签库、国际化/格式化标签库、SQL标签库、XML标签库、函数标签库
  • 使用JSTL需要下载相关Jar包然后导入项目

核心标签库

使用核心标签库的taglib指令如下

1
<%@ taglib prefix="c" url="http://java.sun.com/jsp/jstl/core" %>

<c:out>标签

1
2
3
4
5
6
<%--无标签体--%>
<c:out value="value" [default="defaultValue"] [escapeXml="{true|false}"] />
<%--有标签体--%>
<c:out value="value" [escapeXml="{true|faslse}"]>
defaultValue
</c:out>
  • <c:out>标签用于向页面输出信息
  • value指定输出的文本内容,也可以是EL表达式
  • default指定value为null时的输出内容,是可选的属性(方括号属性是可选的),
  • escapeXml属性用于指定特殊字符是否进行HTML编码后输出,默认为true

<c:remove>标签

1
<c:remove var="name" [scope="范围"]>
  • <c:remove>标签用于移除指定JSP范围内的变量
  • var指定要移除的变量名
  • scope指定范围,可选值有page、request、session、application,默认为page

<c:if>标签

1
2
3
4
5
6
<%--没有标签体--%>
<c:if test="testCondition" var="result" [scope="{page|request|session|application}"] />
<%--有标签体--%>
<c:if test="testCondition" var="result" [scope="{page|request|session|application}"]>
body content
</c:if>
  • <c:if>标签用于条件判断
  • test属性是需要判断的逻辑表达式
  • var用于指定逻辑表达式的变量名字
  • scope指定var的作用范围,默认为page

<c:choose>标签、<c:when>标签、<c:otherwise>标签

1
2
3
4
5
6
7
8
9
10
11
<c:choose>
<c:when test="testCondition">
body content
</c:when>
<c:when test="testCondition">
body content
</c:when>
<c:otherwise>
body content
</c:otherwise>
</c:choose>
  • 这三个标签类似多重if语句
  • 当when中的test属性返回值是true时对应的语句执行,只有所有的when都不匹配时才会执行otherwise中的内容

<c:forEach>循环标签

1
2
3
<c:forEach [var="varName"] items="collection" [varStatus="varStatusName"] [begin="begin"] [end="end"] [step="steo"] >
body content
</c:forEach>
  • <c:forEach>循环标签用于迭代集合的操作
  • var表示当前迭代到的元素保存到page中的名称
  • items指定迭代的集合
  • varStatus用于指定将当前迭代状态信息对象保存到page中的名称
  • begin,end用于指定迭代始末
  • step指定迭代步长