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的三种方式
- 定一个类实现javax.servlet.Servlet接口
- 定义一个类继承javax.servet.GenericServlet类
- 定义一个类继承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。
在以下几种情况下,缓冲区内的数据会被提交给客户,即数据被发送到客户端:
- 当缓冲区内的数据已满时,ServletOutPutStream或PrintWriter会自动把缓冲区内的数据发送给客户端,并且清空缓冲区;
- Servlet调用ServletResponse对象的flushBuffer方法;
- 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文件中相应
已知实现类
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中,直接在
getServletContextName() —— 返回Web应用的名字,即web.xml文件中
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被调用的大致过程