Servlet主要相关类核心类 容器调用的过程浅析 servlet解读 怎么调用 Servlet是什么 工作机制

WEB简介

Web项目 是 B/S结构 浏览器/服务器模式的

浏览器发起请求,服务器作出响应

请求的发起和响应使用HTTP协议进行通讯

所谓协议也就是一种固定格式

而Socket是应用层与传输层的一层编程接口,屏蔽了传输层的细节

所以Web项目也就是通过Socket发送HTTP请求和响应的过程

只不过请求是浏览器发出来的 响应是服务器发出来的

针对于JavaWeb项目,动态响应则是Servlet容器通过调用Servlet进行响应

应用程序员所要做的也就只是编写符合Servlet规范的Servlet

一个基本的 请求--响应 调用过程

Servlet规范约定了Servlet容器与Servlet的工作过程以及工作细节

规范的概念 反映到代码里也就是面向接口的编程


Servlet API主要由两个包组成: javax.servlet和javax.servlet.http

在javax.servlet包中定义了Servlet接口及相关的通用接口和类;

在javax.servlet.http包中主要定义了与HTTP协议相关的HttpServlet类,HttpServletRequest接口和HttpServletResponse接口;

Servlet

Servlet是基于Java 技术的web组件,容器托管的,用于生成动态内容。

平台无关的,协议无关的

基于web的访问模式必然是有   /请求/处理/响应/      的过程

Servlet是顶级接口,表示服务端的运行的程序

GenericServlet抽象类为Servlet接口提供了通用实现,想要实现Servlet只需要继承GenericServlet即可,它与任何网络应用层协议无关。

HttpServlet是针对于HTTP请求的Servlet实现

同理HttpRequest HttpResponse 也是针对HTTP协议的

为什么要绕这么多层,是因为Servlet不针对任何具体的协议,是协议独立的

虽然web应用人员基本上都是在使用HTTPServlet但是并不代表他就只是http协议

Servlet接口中的:

public void init(ServletConfig config)
public void service(ServletRequest req, ServletResponse res)
public void destroy();

三个方法是生命周期方法,由容器负责调用

创建servlet的三种方式

  1. 定一个类实现javax.servlet.Servlet接口
  2. 定义一个类继承javax.servet.GenericServlet类
  3. 定义一个类继承javax.servlet.http.HttpServlet类   web应用我们自然基本上都是继承HttpServlet

Servlet的生命周期 由一套定义良好的生命周期规则来约束管理

其中定义了Servlet如何被加载实例化和初始化,处理客户端请求,以及何时结束服务

生命周期方法有:

       void init(ServletConfig);

       void service(ServletRequest,ServletResponse);

       void destroy();

1. 服务器会在Servlet第一次被访问时创建Servlet,或者是在服务器启动时创建Servlet。

如果服务器启动时就创建Servlet,那么还需要在web.xml文件中配置。也就是说默认情况下,Servlet是在第一次被访问时由服务器创建的

2. 而且一个Servlet类型,服务器只创建一个实例对象,当我们再次访问,不在创建 而是直接使用上次创建的实例。

3. 在Servlet被创建后,服务器会马上调用Servlet的void init(ServletConfig)方法。请记住, Servlet出生后马上就会调用init()方法,而且一个Servlet的一生这个方法只会被调用一次

Servlet服务

当服务器每次接收到请求时,都会去调用Servlet的service()方法来处理请求。

服务器接收到一次请求,就会调用service() 方法一次,所以service()方法是会被调用多次的。

正因为如此,所以我们才需要把处理请求的代码写到service()方法中

Servlet销毁

Servlet是不会轻易被销毁的,通常都是在服务器关闭时Servlet才会销毁!

在服务器被关闭时,服务器会去销毁Servlet,在销毁Servlet之前服务器会先去调用Servlet的destroy()方法,

我们可以把例如对某些资源的释放等代码放到destroy()方法中。

小技巧:

GenericServlet实现了init(ServletConfig config)方法

并且自定义了一个init()方法 方法内容为空

我们知道GenericServlet是Servlet的抽象实现类,完成了Servlet的基本实现

