万丈高楼平地起,但是高楼结实不结实,是靠一块块砖垒起来或一根根钢铁架起来的,关于java的web应用开发,servlet就是那块砖或者那根钢铁。今天就和大伙聊聊web应用开发基础。从web应用协议、web服务器容器及httpservlet类、servlet应用实例几个方面分别介绍。

      一、http协议简介

我们经常用浏览器访问某个网站,查询某些信息、登录办公OA、处理行业应用等各种web应用,在浏览器和服务器之间通信用的是http协议,就像任何人交流用语言一样,设备和设备之间交流也需要约定的“语言”,它就是协议,而web应用的客户端和服务器之间用http或https。

1、HTTP简介                          
    1)HTTP协议,即超文本传输协议(Hypertext transfer protocol)。是一种详细规定了浏览器和万维网(WWW = World Wide Web)服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。
    2)HTTP协议作为TCP/IP模型中应用层的协议也不例外。HTTP协议通常承载于TCP协议之上,有时也承载于TLS或SSL协议层之上,这个时候,就成了我们常说的HTTPS。如下图:

3)HTTP是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型。HTTP是一个无状态的协议。
    4)HTTP默认的端口号为80,HTTPS的端口号为443。
    5)浏览网页是HTTP的主要应用,但是这并不代表HTTP就只能应用于网页的浏览。HTTP是一种协议,只要通信的双方都遵守这个协议,HTTP就能有用武之地。比如咱们常用的QQ,迅雷这些软件,都会使用HTTP协议(还包括其他的协议)。

2、HTTP特点                        
    1)简单快速:客户向服务器请求服务时,只需传送请求方法和路径。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
    2)灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
    3)HTTP 0.9和1.0使用非持续连接:限制每次连接只处理一个请求,服务器处理完客户的请求,并收到客户的应答后,即断开连接。HTTP 1.1使用持续连接:不必为每个web对象创建一个新的连接,一个连接可以传送多个对象,采用这种方式可以节省传输时间。
    4)无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
    5)支持B/S及C/S模式。

3、HTTP工作流程                  
    一次HTTP操作称为一个事务,其工作过程可分为四步:
    1)首先客户机与服务器需要建立连接。只要单击某个超级链接,HTTP的工作开始。
    2)建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。
    3)服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。
    4)客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上,然后客户机与服务器断开连接。
    如果在以上过程中的某一步出现错误,那么产生错误的信息将返回到客户端,有显示屏输出。对于用户来说,这些过程是由HTTP自己完成的,用户只要用鼠标点击,等待信息显示就可以了。

4、HTTP之请求消息Request 
    客户端发送一个HTTP请求到服务器的请求消息包括以下格式:
    请求行、请求头部、空行和请求数据四个部分组成。
    1)Get请求例子

第一部分:请求行,用来说明请求类型,要访问的资源以及所使用的HTTP版本.
GET说明请求类型为GET,[/562f25980001b1b106000338.jpg]为要访问的资源,该行的最后一部分说明使用的是HTTP1.1版本。
第二部分:请求头部,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息
从第二行起为请求头部,HOST将指出请求的目的地.User-Agent,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础.该信息由你的浏览器来定义,并且在每个请求中自动发送等等
第三部分:空行,请求头部后面的空行是必须的
即使第四部分的请求数据为空,也必须有空行。
第四部分:请求数据也叫主体,可以添加任意的其他数据。
这个例子的请求数据为空。

2)POST请求例子

第一部分:请求行,第一行明了是post请求,以及http1.1版本。
第二部分:请求头部,第二行至第六行。
第三部分:空行,第七行的空行。
第四部分:请求数据,第八行。

5、HTTP之响应消息Response
一般情况下,服务器接收并处理客户端发过来的请求后会返回一个HTTP的响应消息。
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。

第一部分:状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。
第一行为状态行,(HTTP/1.1)表明HTTP版本为1.1版本,状态码为200,状态消息为(ok)
第二部分:消息报头,用来说明客户端要使用的一些附加信息
第二行和第三行和第四行为消息报头,
Date:生成响应的日期和时间;Content-Type:指定了MIME类型的HTML(text/html),编码类型是ISO-8859-1
第三部分:空行,消息报头后面的空行是必须的
第四部分:响应正文,服务器返回给客户端的文本信息。
空行后面的html部分为响应正文。

6、HTTP之状态码                   
状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:
1xx:指示信息--表示请求已接收,继续处理
2xx:成功--表示请求已被成功接收、理解、接受
3xx:重定向--要完成请求必须进行更进一步的操作
4xx:客户端错误--请求有语法错误或请求无法实现
5xx:服务器端错误--服务器未能实现合法的请求
常见状态码:

7、HTTP请求方法                  
根据HTTP标准,HTTP请求可以使用多种请求方法。
HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。
HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。

8、HTTP工作原理                    
    HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。
以下是 HTTP 请求/响应的步骤:
    1)客户端连接到Web服务器
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,http://www.oakcms.cn。
    2)发送HTTP请求
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
    3)服务器接受请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
    4)释放连接TCP连接
若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
    5)客户端浏览器解析HTML内容
客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。

9、GET和POST的区别      
    1)GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的数据放在HTTP包的Body中.
    2)GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
    3)GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值。
    4)GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码.

二、Servlet工作原理和过程

1、前言
    Java Servlet技术简称Servlet技术,是Java开发Web应用的底层技术。由Sun公司于1996年发布,用来代替CGI——当时生成Web动态内容的主流技术。官方文档对Servlet的概述,请参考《Servlet的概述》。

2、关键词
Servlet
Servlet是JavaEE规范的一种,主要是为了扩展Java作为Web服务的功能。为了方便第三方准守这种规范,Sun公司(现在Oracle公司)提供了一系列相关的接口,即Servlet API。
Servlet应用
直接或间接实现了Servlet接口并且需要运行在Servlet容器中的Java程序,主要用来生成动态的Web页面。Servlet应用不能独立于运行,必须被部署到Servlet容器。
Servlet容器
Servlet容器(Servlet引擎)是Web服务器或应用程序服务器的一部分,用于在发送的请求和响应之上提供网络服务,解码基于MIME的请求,格式化基于MIME的响应,即Servlet容器用来接收客户端请求,处理协议、请求内容等,初始化Servlet实例(只需要第一次初始化)并调用Servlet应用的对应方法,然后Servlet应用返回处理结果,经Servlet容器再返回到用户客户端。
Tomcat容器
Tomcat容器,又叫应用服务器,也有人称之为Servlet容器。其实,本质上,Tomcat容器具有Servlet容器的功能,是Servlet容器的一种开源实现,但是它又不仅仅只是Servlet容器。

3、Servlet API的包结构
    相关文档可以参考《Servlet 3.0 API 》。通过文档我们可以知道,在Servlet规范中,一种有4个java包,分别是:
javax.servlet
该java包下面主要包含了定义了Servlet和Servlet容器之间契约的类和接口。
javax.servlet.annotation
Servlet体系中定义的注解。包括了Servlet、Filter、Listener等注解。
javax.servlet.descriptor
包含为Web应用的配置信息提供编程式访问的类型,即提供了对通过<jsp-config> 、<jsp-property-group> 、<taglib> 等标签进行的配置信息的访问方式。
javax.servlet.http
该包下的类,可以说是在javax.servlet包中类和接口的契约的基础上,又基于http协议的进一步的延伸,即定义了Http Servlet和Servlet容器之间契约的类和接口。
从项目引入的jar包可以直接看出有哪些类和接口,如下图:

4、Servlet 类结构

在javax.servlet包下的主要类型:

在javax.servlet.http包下的主要类型:

在javax.servlet.descriptor包下的接口和类:

在javax.servlet.annotation包下的注解类:

5、Servlet接口
    Servlet接口是Servlet技术的核心,所有的Servlet类都必须直接或者间接实现Servlet接口。Servlet接口定义了Servlet类与Servlet容器之间的契约,即通过Servlet接口约定了当Servlet容器把Servlet类的实例加载到容器后,如何调用Servlet实例的方法。

Servlet接口定义的方法

package javax.servlet;import java.io.IOException;public interface Servlet {public void init(ServletConfig config) throws ServletException;public ServletConfig getServletConfig();public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;public String getServletInfo();public void destroy();
}

Servlet生命周期的方法:
    在Servlet接口的方法中,init( ),service( ),destroy( )是Servlet生命周期的方法。代表了Servlet从“出生”到“工作”再到“死亡 ”的过程,在后面会具体的分析Servlet的工作过程和工作原理。

剩下的两个方法,作用分别如下:

getServletInfo(),这个方法会返回Servlet的一段描述,可以返回一段字符串。
    getServletConfig(),这个方法会返回由Servlet容器传给init()方法的ServletConfig对象。

6、Servlet的工作过程和原理
  Servlet工作过程中,涉及到了客户端(浏览器)、Servlet容器、Servlet应用三种角色。大致过程如下所示:

首先,由客户端发起请求。
    然后,Servlet容器接收到客户端的请求,解析请求协议和数据,如果servlet程序还没有被加载,就会执行加载过程并调用service()方法,否则直接调用service()方法。
    其中,加载Servlet程序的过程:根据Servlet容器与Servlet程序间的契约,当有请求过来时,如果Servlet程序还没有被载入Servlet容器中,这个时候Servlet容器就会通过调用init()方法将Servlet类载入内存,并产生Servlet实例。在调用init()方法的时候,Servlet容器会传入一个ServletConfig对象进来从而对Servlet对象进行初始化。该过程只会被执行一次,即在一个应用程序中,每类Servlet程序只能有一个实例。其中,在ServletConfig对象中还隐藏一个ServletContext实例对象,这个ServletContext实例对象就表示了Servlet程序在容器中的上下文环境。
    service()方法执行的过程:首先由Servlet容器解析请求参数并封装成一个ServletRequest和ServletResponse对象。其中,ServletRequest中封装了当前的Http请求,开发者可以操作ServletRequest对象获取用户的请求数据;ServletResponse封装了当前用户的Http响应,开发者可以操作ServletResponse对象把响应内容发回给用户。Servlet容器把ServletRequest和ServletResponse作为参数传递给了service()方法,通过执行service()方法,实现响应的逻辑,并通过ServletResponse对象返回内容到客户端。
    最后,如果关闭Servlet容器时,这个时候,Servlet容器就会根据契约,调用destroy()方法,该方法一般都用来编写一些释放资源的逻辑。

7、Servlet的工作过程涉及到的实例
    根据前面分析的Servlet的工作过程,我们可以了解到,在这个过程中用到了以下几类对象:
ServletRequest 封装了当前的Http请求,开发者可以操作ServletRequest对象获取用户的请求数据
ServletResponse 封装了当前用户的Http响应,开发者可以操作ServletResponse对象把响应内容发回给用户
ServletConfig 封装了初始化Serlvet程序需要的信息,同时还保存了一个ServletContext实例的引用。
ServletContext 封装了Servlet程序在Servlet容器中的上下文环境

此段仍然只是介绍了servlet浅层次的内容,抽空再来详细讲解从一个网址如何调用了web容器以及启动servlet容器的全过程。

三、Servlet应用实例

为方便理解,用极简的代码来展示应用过程,以降低入门门槛。

1、用idea创建一个maven空项目,建立如下目录结构

在pom.xml中添加servlet依赖,版本使用4.0.1

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>QinMing</groupId><artifactId>servletStudy</artifactId><version>1.0</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency></dependencies></project>

2、编写一个web前端html文件:

test1.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>servlet test1</title>
</head>
<body><!-- http://127.0.0.1:8080/servlet/test1.do -->
<form name="form1" action="test1.do" method="post"><input type="submit" value="servlet1测试">
</form><br/>
<br/><form name="form2" action="test2.do" method="post"><input type="submit" value="servlet2测试">
</form></body>
</html>

3、实现一个servlet,采用xml配置方式:

Servlet1.java

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;public class Servlet1 extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {//设置响应内容类型response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();String title = "servlet test1";String docType = "<!DOCTYPE html>\n";out.println(docType +"<html>\n" +"<head><title>" + title + "</title></head>\n" +"<body bgcolor=\"#f0f0f0\">\n" +"<h1 align=\"center\">" + title + " success</h1>\n" +"</body>\n" +"</html>\n");}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {doGet(request, response);}}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"><servlet><servlet-name>servlet1</servlet-name><servlet-class>Servlet1</servlet-class></servlet><servlet-mapping><servlet-name>servlet1</servlet-name><url-pattern>/test1.do</url-pattern></servlet-mapping></web-app>

4、再实现一个servlet,采用注解配置方式

Servlet2.java

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;//servlet3.0之后可以不用在web.xml中配置映射关系,用注解方式代替
//注解方式和web.xml配置方式可以同时使用,某个servlet用两种方式都配置时,web.xml方式优先级高,会覆盖注解方式@WebServlet(name="Servlet2",urlPatterns={"/test2.do"})public class Servlet2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {//设置响应内容类型response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();String title = "servlet test2";String docType = "<!DOCTYPE html>\n";out.println(docType +"<html>\n" +"<head><title>" + title + "</title></head>\n" +"<body bgcolor=\"#f0f0f0\">\n" +"<h1 align=\"center\">" + title + " success</h1>\n" +"</body>\n" +"</html>\n");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {doGet(request, response);}}

5、编译后把Servlet1.class、Servlet2.class文件拷贝到web应用目录下WEB-INF\classes目录下,然后到浏览器输入http://127.0.0.1:8080/servlet/test1.html ,测试servlet应用。

这里用的是tomcatweb服务器以及servlet容器,请确保tomcat服务已正常启动。

一步一步学java(8):一文彻底搞懂servlet、httpservlet以及http协议相关推荐

  1. JAVA每个初学者都应该搞懂的问题 还可以比较基础

    还可以比较基础 转自http://blog.csdn.net/devillyd/article/details/2486520 对于这个系列里的问题,每个学Java的人都应该搞懂.当然,如果只是学Ja ...

  2. java写一个外网访问的接口_【JAVA基础】一个案例搞懂类、对象、重载、封装、继承、多态、覆盖、抽象和接口概念及区别(中篇)...

    0 前言 初学JAVA时,总会对一些概念一知半解,相互混淆,不明其设计的用意,如类.对象.重载.封装.继承.多态.覆盖.抽象类.接口概念.为便于理解和巩固,本文将基于一个案例及其变形,展现各个概念的定 ...

  3. 学习java多线程,这必须搞懂的这几个概念

    转载自 学习java多线程,这必须搞懂的这几个概念,很重要. 同步和异步 同步,Synchronous,即调用方法开始,一旦调用就必须等待方法执行完返回才能继续下面的操作. 举个例子,你去银行ATM取 ...

  4. 教妹学Java(二十二):来吧,一文彻底搞懂Java命名约定

    你好呀,我是沉默王二,是<Web 全栈开发进阶之路>的作者,CSDN 博客之星.<教妹学 Java>是一套非常有趣的付费专栏,除了继续保持幽默风趣的行风风格,我还力求把每一个知 ...

  5. java do po dto_彻底搞懂DAO,PO,BO,DTO,VO,DO

    原标题:彻底搞懂DAO,PO,BO,DTO,VO,DO 有干货,就分享,点上面的蓝字"测试之道"关注. 上才艺,哦不,上图... Entity 最常用实体类,基本和数据表一一对应, ...

  6. Java中的线程池如何实现,一文彻底搞懂

    前言 为什么要用线程池一键获取线程相关资料,还可获取最新java面试真题库 在 HotSpot VM 的线程模型中,Java 线程被一对一映射为内核线程. Java 在使用线程执行程序时,需要调用操作 ...

  7. python虽然火为什么工作少_我的心酸求职之路:如果可以,去学Java、C,不要搞Python...

    很多人之所以从事Python,是因为很不爽PHP的语法,虽然PHP被称为世界上最好的编程语言.于是为了这个原因,付出了沉重的代价,失业了好几回. 身边有些人时不时总是会问我一些Python的技术问题, ...

  8. Java 多态 ——一个案例 彻底搞懂它

    最近,发现基础真的hin重要.比如,Java中多态的特性,在学习中就是很难懂,比较抽象的概念.学的时候就犯糊涂,但日后会发现,基础在日常工作的理解中占有重要的角色. 下面,我将用一个代码实例,回忆和巩 ...

  9. java队列_如何彻底搞懂 Java 数据结构?CSDN 博文精选

    作者 | 张振华.Jack 责编 | 郭芮 出品 | CSDN 博客 本文和大家一起来重温<Java数据结构>经典之作. Java数据结构 要理解Java数据结构,必须能清楚何为数据结构? ...

最新文章

  1. 利用 VMWare 搭建随机拓扑网络
  2. 中国半导体最强助攻来了!十年免税、上下游一揽子扶持,明确「集成电路」为一级学科...
  3. 【Eclipse】推荐UML插件Green UML、AmaterasUML
  4. 服务器管理安全(上)
  5. HDU - 5008 Boring String Problem(后缀数组+二分)
  6. 20190423面试记录
  7. 玉置成実(Nami Tamaki) -《もしも愿いが…》单曲[MP3]
  8. 十八般武艺玩转GaussDB(DWS)性能调优(二):坏味道SQL识别
  9. 2017.10.22 诸神眷顾的幻想乡 失败总结
  10. 云端服务器怎么维护,云端服务器怎么维护
  11. 配置jupyter notebook到conda env虚拟环境里可运行
  12. FAL风控培训「六大场景下,模型分数如何应用?」
  13. 有哪些产品被阿里巴巴收购导致质量下滑?
  14. Joomla源代码解析(十九) JController
  15. C#自定义规则对比两个集合的对象是否相等
  16. Node JS环境设置– Node.js安装
  17. Labview连接mysql进行仿真
  18. Error occurred during initialization of VM Could not reserve enough space for object heap
  19. 邮票的制作(1.主要画笔工具2.钢笔工具)
  20. docx文件是什么?如何打开后缀名.docx格式的word2007文件?

热门文章

  1. Servlet六(监听器)
  2. qt中如何由Double类型变为QString类型以及chop()的使用
  3. Alexa工具查询网站流量
  4. 现代修谱,如何看待支系单飞的现象?
  5. 区块链技术之数字签名简介
  6. ThinkPad T430s 摄像头黑屏解决
  7. 怎么截取精彩视频片段 视频分割软件哪个好
  8. python爬取英雄联盟所有皮肤_用Python爬取英雄联盟(lol)全部皮肤
  9. 四角号码查询器 第3版 发布
  10. docker 设置国内加速