(一)一些基本概念
HTTP是基于Request/Response,属于Stateless的通讯协定
GET请求
一个GET请求的发送范例如下:
Http方法, 请求的url, parameters, http版本 | GET /webApp/loginAction.do?username=admin&password=password HTTP/1.1 |
请求标头 | User-Agent: Mozilla/5.0 (Window; U; Windows NT 6.0; zh; rv: 1.9.0.7) Gecko/2009021910 Firefox/3.0.7 Accept: text/xml, application/xml, image/gif, image/x-bitmap; Accept-language: en, zh ... |
请求参数跟在url后面,以键值对的方式用=号连接,多个参数中间用&隔开
服务器可以从请求标头的内容得到更多的附加信息做回应处理,比如浏览器类型版本以及接受的语言等
对于GET方法来数请求参数会显示在浏览器的网址列上,而且请求参数的长度是受限的,根据各浏览器不同,太大量的资料应选用POST方法
POST请求
一个POST请求的发送范例如下
Http方法, 请求的url, parameters, http版本 | POST /webApp/loginAction.doHTTP/1.1 |
请求标头 | User-Agent: Mozilla/5.0 (Window; U; Windows NT 6.0; zh; rv: 1.9.0.7) Gecko/2009021910 Firefox/3.0.7 Accept: text/xml, application/xml, image/gif, image/x-bitmap; Accept-language: en, zh ... username=admin&password=password |
请求参数被移到请求表头中(message body), 长度不再受限,并且浏览器的地址栏不会出现请求参数的内容。
Servlet的执行概念
Servlet是在容器中执行的,而容器其实也是一个Java程序,运行在服务器的JVM中,以跟服务器通讯。客户端的请求都被交给同一个容器,而容器则会启动一个线程,并决定交由哪个Servlet来处理。如果有多次请求进来就会启动多个线程。这与以前的CGI程序是不同的:对每个请求都会启动单独的CGI程序。相比之下启动线程是更轻量级的,可大幅减轻效能负担。
需要注意的是WEB容器和HTTP服务器是两个概念,WEB容器是一个Java程序,负责载入,管理Servlet。而Tomcat就是一个WEB容器的实现,只是它本身还带有一个HTTP服务器,可以直接启动这个HTTP服务器,然后可以在这上面的WEB容器里部署Serlet。
从Servlet到WEB容器
编写Servlet需要继承javax.servlet.http.HttpServlet,并override doGet(),doPost()等方法。下面是Servlet相关的API类图
可以注意到,与Servlet定义相关的类或接口都定义在javax.servlet这个package下面,而与http定义相关的类和接口都定义在javax.servlet.http这个package中。
以Tomcat容器为例,HttpServlet的service方法中的大致流程如下:
protectedvoid service(HttpServletRequest req, HttpServletResponse res)
{
String method = req.getMethod();
if(method.equals(METHOD_GET))
{
//...
doGet(req, res);
//...
}
if(method.equals(METHOD_POST))
{
//...
doPost();
//...
}
当收到请求时,容器会呼叫Servlet的service方法,可以看到HttpServlet的service方法主要就是判断HTTP请求的方式是GET还是POST,然后再分别呼叫对应的doGet()和doPost()。所以想要针对GET或POST方法进行处理,就需要在继承HttpServlet后重写doGet()和doPost(),而不应该重写service方法。
WEB容器做了什么
当请求来到HTTP服务器的时候,HTTP服务器会将请求转交个WEB容器,而WEB容器会首先为这个请求建立一个HttpServletRequest,并将相关的请求参数信息交给这个对象。同时容器还会建立一个HttpServletResponse对象,作为之后想客户端回应的对象。
接着容器根据web.xml的设定找到对应的处理该请求的servlet,呼叫他的service方法,并将之前建立的HttpServletRequest和HttpServletResponse作为参数传入,而service方法会根据HTTP请求的方式,再呼叫对应的doGet或doPost方法。
然后在doGet方法中,可以使用HttpServletRequest和HttpServletResponse对象,例如使用getParameter方法取得请求参数,用getWriter()方法取得PrintWriter,并进行各项回应处理。
最后容器将HttpServletRequest和HttpServletResponse回收销毁,该次请求回应结束。