如果你想要实现自己的Servlet,一般情况下不至于去直接使用实现Servlet

所以都会继承GenericServlet

在继承的时候如果你还想要有自己的个性化特殊的初始化方法,就可以覆盖这个空的无参数的init()

    public void init(ServletConfig config) throws ServletException {         this.config = config;         this.init();     }
    public void init() throws ServletException {     }

请求

ServletRequest:Servlet.service() 方法的参数,它表示请求对象,它封装了所有与请求相关的数据,它是由服务器创建的

常用方法备注:

getContentLength() —— 返回请求正文的长度,如果请求正文的长度未知,则返回-1;

getContentType() —— 获得请求正文的MIME类型,如果请求正文的类型为止,则返回null;

getInputStream() —— 返回用于读取请求正文的输入流;

getLocalAddr() —— 返回服务端的IP地址;

getLocalName() —— 返回服务端的主机名;

getLocalPort() —— 返回服务端的端口号;

getParameters() —— 根据给定的请求参数名,返回来自客户请求中的匹配的请求参数值;

getProtocal() —— 返回客户端与服务器端通信所用的协议名称及版本号;

getReader() —— 返回用于读取字符串形式的请求正文的BufferReader对象;

getRemoteAddr() —— 返回客户端的IP地址

getRemoteHost() —— 返回客户端的主机名

getRemotePort() —— 返回客户端的端口号

HttpServletRequest接口提供了用于读取HTTP请求中的相关信息的方法:

getContextPath() —— 返回客户端请求方法的Web应用的URL入口,例如,如果客户端访问的URL为http://localhost:8080/myApp/index,那么该方法返回“/myApp”;

getCookies() —— 返回HTTP请求中的所有Cookie;

getHeader(String name) —— 返回HTTP请求头部的特定项;

getHeaderName() —— 返回一个Enumeration对象,它包含了HTTP请求头部的所有项目名;

getMethod() —— 返回HTTP请求方式;

getRequestURL() —— 返回HTTP请求的头部的第一行中的URL;

getQueryString() —— 返回HTTP请求中的查询字符串,即URL中的“?”后面的内容;


响应

常用方法备注:

setCharacterEncoding() —— 设置相应正文的字符编码。响应正文的默认字符编码为ISO-8859-1;

setContentLength() —— 设置响应正文的长度;

setContentType() —— 设置响应正文的MIME类型;

getCharacterEncoding() —— 获得响应正文的字符编码

getContentType() —— 获得响应正文的MIME类型

setBufferSize() —— 设置用于存放响应正文数据的缓冲区的大小

getBufferSize() —— 获得用于存放响应正文数据的缓冲区的大小;

reset() —— 清空缓冲区内的正文数据,并且清空响应状态代码及响应头

resetBuffer() —— 仅仅清空缓冲区的正文数据,不清空响应状态代码及响应头;

flushBuffer() —— 强制性地把缓冲区内的响应正文数据发送到客户端;

isCommitted() —— 返回一个boolean类型的值,如果为true,表示缓冲区内的数据已经提交给客户,即数据已经发送到客户端;

getOutputStream() —— 返回一个ServletOutputStream对象,Servlet用它来输出二进制的正文数据

getWriter() —— 返回一个PrinterWriter对象,Servlet用它来输出字符串形式的正文数据

ServletResponse中响应正文的默认MIME类型是text/plain,即纯文本类型,而HttpServletResponse中响应正文的默认MIME类型为text/html,即HTML文档类型。

为了提高输出数据的效率,ServletOutputStream和PrintWriter首先把数据写到缓冲区内。

当缓冲区内的数据被提交给客户后,ServletResponse的isComitted方法返回true。

在以下几种情况下,缓冲区内的数据会被提交给客户,即数据被发送到客户端:

  1. 当缓冲区内的数据已满时,ServletOutPutStream或PrintWriter会自动把缓冲区内的数据发送给客户端,并且清空缓冲区;
  2. Servlet调用ServletResponse对象的flushBuffer方法;
  3. Servlet调用ServletOutputStream或PrintWriter对象的flush方法或close方法;

如果要设置响应正文的MIME类型和字符编码

