基本概念
- Servlet(Server applet)是 Java Servlet 的简称,称为小服务程序或服务连接器,是 Java 语言编写的服务器端程序,也就是说,Servlet 是运行在服务器上的 Java 类
- Servlet 用来完成 B/S 架构下客户端请求的响应处理,也就是交互式地浏览和生成数据,生成动态 Web 内容
编写步骤
- 建立一个 Java Web Application 项目并配置 Tomcat 服务器
- 自定义类实现 Servlet 接口或继承 HttpServlet类(推荐),并重写 service 方法
- 将自定义类的信息配置到 web.xml 文件并启动项目
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.yamin.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
Servlet
Servlet 接口
javax.servlet.Servlet接口用于定义所有 Servlet 必须实现的方法
| 方法 | 功能 |
|---|
| void init(ServletConfig config) | 有servlet容器调用,以向servlet指示servlet正在被放入服务中 |
| void service(ServletRequest req,ServletResponse res) | 有servlet容器调用,以允许servlet响应请求 |
| ServletConfig getServletConfig() | 返回ServletConfig对象,该对象包含此servlet的初始化和启动参数 |
| String getServletInfo() | 返回有关Servlet的信息,如作者、版权和版本 |
| void destory() | 有servlet容器调用,以向servlet指示该servlet正在退出服务 |
GenericServlet 类
javax.servlet.GenericServlet 类主要用于定义一个通用的,与协议无关的 servlet,该类实现了 Servlet 接口,若编写通用 Servlet ,只需要重写 service 抽象方法即可
| 方法 | 功能 |
|---|
| abstract void service(ServletRequest req,ServletResponse res) | 有servlet容器调用,以允许servlet响应请求 |
HttpServlet 类
javax.servlet.HttpServlet 类是一个抽象类并继承了 GenericServlet 类,用于创建使用与网站的 HTTP Servlet,该类的子类必须至少重写一个方法
| 方法 | 功能 |
|---|
| void doGet(HttpServletRequest req,HttpServletResponse res) | 处理客户端GET请求 |
| void doPost(HttpServletRequest req,HttpServletResponse res) | 处理客户端POST请求 |
| void init() | 进行初始化操作 |
| void service(HttpServletRequest req,HttpServletResponse res) | 根据请求决定调用doGet还是doPost方法 |
| void destory() | 删除实例时释放资源 |
ServletRequest接口
javax.servlet.ServletRequest 接口主要用于向 servlet 提供客户端请求信息,可以从中获取到任何请求信息,Servlet 容器创建一个ServletRequest 对象,并将其作为参数传递给 Servlet 的 service 方法
| 方法 | 功能 |
|---|
| String getParameter(String name) | 以字符串形式返回请求参数的值,如果该参数不存在,则返回空值 |
| String[] getParameterValues(String name) | 返回一个字符串对象数组,其中包含给定请求参数锁具有的所有值,如果该参数不存在,则返回空值 |
| Enumeration getParameterNames() | 返回包含此请求中包含的参数名称的字符串对象的枚举,如果请求没有参数,则方法放回空枚举 |
| Map<String,String[]> getParameterMap() | 返回请求参数的键值对,一个键可以对应多个值 |
| String getRemoteAddr() | 返回发送请求客户端或最后一个代理的IP地址 |
| int getRemotePort() | 返回发送请求客户端或最后一个代理的端口号 |
HttpServletRequest 接口
此接口是ServletRequest的子接口,主要用于提供HTTP请求信息的功能,不同于表单数据,在发送HTTP请求时,HTTP请求头直接由浏览器设置。
| 方法 | 功能 |
|---|
| String getRequestURI() | 返回此请求的资源路径信息 |
| StringBuffer getRequestURL() | 返回此请求的完整路径信息 |
| String getMethod() | 返回发出此请求的HTTP方法的类型,如:GET POST |
| String getQueryString() | 返回路径后面请求中附带的参数 |
| String getServletPath() | 返回此请求中调用servlet的路径部分 |
ServletResponse 接口
用于定义一个对象来帮助Servlet 向客户端发送响应
| 方法 | 功能 |
|---|
| PrintWriter getWriter() | 返回可想客户端发送字符文本的PrintWriter对象 |
| String getCharacterEncoding() | 获取响应内容的编码方式 |
| void setContentType(String type) | 如果尚未提交响应,则设置发送到客户端响应的内容类型, 内容类型可以包括字符编码规范,例如:text/html;charset=utf-8 |
HttpServletResponse 接口
接口继承 ServletResponse 接口,以便在发送响应式提供特定于HTTP的功能
| 方法 | 功能 |
|---|
| void sendRedirect(String location) | 使用指定的重定向位置URL向客户端发送临时重定向响应 |
ServletConfig 接口
用于描述 Servlet 本身的相关配置信息,在初始化期间用于将信息传递给 Servlet 配置对象
| 方法 | 功能 |
|---|
| String getServletName() | 返回 Servlet 的别名 |
| String getInitParameter(String name) | 返回包含初始化参数值的字符串,如果该参数不存在,返回null |
| Enumeration getInitParameterNames() | 将servlet的初始化参数名称作为字符串对象的枚举返回, 如果servlet没有初始化参数,则返回空枚举 |
| ServletContext getServletContext() | 返回对调用方正在其中执行的ServletContext的引用 |
ServletContext 接口
- 主要用于定义一组方法,Servlet 使用这些方法与他的 Servlet 容器通信
- 服务器在启动的时候会为每个项目唯一的一个 ServletContext 对象,用于实现对个 Servlet 之间的信息共享与通信
- 在 Servlet 中可以通过使用
this.getServletContext()获取 ServletContext 对象。
- 配置方式
<context-param>
<param-name>key1</param-name>
<param-value>value1</param-value>
</context-param>
<context-param>
<param-name>key2</param-name>
<param-value>value2</param-value>
</context-param>
| 方法 | 功能 |
|---|
| String getInitParameter(String name) | 返回包含初始化参数值的字符串,如果该参数不存在,返回null |
| Enumeration getInitParameterNames() | 将servlet的初始化参数名称作为字符串对象的枚举返回,如果servlet没有初始化参数,则返回空枚举 |
| String getRealPath(String path) | 返回包含给定虚拟路径的实际路径的字符串 |
| String getContextPath() | 返回与此上下文关联的主路径 |
| InputStream getResourceAsStream(String path) | 将位于指定路径的资源作为InputStream对象返回 |
| void setAttrbute(String name,Object value) | 将指定的属性名和属性值绑定到当前对象(能够跨Servlet通信) |
| Object getAttrbute(String name) | 根据执行的属性名获取属性值(能够跨Servlet通信) |
| void removeAttrbute(String name) | 删除指定的属性名信息(能够跨Servlet通信) |
Servlet的生命周期
实例化(容器创建 Servlet 实例,即调用了 Servlet 的构造方法)
↓
初始化(该 Servlet 调用 init() 方法)
↓
服务(有请求进入到 Servlet,该 Servlet 调用了 service() 方法)
↓
销毁(该 Servlet 调用了 destory() 方法)
↓
不可用(销毁该 Servlet,并标记为垃圾回收)
- 构造方法只会调用一次,第一次请求 Servlet 是会调用构造方法来创建实例
- init 方法只会调用一次,当实例创建完成后立即调用 init 方法进行初始化
- service 方法能被多次调用,每当有请求进入 Servlet,都会调用 Service 方法
- destory 方法只会被调用一次,当实例所在的 web 应用被卸载前会调用该方法来释放当前占用的资源
线程安全问题
- 当接收到请求时,就会启动一个线程来进行相应的请求。
- 默认情况下,服务器只会为每个 Servlet 创建一个实例,当多个请求访问同一个 Servlet 时,就会有多个线程访问同一个 Servlet 对象,此时就会可能发生线程安全问题
状态管理
- Web 程序基于 HTTP 协议通信,而 HTTP 协议是"无状态"的协议,一旦服务器响应完客户端的请求之后,就断开连接,而同一个客户端的下一次请求优惠重新建立网络连接
- 服务器程序有时候是需要判断是否为同一个客户发出的请求,比如客户的多次选购商品,所以有必要追踪同一个客户发出的一系列请求
- 把浏览器与服务器之间的多次监护作为一个整体,将多次交互锁涉及的数据保存下来,即状态管理
- 多次交互的数据状态可以在客户端保存,也可以在服务器端保存,状态管理主要分为以下两类:
- 客户端管理:将状态保存在客户端,基于 Cookie 技术实现
- 服务端管理:将状态保存在服务端,基于 Session 技术实现
Cookie 技术
基本概念
- Cookie在这里表示客户端以(key-value)形式将数据保存的一种技术
- 浏览器在先服务器发送请求时,服务器将数据以 Set-Cookie 消息头的方式响应给浏览器,然后浏览器会将这些数据以文本文件的方式保存起来
- 当浏览器再次访问服务器时,会将这些数据以 Cookie 消息头的方式发送给服务器
相关方法
- 使用 javax.servlet.http.Cookie 类的构造方法实现 Cookie 的创建
| 方法 | 功能 |
|---|
| Cookie(String name,String value) | 根据参数指定数值构造对象 |
- 使用 javax.servlet.http.HttpServletResponse 接口的成员方法实现 Cookie 的添加
| 方法 | 功能 |
|---|
| void addCookie(Cookie cookie) | 添加指定的Cookie到响应 |
- 使用 javax.servlet.http.HttpServletRequest 接口的成员方法实现 Cookie 对象的获取
| 方法 | 功能 |
|---|
| Cookie[] getCookie() | 返回此请求中包含的所有Cookie对象 |
- 使用 javax.servlet.http.Cookie 类的的成员方法实现 Cookie 对象中属性的获取与修改
| 方法 | 功能 |
|---|
| String getName() | 返回此Cookie对象的名字 |
| String getValue() | 返回此Cookie对象的数值 |
| void setValue(String newValue) | 设置此Cookie对象的数值 |
Cookie 生命周期
- 默认情况下,浏览器会将Cookie信息保存在内存中,只要浏览器关闭,Cookie 信息就会消失
- 如果希望关闭浏览器后 Cookie 信息任然有效,可以通过Cookie 类的成员方法设置
| 方法 | 功能 |
|---|
| int getMaxAge() | 获取Cookie 的最长使用期限(秒为单位) |
| void setMaxAge(int expiry) | 设置Cookie的最长使用期限(秒) |
路径问题
- 浏览器在访问服务器时,会比较Cookie的路径与请求路径是否匹配,只有匹配的Cookie才会发送给服务器
- Cookie的默认路径等于添加这个Cookie信息是的组件路径,例如:/项目名/目录/cookie 请求添加了一个 Cookie 信息,则该 Cookie 的路径是 :/项目名/目录
- 访问的请求地址必须符合 Cookie 的路径或者其子路径是,浏览器才会发送 Cookie 信息
- 可以通过 Cookie 的成员方法设置路径信息
| 方法 | 功能 |
|---|
| void setPath(String url) | 设置Cookie 的路径信息 |
特点
Cookie技术不适合存储所有数据,只用于存储少量、非敏感信息,原因:
- 将状态数据保存在浏览器端,不安全
- 保存数据量有限制,大约4KB
- 只能保存字符串信息
- 可以通过浏览器设置禁止使用Cookie
Session 技术
基本概念
- session 本意是 "会话" ,用来维护每一个客户端和服务器相关联的一种技术
- 当浏览器访问服务器的时候,服务器会在内存空间中为每一个浏览器分配一个空间,用于创建一个 session 对象,该对象有一个 id 属性 且该值唯一,称之为 sessionId,并且服务器会将这个 sessionId 以 Cookie 方式发送给浏览器存储
- 浏览器再次访问服务器时,会将 sessionId 发送到服务器,服务器依据 sessionId 查找对应的 session 对象
相关方法
- 使用 javax.servlet.http.HttpServletRequest 接口的成员方法实现 session 的获取
| 方法 | 功能 |
|---|
| HttpSession getSession() | 返回此请求相关联的session,如果没有则创建一个 |
- 使用 javax.servlet.http.HttpSession 接口的成员方法实现判断和获取
| 方法 | 功能 |
|---|
| boolean isNew() | 判断是否为新创建的 session |
| String getId() | 获取 session 的编号 |
- 使用 javax.servlet.http.HttpSession 接口的成员方法实现属性的管理
| 方法 | 功能 |
|---|
| Object getAttribute(String name) | 获取此会话中指定名称的对象,如果没有则返回空值 |
| void setAttribute(String name,Object value) | 设置此会话中指定名称的属性值 |
| void removeAttribute(String name) | 删除此会话中指定名称的对象 |
生命周期
- 为了节省服务器内存空间资源,服务器会将空闲时间过长的 session 对象自动清除,服务器默认的超时限制一般是 30 分钟
- 可以使用 javax.servlet.http.HttpSession 接口的成员方法来设置失效的时间
| 方法 | 功能 |
|---|
| int getMaxInactiveInterval() | 获取失效的时间(秒) |
| void setMaxInactiveInterval(int interval) | 设置失效时间(秒) |
- 也可以通过 web.xml 设置失效时间(单位为分钟)
<session-config>
<session-timeout>30</session-timeout>
</session-config>
特点
- 数据比较安全
- 保存的数据类型丰富
- 能保存比较多的数据
- 数据保存在服务器端会占用服务器的内存空间,如果存储信息过多、用户量过大会严重影响服务器的性能