Java Web 开发必须了解的 HTTP 知识点和 Servlet 之间对应关系

红薯 发布于 2013/06/20 11:45
阅读 4K+
收藏 86

之前写的一篇文章:初学 Java Web 开发,请远离各种框架,从 Servlet 开发。今天想说说 Web 开发中常见的知识点和一些经常要用到的功能处理方法。

有很多人认为 Web 开发无非就是了解一些框架,做做页面,如果只是这样的话,就会一直停留在很低的水平,不断干重复的工作,加班累到吐血。之前我们是从 Servlet 讲起,今天需要更深入一步,进入Web的底层协议 —— HTTP。

每个人都会上网浏览网页,作为开发者,我们不光要会浏览网页,还得清楚的知道我们每浏览一个网页,计算机和网站各做了什么工作。以开源中国为例,当我们在浏览器地址栏中输入 http://www.oschina.net 时,你知道的,http://www.oschina.net 这一长串字母叫做 URL (Uniform Resource Locator 统一资源定位符)。下面我们通过 OSC 上一个 URL 来说明它的内容:

http://www.oschina.net[:80]/project/tag/127/webframework?lang=0&os=0&sort=time

当服务器接收到这个 URL 请求时,你可以通过 HttpServletRequest 这个类的方法来获取该 URL 中任意一部分的内容:

request.getSchema() => http
request.getServerName() => www.oschina.net
request.getServerPort() => 80
request.getRequestURI() => /project/tag/127/webframework
request.getParameter() 用来获取请求参数的值

当你需要自己做一个框架,你需要了解这些信息。

OK,这个 URL 是我们可见的,但浏览器在发送这个 URL 请求到网站服务器时,还包含了一些我们不可见的信息。你可以借助 Chrome 提供的开发者工具来查看这些不可见信息,方法如下:

1. 打开 Chrome,按 F12 启用开发者工具
2. 在地址栏中输入上述网址(不包括[:80])
3. 在 Network 面板中找到相应 URL 点击后可以看到如下图所示的信息:

包括请求的 URL 地址,请求方法 GET ,服务器返回的状态码是 200 表示成功。而接下来的 Request Headers 就是我们刚才说的那些不可见的信息。

首先可以通过 request.getMethod() 来判断是 GET 还是其他方法,如 POST/PUT/DELETE/HEAD 等。

Request Headers 所有信息都可以通过 request.getHeader(name) 方法来获取,其中 Cookie 还提供了 request.getCookies() 方法更方便的读取。

细心一点的你可能还会发现,其实我们前面提到的 request.getServerName() 相当于是 request.getHeader("Host") 。如果浏览器的请求中不包含 Host 这样一个头信息,那么你是获取不到 ServerName 的,或者获取到的只是 IP 地址。

如果你想知道客户端所在的 IP 地址(这个不是 HTTP 协议范畴的)可以通过 request.getRemoteAddr() 方法来获取。但是在一些使用了类似 Nginx+Tomcat 这样的架构中,获取客户端所在的 IP 地址需要做一些变化,详细的方法参考 OSChina 的 RequestUtils 的 getRemoteAddr 方法。

如果你想知道用户使用什么浏览器,Request Headers 里的 User-Agent 就是你想要的。

关于 POST

浏览器的每个 URL 请求都包含了 Head 和 Body 两块内容,Head 就是前面提到的 Request Headers,Body 就是客户端要向服务器端传输的数据。使用 GET 方法时 Body 为空。

一般我们在浏览器中输入某个 URL 访问网页,使用的是 HTTP 里的 GET 方法。而很多页面中的表单提交会用到 POST 方法。

POST 方法和 GET 方法最大的不同是在参数的处理上,使用 POST 时参数是通过 body 的方式传递,因为它所能传递的参数的大小只受限于服务器端的限制。而 GET 的参数是在 URL 中传输的,长度受限与不同浏览器本身的限制,而且每个浏览器限制有所不同,一般也就是1K 左右。

不过使用 POST 时的 URL 也可以带参数,例如可以 POST 到 http://www.oschina.net/?name=红薯 这样的 URL 地址。

关于 Session

我还想再次说说 Session,经常面试的时候问答这样的问题,多数人都知道怎么用,但谈及原理很多人就晕了。请看这篇文章的第5节。

HTTP状态码

当浏览器发送请求到服务器,服务器处理结束后会返回三部分内容:状态码,响应头,响应实体内容。这里有关于所有 HTTP 状态码的详细说明。一般 2xx 表示 OK,3xx 表示状态变化,4xx 表示客户端原因导致的一些错误,5xx 表示服务器端原因导致的错误。