必须先调用ServletResponse对象的setContentType()和setCharacterEncoding()方法,然后再调用ServletResponse的getOutputStream()或getWriter()方法

HttpServletResponse接口提供了与HTTP协议相关的一些方法,Servlet可通过这些方法来设置HTTP响应头或向客户端写Cookie。

addHeader() —— 向HTTP响应头中加入一项内容

sendError() —— 向客户端发送一个代表特定错误的HTTP响应状态代码

setHeader() —— 设置HTTP响应头中的一项内容,如果在响应头中已经存在这项内容,则原来的设置被覆盖

setStatus() —— 设置HTTP响应的状态代码

addCookie() —— 向HTTP响应中加入一个Cookie

在HttpServletResponse接口中定义了一些代表HTTP响应状态代码的静态常量。


Servlet容器是调度机器 ,Servlet 是处理器   ,ServletRequest是请求,ServletResponse是响应

假设有一个小饭店,有老板和大厨,大厨就炒菜,老板干其他所有点菜收钱上菜

Servlet容器就好比饭店的服务员

Servlet 就是大厨 就负责炒菜

ServletRequest 就是点菜单

ServletResponse就是装盘的菜

显然:,服务员负责了所有的外围操作,点菜下单到厨房(接收请求),端菜到餐桌(返回响应)

可以看得出来大厨除了炒菜什么都不做

老板做好了所有的外围工作

对于大多数web项目来说 接收到的请求自然就是HTTP请求,响应也是HTTP响应

所以也可以说HttpServlet工作流程就是对HTTP的映射

所以说其实熟悉了HTTP 也就很容易就熟悉了HttpServlet  HttpRequest HttpResponse 中的方法和属性


javax.servlet

Interface ServletConfig

是Servlet的配置信息

servlet容器用于在Servlet初始化时传递信息的Servlet配置对象

一个Servlet对应一个ServletConfig

当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中

通过Servlet接口的init方法可以看得出来,init方法的参数

init方法由Servlet容器调用  Servlet容器将ServletConfig参数传递过来

    public void init(ServletConfig config) throws ServletException;

常用方法备注:

getInitParameter(String name) —— 返回匹配的初始化参数值

getInitParameterNames() —— 返回一个Enumeration对象,里面包含了所有的初始化参数名

getServletContext() —— 返回一个ServletContext对象

getServletName() —— 返回Servlet的名字,即web.xml文件中相应<servlet>元素的<servlet-name>子元素的值;如果没有为servlet配置<servlet-name>子元素,则返回Servlet类的名字

已知实现类

GenericServlet, HttpServlet

也就是说:

HttpServlet类继承了GenericServlet类,而GenericServlet类实现了ServletConfig接口,

因此HttpServlet或GenericServlet类及子类中都可以直接调用ServletConfig接口中的方法。


javax.servlet

Interface ServletContext

定义了servlet用来与servlet容器通信的一组方法,例如,获取文件的MIME类型、分派请求或写入日志文件。

一个web应用一个JVM只有一个Context

对于在其部署描述符中标记为“分布式”的web应用程序,此应用每个虚拟机都将有一个上下文实例

ServletContext对象包含在ServletConfig对象中,ServletConfig是Web服务器在servlet被初始化时,提供给servlet。

所以可以使用:

Servlet.getServletConfig()

ServletConfig.getServletContext() 

获取Context

一个应用一个JVM只有一个Context也就是所有应用共享的

常用方法备注:

ServletContext接口提供的方法可以分为以下几种类型:

用于在web应用范围内存取共享数据的方法

setAttribute(String name, Object object) —— 把一个Java对象与一个属性名绑定,并存入到ServletContext中;

getAttribute() —— 返回指定数姓名的属性值

getAttributeNames() —— 返回一个Enumeration对象,包含所有存放在ServletContext中的属性名

removeAttributes() —— 从ServletContext中删除匹配的属性

访问当前Web应用的资源

getContextPath() —— 返回当前Web应用的URL入口

getInitParameter() —— 返回Web应用范围内的匹配的初始化参数值。在web.xml中,直接在<web-app>根元素下定义的<context-param>元素表示应用范围内的初始化参数

