Servlet简介
概念
运行在服务器端的小程序
<!-- web.xml配置Servlet -->
<servlet>
<servlet-name>demo</servlet-name>
<servlet-class>cn.web.servlet.ServletDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo</servlet-name>
<url-pattern>/demo</url-pattern>
</servlet-mapping>
- 当服务器接受到客户端浏览器的请求后,会解析请求 URL 路径,获取访问的 Servlet 的资源路径;
- 查找 web.xml 文件,是否有对应的
<url-pattern>
标签体内容; - 如果有,则在找到对应的
<servlet-class>
全类名; - tomcat 会将字节码文件加载进内存,并且创建其对象;
- 调用其方法;
生命周期
1.初始化阶段
当客户端向Servlet容器发出HTTP请求要求访问Servlet时,Servlet容器首先会解析请求,检查内存中是否已经有了该Servlet对象,如果有,则直接使用该Servlet对象,如果没有,则创建Servlet实例对象,然后通过调用init()方法实现Servlet的初始化工作。需要注意的是,在Servlet的整个生命周期内,它的init()方法只能被调用一次。
- 第一次请求时,创建Servlet实例对象;
- 调用init()方法初始化。(不是第一次时直接使用Servlet对象)
2.运行阶段
这是 Servlet 声明周期中最重要的阶段,在这个阶段中,Servlet 容器会为这个请求创建代表 HTTP 请求的。
ServletRequest 对象和代表 HTTP 响应的 ServletResponse 对象,然后将它们作为参数传递给 Servlet 的 service()方法。
service() 方法从 ServletRequest 对象中获得客户请求信息并处理该请求,通过 ServletResponse 对象生成响应结果。
在 Servlet 的整个生命周期内,对于 Servlet 的每一次访问请求,Servlet 容器都会调用一次 Servlet 的 service() 方法,并且创建新的 ServletRequest 和 ServletResponse 对象,也就是说,service() 方法在 Servlet 的整个生命周期中会被调用多次。
- 一次请求就调用一次 service() 方法,并创建新的请求和响应对象作为参数传入;
3.销毁阶段
当服务器关闭或 Web 应用被移除出容器时,Servlet 随着 Web 应用的关闭而销毁。在销毁 Servlet 之前,Servlet容器会调用 Servlet 的 destory() 方法,以便让 Servlet 对象释放它所占用的资源。在 Servlet 的整个生命周期中,destory() 方法也只会被调用一次。
需要注意的是,Servlet 对象一旦创建就会驻留在内存中等待客户端的访问,直到服务器关闭或 Web 应用被移除出容器时,Servlet 对象才会销毁。
- 服务器关闭或应用销毁时,调用 destory() 方法销毁;
体系结构
Servlet是一个接口,下面有两个抽象子类。
其中 GenericServlet 抽象类直接实现Servlet接口,HttpServlet 继承 GenericServlet 抽象类;
request和response
- request 和 response 对象是由服务器创建的。
- request 对象是来获取请求消息,response 对象是来设置响应消息
- request 和 response 对象是 ServletRequest 接口的两个子接口 HttpServletRequest 和 HttpServletResponse声明的两个对象,用来处理请求和响应进而与客户端进行交互;
- ServletRequest 接口 的子接口 HttpServlet 比较常用,一般使用 HttpServleRequest 来声明 request 对象;response 同理;
- 通过 request 对象可以获得请求行数据中的请求方式,URI,请求参数,HTTP协议等;还可以获得请求头数据和请求体数据;
- 通过 response 对象可以设置响应消息;响应行,响应头,响应体;
- HTTP传输数据类型:ContentType
request域
域对象:一个有作用范围的对象,可以在范围内共享数据;
作用范围:一次请求。一般用于请求转发的多个资源中共享数据;
方法:
void setAttribute(String name, Object obj)
:存储数据;Object getAttribute(String name)
:根据键获取数据;void removeAttibute(String name)
:根据键移除键值对数据;
Servlet请求响应流程
- 浏览器发送请求到服务器(请求)
- 服务器接收浏览器的请求进行解析,创建request对象存储请求数据
- 服务器调用对应的Servlet进行请求处理,并将request对象作为实参传递给Servlet的service方法
- Servlet的service方法执行请求处理:
- 设置请求的编码格式
request.setCharacterEncoding("utf-8");
- 设置响应的编码格式
response.setContentType("text/html;charset=utf-8");
- 获取请求信息
- 处理请求信息
- 创建业务层对象
- 调用业务层对象的方法
- 设置请求的编码格式
- 响应请求处理
- 直接响应
- 请求转发
- 重定向
请求转发
服务器内部资源跳转的一种方式。
request.getRequestDispatcher("servletname").forward(request,response);
- 请求转发的两个Servlet属于一次请求,可以使用request对象共享数据;
- 浏览器地址栏信息不改变,
- 只能转发到当前服务器的资源;
- 刷新时可能导致表单重复提交。
- / :表示项目根目录
重定向
资源跳转的方式。
response.sendRedirect("url");
- 使用时机:解决当前Servlet无法处理请求的问题以及表单重复提交的问题。
- 重定向的两个Servlet属于两次请求,拥有两个request对象;
- 浏览器地址会改变,Servlet之间数据不能共享。
- 可以重定向到其他站点的资源;
- 两次请求的数据共享需要使用session,session依赖于cookie。
- / : 表示服务器根目录,绝对路径需要加上虚拟项目名
会话技术
springMVC操作cookie和session
- 会话:一次会话中包含多次请求和响应;一次会话是指浏览器第一次向服务器发起请求,会话建立,直到有一方断开为止;
- 功能:再一次会话的范围内的多次请求间共享数据;
- 方式:
- Cookie:客户端(浏览器)会话技术;
- Session:服务器端会话技术;
Cookie
概念:客户端会话技术,将数据保存在客户端。
实现原理:基于响应头 set-cookie(发送) 和 请求头 cookie实现(接收);
使用步骤:
- 创建cookie对象,绑定数据
Cookie cookie = new Cookie(String name, String value);
- 发送Cookie对象,在响应头中的set-cookie字段中;
response.addCookie(cookie);
- 获取Cookie,拿到 Cookie,在下一次请求请求头的 cookie 字段中;
Cookie[] cookies = request.getCookies();//数组
细节:
- 一次可不可以发送多个cookie?
- 可以,创建多个cookie对象,多次调用 addCookie 方法;
- cookie 在浏览器中保存多长时间?
- 默认情况下,当浏览器关闭后,cookie 数据被销毁;
- 持久化存储,设置有效期:
cookie.setMaxAge(int seconds);
参数为正数表示持久化到硬盘并设置 cookie 存活时间,单位秒;负数为默认值;0 代表删除 cookie 信息;
- cookie能不能存中文?
- tomcat8 之前不能直接存储中文数据,tomcat8 之后支持中文数据;
- tomcat8 之前对中文要进行 URL 编码存储,URL 解码解析;
- tomcat8 对特殊字符如空格等也不支持,要进行 URL 编码存储;
- cookie共享问题?
- 在同一个 tomcat 服务器下的多个 web 项目不可以共享 cookie;
- 可以通过设置有效路径:
cookie.setPath(String uri);
设置 cookie 的获取范围。默认情况下为当前项目的虚拟目录; - 如果要在同一服务器内多个 web 项目共享,可以把 path 设置为”/“,表示服务器内部共享;
- 如果要在不同服务器间进行 cookie 共享,可以设置域名 setDomain(String path):如果设置一级域名相同,那么多个服务器之间的 cookie 可以共享;
- setDomain(“.baidu.com”),那么 tieba.baidu.com 和 news.baidu.com 之间的 cookie 可以共享;
特点:
- cookie存储在客户端浏览器;
- 浏览器对于单个cookie的大小有限制,以及对同一个域名下的总数量也有限制;
作用:
- cookie 一般用于存储少量的不太敏感的数据;
- 在不登录的情况下,完成服务器对客户端的身份识别;
Session
概念:服务器会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中,属于 HttpSession类型;
实现原理:session 的实现是依赖于 cookie 的;
Session 也是一个域对象,与 Request、ServletContext 相似,也有域对象同样的方法:
Object getAttribute(String name);
void setAttribute(String name, Object value);
void removeAttribute(String name);
使用步骤:
- 创建/获取 session 对象;
- 如果请求中拥有 session 的标识符也就是 JSSESIONID,则返回其对应的 session 对象
- 如果请求中没有 JSSESIONID,则创建新的 session 对象,并将其 JSSESIONID 作为 cookie 对象存储到浏览器的运行内存中
- 如果 session 对象失效了,也会创建一个 session 对象,并将其 JSESSION 对象存储到浏览器的运行内存中
HttpSession session = request.getSession();
- 存储数据
session.setAttribute(String name, Object value);
- 获取数据
Object value = session.getAtrribute(String name);
注意:存储数据的动作和获取数据的动作发生在不同的请求中,但是存储要先于取出执行;
细节:
客户端关闭后,服务器不关闭,两次获取的session是否为同一个?
默认情况下,不是。默认情况下,浏览器关闭后,cookie 即失效,session 也就失效了,除非提前创建cookie 并设置最大存活时间,让 cookie 持久化保存,在设置时间范围内,获取的session为同一个。Cookie c = new Cookie("JSESSIONID", session.getId()); c.setMaxAge(60*60); response.addCookie(c);//此时1小时内,获取的session为同一个;
客户端不关闭,服务器关闭后,两次获取的session是否为同一个?
不是。但是要确保数据不丢失。Tomcat服务器自动实现钝化和活化;- session的钝化:在服务器正常关闭之前,将session对象序列化到硬盘上;
- session的活化:在服务器启动后,将session文件转化为内存中的session对象;
- session什么时候被销毁?
- 服务器关闭;
- session对象调用invalidate()
session.invalidate();
; - 默认失效时间为30分钟;
可以在web.xml中配置session-config设置默认失效时间。
也可以设置:hs.setMaxInactiveInterval(int seconds);
特点:
- session 用于存储一次会话的多次请求的数据,存在服务器端
- session 可以存储任意类型,任意大小的数据
- 依赖 cookie 技术,生命周期为一次回话,默认存储时间是 30 分钟
- session 对象的唯一标识 JSESSIONID 通过 cookie 技术作为一个 cookie 数据存储到浏览器的运行内存中
与cookie的区别:
- session存储数据在服务器端,cookie在客户端;
- session没有数据大小限制,cookie有;
- session数据安全(在服务器端),cookie相对不安全;
总结:
- 总结:session 解决了一个用户的不同请求的数据共享问题,只要在 JSESSIONID 不失效和 session 对象不失效的情况下,用户的任意请求在处理时都能获取到同一个 session 对象
- 注意:JSESSIONID 存储在了 cookie 的临时存储空间中,浏览器关闭即失效;
ServletContext对象
request解决了一次请求内的数据共享问题,session解决了一个用户不同请求的数据共享问题,而不同用户之间的数据共享问题则需要使用ServletContext对象。
特点
1. 由服务器创建
2. 用户共享
3. 一个项目只有一个
生命周期
服务器启动到服务器关闭
使用:
//1.获取ServletContext对象(三种方式,等价)
ServletContext sc = this.getServletContext();
ServletContext sc2 = this.getServletConfig().getServletContext();
ServletContext sc3 = request.getServletContext();
//ServletContext sc3 = req.getSession().getServletContext();
//2.使用ServletContext对象完成数据共享
sc.setAttribute(String name,Object value);
sc.getAttribute(String name);//返回Object对象类型数据
//3.获取项目中web.xml中的全局配置数据
sc.getInitParameter(String name);//返回String类型数据
//4.获取项目根的根路径信息
sc.getRealPath();
功能:
- 获取MIME类型:在互联网通信过程中定义的一种文件数据类型;
格式:大类型/小类型 text/html;
方法:String getMinmeType(String file); - 域对象:共享数据;所有用户共享数据;
- setAttribute(String name, Object value);
- getAttribute(String name);
- removeAttribute(String name);
- 获取文件的真实(服务器)路径;
- String getRealPath(String path);
文件下载
设置请求头信息:
- setHeader(“content-disposition”, “attachment;filename=xxx”);
setHeader(“content-type”, this.getServletContext().getMinmeType(filename));
- HTTP传输数据类型:ContentType;
- 这里要在响应头中设置HTTP传输数据的类型MIME为文件对应的类型;
注意:文件名的中文问题要根据浏览器版本信息设置对应的文件编码方式;
ServletConfig
ServletConfig对象是Servlet的专属对象(域对象).
问题:
如何获取在web.xml中给每个Servlet单独配置的数据?
解决:
使用ServletConfig对象
使用:
获取ServletConfig对象
ServletConfig sc = this.getServletConfig();
获取web.xml中的配置数据
String value = sc.getInitParameter("name")
Web.xml文件使用总结
作用:
存储项目相关的配置信息,保护Servlet。解耦一些数据对程序的依赖。
使用位置:
每个Web 项目中;
Tomcat服务器中(在服务器conf目录下)
区别:
Web项目下的web.xml文件为局部配置,针对本项目的配置;
Tomcat下的web.xml文件为全局配置,配置公共信息;
内容(核心组件)
全局上下文配置(全局配置参数)
Servlet配置
过滤器配置
监听器配置
加载顺序:
Web容器会按ServletContext -> context-param -> listener -> filter -> servlet这个顺序加载组件,这些元素可配置在web.xml文件中的任意位置。
在服务器启动时完成加载。
server.xml
问题:
浏览器发起请求后,服务器根据请求在webapps目录下调用对应的的Servlet进行请求处理。那么为什么是webapps目录,难道不能是其他的文件吗?
解决:
了解server.xml文件的配置信息
server.xml文件的核心组件
<Server>
<Service>
<Connector/>
<Connector/>
<Engine>
<Host>
<Context/>
</Host>
</Engine>
</Service>
</Server>
热部署
<Context path="/Pet" reloadable="true" docBase="F:/PetWebroot"/>