在写服务器端程序,可以通过 response.sendError(xxx) 来返回不同的错误码,使用 sendRedirect 来做一些页面的重定向。

页面重定向

HTTP 协议中规定了两种重定向状态码,分别是 301 和 302。如果我们用 sendRedirect 方法进行页面重定向,那么使用的是 302 状态码。Servlet 没有关于 301 错误码的对应方法,你可以使用 sendError(301) 来自行处理,不过在 sendError(301) 之前必须设定响应 Header:Location: <新的URL 地址>。

响应内容

使用前面提到的方法也可以看到 HTTP 响应头信息,如下图所示:

或者如果在 Linux 下可以通过 curl 命令来查看这个信息,如:

[root@R710 oschina]# curl -I http://git.oschina.net/
HTTP/1.1 200 OK
Server: Tengine
Date: Thu, 20 Jun 2013 03:41:09 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Status: 200 OK
X-XSS-Protection: 1; mode=block
X-UA-Compatible: IE=Edge,chrome=1
ETag: "10e2591ff8197084df5bdea9cdfea634"
Cache-Control: max-age=0, private, must-revalidate
Set-Cookie: git_osc_session=BAh73Npb25faWQGOgZFRkkiJTYy; path=/; HttpOnly
X-Request-Id: 74570554af95e222741f3749f33abfdd
X-Runtime: 0.016512
X-Rack-Cache: miss
从这里可以获取很多关于网站服务器的信息,例如所用的 Web 服务器类型之类的。


而真正在浏览器上显示的HTML网页内容是在响应的Body中传送的。

这些知识你不一定非得有实际的工作经验才能学,平时自己写个小应用都可以来进行演示。等完全弄明白这些知识点再去学各种框架才是正道。

以上这些内容是我认为一个使用Java开发Web应用的初学者必须要具备的知识点,肯定有不少遗漏的请大家帮忙补充下。

加载中
1
james_you
james_you

request.getHeader(name) 能拿到 HTTP/1.1 这个信息吗?或者说把 HTTP/1.1 改成 HTTP/1.0

因为之前开发用hessian给 PHP调java服务时,拿不到对象,大概原因是因为 HTTP/1.1 传输是分块的,对象太大了,没有接收完。

james_you
james_you
回复 @明月照大江 : 是的,可以调整吗?
明月照大江
明月照大江
分块传输,是http 1.1协议中的chunk 决定的,位于 首部字段中
james_you
james_you
或者说是 服务器里面设定的。
0
布谷鸟
布谷鸟
老大,啥时候搞个高手问答,让 @蟋蟀哥哥 过来讲一下web的安全与防护捏?
布谷鸟
布谷鸟
回复 @蟋蟀哥哥 : 这个已经很有一说了哦,好像看到过你在哪儿贴过一个扫描工具的截图,还有什么xss,cookie之类你博客的文章我都看过,学不了少,还有木有其它的门门道道也适当的抖出来点儿呗。。
蟋蟀哥哥
蟋蟀哥哥
回复 @布谷鸟 : WEB通用漏洞,不是Java特定的。
布谷鸟
布谷鸟
回复 @蟋蟀哥哥 : 可是你还是强奸过红薯。。
蟋蟀哥哥
蟋蟀哥哥
我不了解java。。sorry
红薯
红薯
那你要问 @蟋蟀哥哥
0
渔樵耕读
渔樵耕读

哈哈 突然联想到 红薯好像祥林嫂 看到每个新手问框架的问题

就会走过去幽幽的说“先学好Servlet!”

PS 我不会框架 只会Servlet Jsp j2se~

0
Credo-Zhao
Credo-Zhao

@红薯 老大,结合你的文章再推荐大家去看看 HTTP权威指南和服务器的servlet实现的源码.

其实可以搞个推荐图书的区域.大家可以推荐一些书籍.链接可以链接到京东的图书.可以跟京东说下嘛,多多少少算点广告费.蚊子再小也是肉嘛.而且最主要也方便大家的学习.

反正也就几个页面.

0
chape
chape
下一篇应该是tcp/ip了
0
明月照大江
明月照大江
学好基础这些没那么难理解吧
0
景愿
景愿
红薯一直在推广servlet思想,对于那些死认框架的同学,就让他们干个两年,苦了之后才会回过来思考,现在说什么都是“我要学框架”! 是吧
0
loki_lan
loki_lan
很好很强大!
0
罪恶的花生
罪恶的花生
飞机上也能发文章,牛~
0
hlevel
hlevel
老大没讲缓存之类的客户端缓存,和 服务器缓存。。
返回顶部
顶部