getServletContextName() —— 返回Web应用的名字,即web.xml文件中<display-name>元素的值

getRequestDispatcher() —— 返回一个用于向其他WEB组件转发请求的RequestDispatcher对象

访问Servlet容器中的其他WEB应用

访问Servlet容器的相关信息

访问服务器端的文件系统资源

getRealPath() —— 根据参数指定的虚拟路径,返回文件系统中的一个真实的路径

getResources() —— 返回一个映射到参数指定的路径的URL

getResourceAsStream() —— 返回一个用于读取参数指定的文件的输入流

getMimeType() —— 返回参数指定的文件MIME类型

输出日志

log(String msg) —— 向Servlet的日志文件中写日志

log(String message, Throwable throwable) —— 向Servlet的日志文件中写入错误日志,以及异常的堆栈信息


总结:

Servlet容器比如tomcat

负责创建/调用/销毁 Servlet

对于大多数程序员来说需要做的就是编写Servlet类一般继承HTTPServlet就可以了

Web.xml中可以配置ServletContext以及ServletConfig的信息

tomcat 初始化Servlet的时候会将ServletConfig传给Servlet,通过ServletConfig又可以获取到ServletContext

每次的请求时,Servlet容器将请求进行封装ServletRequest,传递给Servlet,我们可以在Servlet中解析请求,根据请求作出相应的响应

响应信息通过ServletResponse传递回去

这就是一个Servlet被调用的大致过程

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT笔记

JavaWeb中web.xml初始化加载顺序

需求说明 做项目时,为了省事,起初把初始化的配置都放在每个类中 static加载,初始化配置一多,就想把它给整理一下,这里使用servlet中的init方法初始...

37880
来自专栏人工智能LeadAI

今天不如来复习下Python基础

01 python是什么? Python是一种解释型语言。这就是说,与C语言和C的衍生语言不同,Python代码在运行之前不需要编译。其他解释型语言还包括PH...

42550
来自专栏别先生

基于jsp+servlet图书管理系统之后台用户信息删除操作

上一篇的博客写的是修改操作,且附有源码和数据库,这篇博客写的是删除操作,附有从头至尾写的代码(详细的注释)和数据库!   此次删除操作的源码和数据库:http:...

402100
来自专栏专注 Java 基础分享

Java EE基础之JSP(二)

     接着上篇文章,我们上篇文章讲到了jsp的基本原理以及和servlet的关系,还介绍了jsp的基本语法部分,本篇文章就继续介绍余下的内容。 编译指令Pa...

18980
来自专栏软件开发

MyBatis学习总结(一)——ORM概要与MyBatis快速入门

程序员应该将核心关注点放在业务上,而不应该将时间过多的浪费在CRUD中,多数的ORM框架都把增加、修改与删除做得非常不错了,然后数据库中查询无疑是使用频次最高、...

20830
来自专栏编程思想之路

WiFiAp探究实录--功能实现与源码分析

Android虐我千百遍,我待Android如初恋。 ——————编辑于2017-08-02——————— wifi热点说的是wifiAp相...

1.7K90
来自专栏一个会写诗的程序员的博客

CAS指令与MESI缓存一致性协议、 “轻量级锁” 与原子操作CAS指令与MESI缓存一致性协议、 “轻量级锁” 与原子操作

CAS指令,在Intel CPU上称为CMPXCHG。最常见的原子操作有Compare and Exchange,Self Increase/Decrease等...

22750
来自专栏北京马哥教育

MongoDB多纬度监控方法详解

一、mongostat工具方法 mongostat是mongdb自带的状态检测工具,在命令行下使用。它会间隔固定时间获取mongodb的当前运行状态,并输出。如...

48250
来自专栏orientlu

FreeRTOS 软定时器实现

考虑平台硬件定时器个数限制的, FreeRTOS 通过一个 Daemon 任务(启动调度器时自动创建)管理软定时器, 满足用户定时需求. Daemon 任务会在...

20220
来自专栏Python

Flask快速入门,知识整理

一、Flask介绍(轻量级的框架,非常快速的就能把程序搭建起来)   Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服...

47090

扫码关注云+社区

领取腾讯云代金券