Servlet笔记

Servlet简介

Servlet是什么?

Servlet是Java Servlet的简称,Servlet即Server Applet,Java服务程序。
Java Servlet是运行在Web服务器或应用服务器上的程序,它是作为来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层。
简单点说,Servlet的作用就是负责接收和响应客户端的请求。
Servlet可以使用javax.servlet和javax.servlet.http包创建。

创建Servlet

Servlet笔记
Servlet接口是Servlet的基类,其中的service()方法负责接收和响应客户端发来的请求。
GenericServlet类实现了Servlet接口,并将Servlet接口中的方法做了空实现,只将service()方法作为抽象方法。可以继承GenericServlet类,并重写service()方法,从而创建一个Servlet。
HttpServlet类继承了GenericServlet类,其中service()方法处理了doGet()和doPost()等方法。所以继承HttpServlet类时,只需要重写doGet()和doPost()方法。
实现HttpServlet类,重写doGet()和doPost()方法。

package com.zyz.servlet;

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

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

继承HttpServlet类后,还需要在web.xml文件中配置该Servlet处理那些请求。

<servlet>		
	<servlet-name>myServlet</servlet-name>
	<servlet-class>com.zyz.servlet.MyServlet</servlet-class>
	<init-param>
		<param-name>key</param-name>
		<param-value>value</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>myServlet</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>

配置说明如下:

标签 描述
<servlet> 注册一个servlet
<servlet-name> 该servlet的名称
<servlet-class> 该servlet对应的类
<init-param> 初始化参数,key-value形式
<load-on-startup> 加载优先级
<servlet-mapping> 该servlet映射的路径
<url-pattern> 访问路径,必须以/开头

除了在web.xml中配置以外,还可以使用@WebServlet注解配置Servlet。

@WebServlet(name = "servlet名称",
        description = "该servlet的描述",
        urlPatterns = {"/映射地址1", "/映射地址2"},
        loadOnStartup = 1,
        initParams = {@WebInitParam(name = "键", value = "值")})
public class MyServlet extends HttpServlet {
}

配置说明如下:

属性 描述
name 该servlet的名称
description 该servlet的描述
urlPatterns 访问路径,可以有多个
loadOnStartup 加载优先级
initParams 初始化参数,key-value形式

一个Servlet可以定义多个访问路径,路径定义规则如下:

路径 描述
/xxx 单层路径
/xxx/xxx 多层路径
*.do 扩展名配置
/ 缺省路径

ServletConfig对象

Servlet基类中定义了getServletConfig()方法,GenericServlet类实现了Servlet接口后,重写了该方法,该方法就是用来获取ServletConfig对象的。
当Servlet配置了初始化参数后,web容器在创建Servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用Servlet的init()方法时,将ServletConfig对象传递给Servlet。所以,我们通过ServletConfig对象就可以得到当前Servlet的初始化参数信息。
ServletConfig对象中有四个方法,说明如下:

方法 描述
getServletName() 获取该servlet名称
getServletContext() 获取ServletContext对象
getInitParameter(String key) 根据键获取初始化参数的值
getInitParameterNames() 获取所有参数名称列表

ServletContext对象

Servlet容器在启动加载web应用时,会为每个web应用创建唯一的ServletContext对象,ServletContext对象就像是一个web应用的共享资源库,他是一个全局对象,凡是web容器中的Servlet都可以访问。
ServletContext是一个域对象,在Servlet中,除了ServletContext还有两个域对象,分别是Request、Session。
域对象是服务器在内存上创建的存储空间,用于在不同动态资源(servlet)之间传递与共享数据。
凡是域对象都有如下3个方法:

方法 描述
setAttribute(String name,Object value) 往域对象里面添加数据,添加时,以key-value形式添加
getAttribute(String name) 根据指定的key读取域对象里面的数据
removeAttribute(String name) 根据指定的key从域对象里面删除数据

在web项目初始化时,我们可以给整个项目添加全局参数,这些参数会被转化为键值对,并交给ServletContext对象。这些参数会在web项目完全启动之前被执行,所以往往这些参数会被当作初始化参数使用。
在web.xml文件中添加初始化参数:

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>classpath:spring-mybatis.xml</param-value>
</context-param>

ServletContext对象中的方法:

方法 描述
getInitParameter(String name) 根据指定的参数名获取参数值
getInitParameterNames() 获取所有参数名称列表
getRealPath(String path) 根据相对路径获取服务器上资源的绝对路径
getContextPath() 返回当前响应的上下文路径

ServletConfig和ServletContext的区别

Servlet笔记
他们的共同点是都能给Servlet预设参数。
他们的区别是:每一个Servlet都可以获取ServletContext对象,而ServletConfig对象只能是其对应的Servlet才能获取。
因为ServletContext对象是所有Servlet共享的,所以会存在线程安全隐患。

Servlet的生命周期

Servlet笔记
Servlet生命周期定义了一个Servlet如何被加载、初始化,以及它怎样接收请求、响应请求,提供服务。
主要体现在三个方法:

方法 描述
init(ServletConfig config) 客户端首次访问该Servlet时执行,仅执行一次
service(ServletRequest request, ServletResponse response) Servlet的核心,处理和响应客户端发来的请求
destroy() 服务端关闭或Servlet销毁时,执行该方法,仅执行一次

Servlet笔记
服务器启动时,如果配置了自动装载,那么Servlet就会被自动装载进Servet容器。如果没有配置自动装载,那么客户端第一次请求时,装载Servlet为实例。
当Servlet被装载为实例后,Servlet容器会调用每个Servlet的init()方法进行初始化,如果初始化失败,init()方法抛出ServletException异常,Servlet对象将会被垃圾回收器回收。
一个Servlet实例只能初始化一次,但可以创建多个相同的Servlet实例。如相同的Servlet可以在根据不同的配置参数连接不同的数据库时创建多个实例。
如果初始化成功,该实例就处于待命状态,客户端每发起一次请求,都会调用一次service()方法。
当服务器不再需要Servlet实例或重新装入时,会调用destroy()方法,使用这个方法,Servlet可以释放掉所有在init()方法申请的资源。一个Servlet实例一旦终止,就不允许再次被调用,只能等待被回收。

request和response对象

Servlet笔记
request对象是服务器对浏览器请求的封装,而response对象是服务器对服务器响应的封装。
简单点说,request就是客户端发给服务器的东西,response就是服务器返回给客户端的东西。

request

request常用方法:

方法 描述
getCharacterEncoding(String encoding) 返回字符编码方式
getContentLength() 返回请求体的长度(字节数)
getContentType() 得到请求体的MIME类型
getParameter(String name) 返回name指定参数的参数值
getParameterNames() 返回可用参数名的枚举
getParameterValues(String name) 返回包含参数name的所有值的数组
getProtocol() 获取请求使用的具体协议版本
getRealPath(String path) 获取相对路径对应的真实路径
getRemoteAddr() 返回发送此请求的客户端IP地址
getRemoteHost() 返回发送此请求的客户端主机名
getRequestDispatcher(String path) 获取转发器
getServerName() 返回接收此请求的服务器主机名
getServerPort() 返回接收此请求的服务器端口号
setCharacterEncoding(String encoding) 设置请求参数的编码方式
getContextPath() 返回当前WEB项目根路径
getCookies() 返回一个Cookie数组
getHeader(String name) 返回指定请求头
getMethod() 返回请求方法类型
getSession() 获取Session对象

response

response常用方法:

方法 描述
getOutputStream() 返回字节输出流对象
getWriter() 返回字符输出流对象
setCharacterEncoding(String encoding) 设置Response的编码方式
setContentLength(int len) 设置响应头长度
setContentType(String type) 告知浏览器数据类型
addCookie(Cookie cookie) 添加Cookie
addHeader(String name,String value) 添加消息头
sendRedirect(String location) 重新定向客户端的请求
setHeader(String name,String value) 设置消息头
setStatus(int sc) 设置状态码

addHeader()和setHeader()的区别

相同点:如果Header中没有定义则添加。
不同点:addHeader()如果已定义则保持原有value不改变,setHeader()如果已定义则用新的value覆盖原用value值。

请求转发和重定向

请求转发

Servlet笔记
请求转发指的是一个Servlet接收request后没有返回response,而是调用另一个Servlet来返回response,也就是说客户端的一次请求调用了两个Servlt才返回响应。
请求转发时,需要先获取一个RequestDispatcher转发器对象,然后再通过该对象,进行请求转发。

request.getRequestDispatcher(“转发的地址”).forward(request, response);

重定向

Servlet笔记
重定向指的是一个Servlet接收request后返回response,但是在response的响应头中,会添加一个新的访问路径,客户端接收到这个response后,会根据这个新路径,再次发起请求,也就是说客户端发起了两次请求。
重定向的时候,直接在response中添加新的路径。

response.sendRedirect(“重定向的地址”);

请求转发和重定向的区别

请求转发 重定向
使用对象 request response
地址栏 不变 发生变化
请求/响应 一次请求,一次响应 两次请求,两次响应
路径 不需要加工程名 需要加工程名
功能 只能服务器内部转发 可以跳转任意网站
数据共享 request数据可以共享 request数据不可以共享

过滤器Filter

Servlet笔记
过滤器主要的作用包括过滤和拦截,对web服务器管理的所有web资源(静态和动态)进行过滤和拦截。
Filter中有三个方法,这三个方法也就是Filter的生命周期。

init(FilterConfig filterConfig) 
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
destroy()

Filter中的init()方法,主要负责初始化参数,在创建Filter时自动调用FilterConfig对象进行初始化,当web容器启动时,Filter就会被加载到内存,该方法仅执行一次。
Filter中的destroy()方法,当web容器关闭时执行,释放Filter占用的资源,该方法仅执行一次。
Filter中的doFilter()方法,该方法负责对web资源进行过滤和拦截。web服务器在调用doFilter()方法时,会传递一个FilterChain对象进来,FilterChain对象是Filter接口中最重要的一个对象,它是由多个过滤器组成的一条链路,它也提供了一个doFilter()方法,调用该方法,则执行下一个过滤器的doFilter()方法,直到最后一个过滤器,才会执行目标Servlet的service()方法。

