前言
简单的逻辑的处理。此次分析的是Servlet对HTTP请求的处理和对表单的处理。
下面HTTP的通信机制参考此篇文章:
http://www.cnblogs.com/yin-jingyu/archive/2011/08/01/2123548.html
HTTP通信机制
在前面的学习中知道HTTP是一套网络通信协议,而且它是一种无状态的协议。这里无状态的
含义是指客户端web浏览器和web服务器之间不需要建立持久的连接,这意味着当一个客户端向
服务器发出请求(HttpRequest),然后web服务器返回响应(HttpResponse)之后连接就关闭了,
在web服务器上不保留连接的信息。
HTTP协议遵循请求(Request)/应答(Response)模型,浏览器向服务器发送请求,服务器处理
请求并返回适当的应答。其一次连接被构造成一次请求和应答。
HTTP通信过程
在完整的一次请求、应答模式中HTTP通信的过程为以下七个步骤:
1、建立TCP连接
在HTTP协议开始工作之前,浏览器和服务器首先需要建立连接,该连接是通过TCP来完成的
2、浏览器向服务器发送请求指令
TCP连接建立了以后,浏览器就可以向服务器发送请求指令了。
常见的位POST和GET
3、浏览器发送请求头消息
浏览器发送请求命令之后,还要以头消息的形式向服务器发送一些别的信息,之后浏览器发送
一行空白行来通知服务器其已经结束了头信息的发送。
4、Web服务器响应
浏览器发送请求后进行一些相关逻辑的处理之后,服务器会向客户端浏览器返回应答。
例如:HTTP/1.1 200 OK 版本号+状态码
5、web服务器发送应答头信息
如同客户端一样,服务器应答也会想用户发送关于他自己的数据和被请求的文档信息。
6、web服务器向浏览器发送数据
向浏览器发送头信息,同样以空白行来表示头信息的发送结束。之后以Content-type应答
头信息所描述的格式发送实际的数据。
7、web服务器关闭TCP连接
当实际的数据发送完毕之后,Web服务器关闭TCP连接。不过服务器或者浏览器头信息
加入了Connection:keep-alive。TCP连接在数据发送完毕之后仍然保持的是打开状态。
缩短了下一次连接建立的时间,节约了网络带宽。
HTTP请求格式
HTTP请求信息由三部分组成:
请求方法URI协议/版本、请求头(Request Header)、正文
请求方法、URI、协议
HTTP/1.1 表示的是HTTP一些的版本,GET表示请求的方法,/sample.jsp表示资源URI。
在Intenet应用中常用的请求方法是GET和POST,当然还有其他的一些方法例如HEAD、PUT
URI完整的指定了要访问的网络资源,一般情况下只需要给出相对于服务器根目录的相对目录
即可。
上述中GET方法和POST方法由很大的区别,笔者会找个时间做一个总结。
请求头信息
以一行空信息为结束标志,请求头信息包含了一些客户端环境信息和一些正文信息。
请求正文
请求正文包含客户端提交的查询字符串的信息。一般情况下查询字符串信息是通过表单
传递给服务器,进行一些逻辑的处理,例如登录,注册等功能。
Servlet处理HTTP请求
了解了HTTP协议和HTTP请求的相关内容,我们可能会思考一个问题:Servlet中如何获取
HTTP请求信息来实现相关的业务逻辑呢?
接下来笔者将实际进行一下演示,来说明Servlet对HTTP请求的处理。
阅读源码可以知道HTTP请求是封装在HttpServletRequest对象中的。
不过这里我们会发现HttpServletRequest是一个接口,是不能直接实例化的,不过根据Java
的多态性质我们不难猜想到,具体实例化的肯定是实现此接口的子类,不过我们如何知道是哪
个类呢?(其实这里实例化的是Tomcat容器里面的类)
利用反射嘛,合理的运用反射在一些框架的学习中是十分有必要的。
class org.apache.catalina.connector.RequestFacade
这里是笔者通过反射得到的结果,具体的类在Tomcat容器中,对于Tomcat的学习笔者
有时间的时候会进行下去的。
我们现在知道HttpServletRequest封装了HTTP请求的相关信息,这些信息我们如何获取呢?
读者可以去查阅其源码。这里笔者给出一些比较常用的方法。
请求信息的获取
getHeader(name):返回指定的请求头的信息。
............
请求方法、URI信息的获取
getMethod():获取HTTP请求的方法。
getContextPath();获取请求URI资源的上下文路径
getServletPath();获取Servlet的映射路径
请求正文信息的获取
getPrarameter(parameterName)
............................................................
请求派发
这里Tomcat在实现了对HTTP请求的封装之后,还提供了请求派发的功能:每个客户的请求
可以传递给多个Servlet、web应用程序中的其他资源。整个的过程是在服务器端完成的,没有
任何客户端的参与不需要在客户端浏览器和服务器之间传递什么特殊的信息。
研究其源码可以发现其是借助于RequestDispatcher对象来实现的。
需要注意的是RequestDispatcher提供了两种派发的方式:
include、forward();两者的区别在于forward()方法只会输出后面页面的内容,而include()
方法两个页面都会输出。
实例源码演示
package com.kiritor.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class HelloServlet */ public class HelloServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public HelloServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println(request.getMethod()); System.out.println(request.getContextPath()); System.out.println(request.getHeader("User-Agent")); System.out.println(request.getParameter("username")); } }
这里我们直接看输出结果吧:
至于其他的方法,笔者这里就不多讲了,读者自己去看源码,写实例尝试吧。
之后一篇文章将会就HTTP响应,以及Servlet如何处理HTTP的响应做一些总结、学习。
OK,这篇文章就到这儿了!
转载于:https://blog.51cto.com/kiritor/1226722