一、Servlet的生命周期
(1)创建:构造方法
(2)初始化:init()
默认:第一次访问时,完成创建和初始化。
<!--
在web.xml中的servlet标签中配置
load-on-startup就是在启动服务器时就创建并初始化Servlet对象
数字越小,优先级越高。
-->
<load-on-startup>1</load-on-startup>
(3)执行:service() 客户端发起请求时执行
(4)销毁:destroy() 服务器关闭时,Servlet被销毁
问题1:Servlet对象创建、初始化并使用完后会销毁吗?
显然,Servlet对象在创建、初始化并使用后不应该销毁。如果使用完(请求处理完)就销毁,那么下次过来请求又得去创建Servlet对象,这样效率并不高!!
我们自始至终都使用同一个Servlet对象去处理请求,如果同时有10个请求过来访问Tomcat服务器,服务器会创建10个线程来处理请求,因为service方法不涉及到全局变量的修改操作,所以也不会有线程安全问题的。
问题2:Servlet对象会被创建及初始化几次?
由问题1,我们可以了解到,Servlet对象只会被创建及初始化一次。之后会驻留在内存当中。
问题3:Servlet对象是在什么时候创建及初始化的?
Servlet的创建与初始化的时机有两个:
-
Servlet在第一次被浏览器访问的时候创建与初始化的(目前我们的代码用的就是这种方式,默认就是这种)
-
Servlet在启动服务器的时候被创建与初始化的(该方式需要做一些配置,告诉Tomcat服务器在启动的时候就创建Servlet对象)
问题4:Servlet对象什么时候销毁?
Servlet对象是由Tomcat服务器创建的,之后就一直驻留在内存中处理请求。直到服务器停止后,Servlet才会被销毁!
二、web.xml配置Servlet的几种方式
<!--
1. url-pattern的值是 /字符 的方式
比如 /UserServlet,那访问该Servlet的时候url这么写:http://ip:port/项目名/UserServlet
-->
<url-pattern>/UserServlet</url-pattern><!--
2. url-pattern的值是 *.do的方式,
比如 *.do 那访问该Servlet的时候url这么写:http://ip:port/项目名/xxx.do 只要以.do结尾就行
-->
<url-pattern>*.do</url-pattern><!--
3. url-pattern的值是 多级目录的方式
比如 /user/UserServlet,那访问该Servlet的时候url这么写:http://ip:port/项目名/user/UserServlet
-->
<url-pattern>/user/UserServlet</url-pattern><!--
4. url-pattern的值是 /*,表示拦截所有请求
那随便写个访问到该项目的url地址,都会访问该Servlet
-->
<url-pattern>/*</url-pattern><!--
5. url-pattern的值是 /,表示拦截所有请求,但是不拦截 jsp文件
除了访问jsp外,访问其他的资源都会访问到该Servlet
-->
<url-pattern>/</url-pattern><!-- 默认欢迎页的设置 -->
<welcome-file-list>
<welcome-file>hello.html</welcome-file>
</welcome-file-list>
三、HttpServletResponse的使用
(1)获取请求方式
req.getMethod();
(2)获取URI
req.getRequestURI();
(3)获取协议及版本号
req.getProtocol();
(4)获取请求头中的数据
req.getHeader(请求头中的key);
(5)获取请求头中的所有key的值
req.getHeaderNames();
(6)获取客户端的IP
req.getRemoteHost();
(7)获取客户端的端口号
req.getRemotePort();
※(8)获取请求参数
req.getParameter(key值);
※(9)获取请求参数,同一个key值对应了多个value
req.getParameterValues(key值);
※(10)获取所有请求参数key值
req.getParameterNames();
※(11)获取请求参数的Map集合
req.getParameterMap();
※(12)设置编码格式
req.setCharacterEncoding("utf-8");
※(13)设置响应体内容类型
resp.setContentType("text/html;charset=utf-8");
Type | Meaning |
---|---|
application/postscript | PostScript file |
application/vnd.lotus-notes | Lotus Notes file |
application/vnd.ms-excel | Excel spreadsheet |
application/vnd.ms-powerpoint | PowerPoint presentation |
application/x-gzip | Gzip archive |
application/x-java-archive | JAR file |
application/x-java-serialized-object | Serialized Java object |
application/x-java-vm | Java bytecode (.class) file |
application/zip | Zip archive |
audio/basic | Sound file in .au or .snd format |
audio/midi | MIDI sound file |
audio/x-aiff | AIFF sound file |
audio/x-wav | Microsoft Windows sound file |
image/gif | GIF image |
image/jpeg | JPEG image |
image/png | PNG image |
image/tiff | TIFF image |
image/x-xbitmap | X Windows bitmap image |
text/css | HTML cascading style sheet |
text/html | HTML document |
text/plain | Plain text |
text/xml | XML |
video/mpeg | MPEG video clip |
video/quicktime | QuickTime video clip |
application/msword | Microsoft Word document |
application/octet-stream | Unrecognized or binary data |
application/pdf | Acrobat (.pdf) file |
四、HttpServletResponse的使用
设置响应头的信息
//修改响应头
resp.setHeader("key", "value");
//添加响应头
resp.addHeader("name", "value");
//下面两行代码是等价的
resp.setContentType("text/html;charset=utf-8");//设置响应的数据类型及解码方式
resp.setHeader("Content-Type", "text/html;charset=utf-8");//设置响应的数据类型及解码方式
五、请求转发和请求重定向
(1)请求转发
//向req对象中存储数据
req.setAttribute("key","value");
//从req对象中获取数据
req.getAttribute("key");
//请求转发
req.getRequestDispatcher("/Servlet2").forward(req,resp);
特点:
-
请求转发是一次请求,地址栏地址不变,还是访问第一个Servlet的地址
-
请求转发是一次请求,所以转发内的各个Servlet共享一个request对象
-
请求转发是Tomcat服务器内部的行为,用户是看不到的
-
可以使用req.setAttribute(key,value)和getAttribute(key)实现请求转发内的Servlet的数据的流转
总结:请求转发可以实现在后端Servlet之间的相互调用,一个请求由一个Servlet处理,转变为了多个Servlet的协同处理。
(2)请求重定向
resp.sendRedirect(req.getContextPath() + "/MainServlet");
特点:
-
重定向是两次请求,地址栏信息改变,地址会变成第二次请求的地址
-
重定向的地址是浏览器收到第一次请求响应回来的地址,自动跳转的,用户不参与
-
重定向的两次请求,request对象是不同的
(3)转发和重定向的区别
请求转发是一次请求,是Tomcat服务器内部的行为,共享同一个request对象。浏览器只需要发一次请求即可将业务处理完毕。
重定向是两次请求,地址栏信息会改变。一般用户的增删改请求会使用重定向的方式来处理请求。目的是保护第一次请求,避免用户因刷新页面造成表单重复提交。
总结:不论是请求转发还是请求重定向,都会涉及到多个Servlet。如果你需要将A Servlet的处理结果要带到B Servlet中去使用,那就使用请求转发。如果A Servlet的处理结果不需要带到B Servlet中去使用,那就使用重定向。
六、Cookie对象
(1)用处
浏览器在发起请求的时候,请求达到服务器,服务器认为本次请求携带的数据比较常用,以后的请求也会用得上,那么服务器就会在响应的时候告诉浏览器,把本次请求的数据给保存起来。然后浏览器以后每次发送请求访问服务器的时候都给带上!而存储这样数据的对象就是Cookie。
(2)总结
-
服务器决定哪些数据是以后的请求也会用到的
-
服务器以响应的方式告诉浏览器将常用的这些数据存储起来,存储在浏览器端
-
浏览器以后每次发送请求的时候需要带上这些存储起来的数据
(3)性质
-
Cookie是浏览器端的数据存储技术
-
浏览器每次发起请求的时候,请求信息中就包含了Cookie中存储的数据
-
Cookie不适合大量数据的存储(每个Cookie存储的数据不超过4KB)
-
不安全,不适合存储重要的数据到浏览器端
(4)使用方式
//创建Cookie对象
Cookie cookie = new Cookie("username", username);
//将创建好的Cookie对象创建到响应中
resp.addCookie(cookie);//其他servlet获取Cookie
Cookie[] cookies = req.getCookies();/* 设置Cookie对象的存活时间
正数:表示在指定的秒数后过期
负数:表示浏览器一关,Cookie就会被删除(默认是-1)
零:表示马上删除Cookie */
cookie.setMaxAge(60);//设置可以获取到该Cookie对象的路径范围,若abc为文件夹则只有abc下的资源能访问,若abc为一个资源则只有abc资源能访问
cookie.setPath(req.getContextPath()+"/abc");
//设置域名只要是baidu.com结尾的二级域名都可以访问
cookie.setDomain("baidu.com");
七、HttpSession对象
(1)作用
解决Http协议无状态,实现方式是将数据存储在服务器的Session对象中,将Session的唯一标识JSESSIONID存储到浏览器中的Cookie对象中;一般只存放用户登录的信息或者错误信息。
(2)特点
-
Session技术解决用户发送不同请求时数据共享的问题
-
一个用户在服务器中只会创建一个Session对象。不同用户的Session对象之间是互相独立的
-
在服务器中创建Session对象,创建完成后会将Session对象的Id(JSESSIONID)以Cookie的形式保存在客户端(浏览器),用户再次发请求时,会携带该Cookie,也就是JSESSIONID到服务器,服务器会根据该id找到用户的Session对象
-
用户JSESSIONID的Cookie丢失或者服务器中存储的Session对象被销毁,服务器接收到用户的请求后,如果找不到对应的Session对象,会重新创建,并将新的JSESSIONID以Cookie的形式保存到浏览器中
-
存储JSESSIONID的Cookie不需要手动创建,Session对象创建完成,Tomcat服务器会自动创建Cookie, 将JESSIONID存储在Cookie中响应回浏览器。
-
Cookie默认的有效期为一次会话,浏览器关闭,Cookie即失效
-
Session对象在Tomcat服务器的默认有效期为30分钟
-
Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session"活跃(active)"了一次。
总结:综上所述,默认情况下,浏览器关闭后Cookie被删除,那么再次访问时就不能对应到Session,如果没有关闭浏览器,但是浏览器30分钟内没有操作,那么该Session对象被销毁了,那么存在浏览器中的Cookie也就失去了意义。
(3)使用方式
package com.bjsxt.controller;
import com.bjsxt.pojo.TUser;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
TUser user = new TUser();
/*
* 浏览器第一次请求服务器,Cookie中没有JSESSIONID
* 执行req.getSession();,会创建Session对象,自动将Session对象得到JSESSIONID以Cookie形式存储到浏览器中,再返回session
*
* 浏览器再次请求服务器,Cookie中携带JSESSIONID,
* 执行req.getSession(),会根据JSESSIONID寻找Session对象
* 1.找到,直接返回session
* 2.没找到,会创建Session对象,自动将Session对象得到JSESSIONID以Cookie形式存储到浏览器中,再返回session
*
* Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。
* 用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session"活跃(active)"了一次。
* */
HttpSession session = req.getSession();
//向Session对象中存储数据
session.setAttribute("user",user);
//从Session对象中获取数据
session.getAttribute("user");
//获取JSESSIONID
String id = session.getId();
//获取创建时间
long creationTime = session.getCreationTime();
//获取最后一次访问时间
long lastAccessedTime = session.getLastAccessedTime();
//设置最大不操作时间,单位是秒
session.setMaxInactiveInterval(600);
//获取最大不操作时间
int maxInactiveInterval = session.getMaxInactiveInterval();
/*
* 销毁HttpSession对象
* 1.默认浏览器没有操作30分钟后销毁,可通过配置web.xml文件修改默认销毁的时间
* <session-config>
* <!--设置Session的超时时间,单位是分钟-->
* <session-timeout>10</session-timeout>
* </session-config>
* 2.通过invalidate()方法手动销毁
* */
session.invalidate();
}
}
(4)Cookie和Session的区别
-
Cookie数据存储在客户端,而HttpSession中的数据存储在服务器
-
Cookie不安全,而HttpSession是安全的
-
单个cookie保存的数据不能超过4KB,很多浏览器都限制一个域名保存cookie的数量
HttpSession没有容量以及数量的限制, 随着Session中存储的内容增多,会比较占用服务器内存, Session不存放业务数据
-
Cookie的数据都以字符串的形式保存。Session中可以保存对象
-
Cookie实现, 如: 记住我 最近浏览商品 网页皮肤 等
-
Session实现, 如: 登录信息 错误信息 购物车 等
-
Session依赖于Cookie
八、ServletContext对象
(1)作用
存储不同的用户也可能会用到相同的数据。
(2)特点
-
ServletContext对象由Tomcat服务器在启动加载项目的时候完成创建
-
ServletContext对象一个项目中只有一个,以任意方式获取到的都是同一个
-
ServletContext对象中保存的数据是所有共享的
(3)使用方式
package com.bjsxt.controller;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/contextServlet")
public class ContextServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取ServletContext对象
ServletContext servletContext = getServletContext();
ServletContext servletContext1 = this.getServletContext();
ServletContext servletContext2 = super.getServletContext();
ServletContext servletContext3 = req.getServletContext();
ServletContext servletContext4 = req.getSession().getServletContext();
//往ServletContext对象中存数据,键值对的方式
servletContext.setAttribute("name", "root");
//从ServletContext对象中获取数据
String name = (String)servletContext.getAttribute("name");
/*
* 可以在web.xml中配置一些参数,可以通过ServletContext对象获取。经常出现在框架的底层。
* <!--配置上下文参数-->
* <context-param>
* <param-name>name</param-name>
* <param-value>admin</param-value>
* </context-param>
* */
String name1 = servletContext.getInitParameter("name");
}
}
九、域对象
什么是域对象
域对象类似于map集合,可以存放键值对的数据。不同的是域对象中数据的使用有一定的区域范围限制。
三大域对象
request域 对应HttpServeltRequest对象 也叫请求域
Session域 对应HttpSession对象 也叫会话域
application域 对应ServletContext对象 也叫应用域
常用API
setAttribute(key, value) 向域中添加/修改数据,无则添加,有则修改
getAttribute(key) 获取域中的数据
removeAttribute(key) 从域中移除指定key的数据
十、过滤器(Filter)
(1)使用场景
需要对请求进行相关处理, 处理完成后, 在访问请求的资源。
(2)使用方式
-
创建一个类,实现过滤器接口(Filter)
-
实现接口中的方法,编写自己的代码
-
在web.xml中配置过滤器或通过注解配置
package com.bjsxt.controller;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")
public class CharacterFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
//请求之前会经过
//放行
filterChain.doFilter(servletRequest,servletResponse);
//响应之前会经过
}
@Override
public void destroy() {
}
}
十一、 监听器(Listener)
(1)作用
监听三大域对象的创建、销毁及数据的变更。
(2)特点
-
监听方法由tomcat根据监听结果来调用执行
-
监听方法中的逻辑代码由我们根据需要编写
(3)使用方式
监听器的使用步骤:
-
创建一个类,实现监听器接口(Listener)
-
实现里面的方法
-
在web.xml中配置监听器或通过注解配置
<!--
配置监听器,在服务器启动的时候就会创建监听器对象,监听器生效,一旦符合监听要求,
tomcat底层会通过反射调用监听器中的方法完成处理
-->
<listener>
<listener-class>com.bjsxt.listener.MyListener</listener-class>
</listener>@WebListener
监听器接口:
-
ServletRequestListenter 监听request对象的创建销毁
-
ServletRequestAttributeListener监听request域中数据的变更
-
HttpSessionListener 监听Session对象的创建销毁
-
HttpSessionAttributeListener 监听Session对象中数据的变更
-
ServletContextListener 监听ServletContext对象的创建销毁
-
ServletContextAttributeListener监听ServletContext对象中数据的变更
package com.chen.listener;
import javax.servlet.*;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class MyListener implements ServletRequestListener, ServletRequestAttributeListener,
HttpSessionListener, HttpSessionAttributeListener, ServletContextListener, ServletContextAttributeListener {
//监听ServletContext对象中数据的添加
@Override
public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
}
//监听ServletContext对象中数据的删除
@Override
public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
}
//监听ServletContext对象中数据的修改
@Override
public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
}
//监听ServletContext对象的初始化
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
}
//监听ServletContext对象的销毁
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
//监听ServletRequest对象中数据的添加
@Override
public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("request对象中添加的数据!");
}
//监听ServletRequest对象中数据的删除
@Override
public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("request对象中删除了数据!");
}
//监听ServletRequest对象中数据的修改
@Override
public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("request对象中修改了数据!");
}
//监听ServletRequest对象中数据的销毁
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
System.out.println("request对象被销毁!");
}
//监听ServletRequest对象的初始化
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
System.out.println("request对象被初始化!");
}
//监听HttpSession对象中数据的添加
@Override
public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
}
//监听HttpSession对象中数据的删除
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
}
//监听HttpSession对象中数据的修改
@Override
public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
}
//监听HttpSession对象的创建
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
}
//监听HttpSession对象的销毁
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
}
}