Servlet笔记
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的基类,其中的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都可以获取ServletContext对象,而ServletConfig对象只能是其对应的Servlet才能获取。
因为ServletContext对象是所有Servlet共享的,所以会存在线程安全隐患。
Servlet的生命周期
Servlet生命周期定义了一个Servlet如何被加载、初始化,以及它怎样接收请求、响应请求,提供服务。
主要体现在三个方法:
方法 | 描述 |
---|---|
init(ServletConfig config) | 客户端首次访问该Servlet时执行,仅执行一次 |
service(ServletRequest request, ServletResponse response) | Servlet的核心,处理和响应客户端发来的请求 |
destroy() | 服务端关闭或Servlet销毁时,执行该方法,仅执行一次 |
服务器启动时,如果配置了自动装载,那么Servlet就会被自动装载进Servet容器。如果没有配置自动装载,那么客户端第一次请求时,装载Servlet为实例。
当Servlet被装载为实例后,Servlet容器会调用每个Servlet的init()方法进行初始化,如果初始化失败,init()方法抛出ServletException异常,Servlet对象将会被垃圾回收器回收。
一个Servlet实例只能初始化一次,但可以创建多个相同的Servlet实例。如相同的Servlet可以在根据不同的配置参数连接不同的数据库时创建多个实例。
如果初始化成功,该实例就处于待命状态,客户端每发起一次请求,都会调用一次service()方法。
当服务器不再需要Servlet实例或重新装入时,会调用destroy()方法,使用这个方法,Servlet可以释放掉所有在init()方法申请的资源。一个Servlet实例一旦终止,就不允许再次被调用,只能等待被回收。
request和response对象
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接收request后没有返回response,而是调用另一个Servlet来返回response,也就是说客户端的一次请求调用了两个Servlt才返回响应。
请求转发时,需要先获取一个RequestDispatcher转发器对象,然后再通过该对象,进行请求转发。
request.getRequestDispatcher(“转发的地址”).forward(request, response);
重定向
重定向指的是一个Servlet接收request后返回response,但是在response的响应头中,会添加一个新的访问路径,客户端接收到这个response后,会根据这个新路径,再次发起请求,也就是说客户端发起了两次请求。
重定向的时候,直接在response中添加新的路径。
response.sendRedirect(“重定向的地址”);
请求转发和重定向的区别
请求转发 | 重定向 | |
---|---|---|
使用对象 | request | response |
地址栏 | 不变 | 发生变化 |
请求/响应 | 一次请求,一次响应 | 两次请求,两次响应 |
路径 | 不需要加工程名 | 需要加工程名 |
功能 | 只能服务器内部转发 | 可以跳转任意网站 |
数据共享 | request数据可以共享 | request数据不可以共享 |
过滤器Filter
过滤器主要的作用包括过滤和拦截,对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。
个人学习总结,欢迎批评指正