FilterConfig对象

FilterConfig对象用来配置Filter初始化时的一些参数。
FilterConfig接口中,有四个方法。

方法 描述
getFilterName() 返回过滤器名称
getInitParameter(String name) 返回指定参数的值
getInitParameterNames() 返回所有指定参数的集合
getServletContext() 返回ServletContext对象

创建Filter

实现Filter接口,重写doFilter()方法。

package com.zyz.filter;

import javax.servlet.*;
import java.io.IOException;

public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        
    }

    @Override
    public void destroy() {

    }
}

定义好实现类后,还需要在web.xml文件中配置该Filter过滤那些请求。

<filter>
	<filter-name>myFilter</filter-name>
    <filter-class>com.zyz.filter.MyFilter</filter-class>
    <init-param>
        <param-name>key</param-name>
        <param-value>value</param-value>
    </init-param>
</filter>
<filter-mapping>
	<filter-name>myFilter</filter-name>
	<url-pattern>/*</url-pattern>
	<servlet-name>myServlet</servlet-name>
</filter-mapping>

配置说明如下:

标签 描述
<filter> 注册一个filter
<filter-name> 该filter的名称
<filter-class> 该filter对应的类
<init-param> 初始化参数,key-value形式
<filter-mapping> 该filter拦截的资源
<url-pattern> 拦截的请求
<servlet-name> 拦截的servlet

除了在web.xml中配置以外,还可以使用@WebFilter注解配置Filter。

@WebFilter(description = "该servlet的描述",
        filterName = "filter名称",
        urlPatterns = {"/过滤请求1", "/过滤请求2"},
        servletNames = {"servlet1", "servlet2"},
        initParams = {@WebInitParam(name = "键", value = "值")})
public class MyFilter implements Filter {
}

配置说明如下:

属性 描述
filterName 该filter的名称
description 该filter的描述
urlPatterns 拦截的请求,可以有多个
servletNames 拦截的servlet
initParams 初始化参数,key-value形式

监听器Listener

监听器的作用就是用来监听指定对象的在生命周期内的变化。
Servlet中的监听器主要是监听ServletContext,HttpSession,ServletRequest三个域对象。
Servlet提供了八个监听器:
监听三个域对象的创建和销毁

被监听对象 监听器
ServletContext ServletContextListener
HttpSession HttpSessionListener
ServletRequest ServletRequestListener

监听三个域对象的属性的变更(属性添加,属性移除,属性替换)

被监听对象 监听器
ServletContext ServletContextAttributeListener
ServletRequest ServletRequestAttributeListener
HttpSession HttpSessionAttributeListener

监听HttpSession中JavaBean的状态的改变(绑定和解除绑定,钝化和活化)

被监听对象 监听器
HttpSession HttpSessionBindingListener
HttpSession HttpSessionActivationListener

使用监听器时,只需要根据要监听的对象实现八个接口即可。

public class MyListener implements ServletContextListener {
}

然后在web.xml中配置监听器。

<listener>
	<description>该监听器的描述</description>
	<listener-class>该监听器所在位置</listener-class>
</listener>

也可以直接使用@WebListener注解,配置监听器。

@WebListener
public class MyListener implements ServletContextListener {
}

Session和Cookie

因为HTTP协议是无状态的,所以服务器端根本就记不住客户端,所以需要用到Session和Cookie这两种保存会话的技术。

Session

Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的Session对象,由于Session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的Session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的Session中取出数据为用户服务。

request.getSession();
使用request获取session,如果不存在,则创建一个

Session常用方法:

方法 描述
getAttribute(String name) 根据key获取value
getAttributeNames() 返回session中所有的key
getCreationTime() 返回session创建时间
getId() 返回session的唯一id
getLastAccessedTime() 返回最近一次请求时间
getMaxInactiveInterval() 返回session超时时间
invalidate() session失效
removeAttribute(String name) 根据key删除指定value
setAttribute(String name,Object value) 设置key-value
setMaxInactiveInterval(int interval) 设置session超时时间

Cookie

Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样web资源处理的就是用户各自的数据了。

Cookie cookie = new Cookie(key,value);
创建cookie

Cookie常用方法:

方法 描述
getDomain() 获取cookie的有效域
getMaxAge() 获取cookie的有效期
getName() 取得cookie的名字
getPath() 获取cookie的有效路径
getValue() 取得cookie的值
setDomain(String pattern) 设置cookie的有效域
setMaxAge(int expiry) 设置cookie的有效期
setPath(String uri) 设置cookie的有效路径
setValue(String newValue) 设置cookie的值

一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。
浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
如果不设置Cookie的有效期,那么Cookie就会存储在浏览器的内存中,关闭浏览器,Cookie就会被删除。如果设置了有效期,浏览器就会将Cookie存储在硬盘上。将有效期设为0,则是命令浏览器删除该Cookie。


个人学习总结,欢迎批评指正