客户请求的处理:Http请求报头
创建高效servlet的关键之一,就是要了解如何操纵超文本传输协议(HypeText TransferProtocol, HTTP)。
HTTP请求报头不同于前一章的表单数据。表单数据直接来源于用户的输入,对于GET请求,这些数据是URL的一部分,对于POST请求,这些数据在单独的行中。相应的,请求报头由浏览器间接设定,并紧跟在初始的GET和POST请求行之后发送。

请求报头的读取:
HttpServletRequest的getHeader方法,使用报头名称为参数。有返回String,没有返回null。
报头名称对大小写不敏感。
尽管getHeader是读取报头的通用方式,但由于几种报头的应用太普遍,故而HttpServletRequest为它们提供了专门的访问方法:
getCookies
getCookies返回Cookie报头的内容,这些内容经分析后存储在由Cookie对象构成的数组中。
getAuthType和getRemoteUser
getAuthType和getRemoteUser方法对Authorization报头进行拆分,分解成它的各个构成部分。
getContentLength
getContentLength方法返回Content-Length报头的值(int)
getContentType
getContentType返回Content-Type报头的值(string)
getDateHeader和getIntHeader
getDateHeader和getIntHeader饭别读取指定的报头,然后分别将它们转换成Date和int值
getHeaderNames
可以用getHeaderNames方法得到一个Enumeration,枚举当前特定请求中所有的报头名称
getHeaders
大多数情况下,每个报头名称在请求中只出现一次。然而报头偶尔也可能出现多次,每次出现列出各自的值。Accept-Language就是一例子。您可以使用getHeaders获取一个Enumeration,枚举报头每次出现所对应的值
除了查找请求的报头之外,您还可以获取主请求行自身的信息,同样是使用HttpServletRequest提供的方法
getMethod
返回主请求方法
getRequestURI
返回URL中主机和端口之后,但在表单数据之前的部分
getQueryString
返回表单数据
getProtocol
getProtocol方法返回请求行的第三部分,一般为HTTP/1.0或者HTTP/1.1。
了解Http请求报头:
Accept:浏览器能处理的MIME类型。
Accept-Charset: 浏览器使用的字符串
Accept-Encoding
Accept-Language:浏览器使用的语言,如en
Authorization:访问需要用户信息的web页面的时候,用这个报头标识自己身份
Connect:标识浏览器能否处理持续性连接。Keep-Alive表示应该使用持续性连接,close表示使用旧式连接
Content-Length:
Cookie:
Host:URL中的主机名和端口号
if-Modified-Since:这个报头标明,仅当页面在指定日期之后修改的情况下,客户程序才能访问页面。如果没有更新的结果,则返回403.这个选项十分有用,因为使用它,浏览器可以缓存文档,只有他们发生更改时才通过网络重新载入。但是servlet不需要直接处理这个报头。取而代之,他们应该事先getLastModified方法,让系统自动处理修改日期。

使用getLastModified的例子:

package com.zhen.test.o2;

import com.zhen.util.ServletUtilities;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter; /**
* Created by zhen on 2017-10-10.
* Example using servlet initialization and the getLastModified method
*/
public class LottyNumbers extends HttpServlet{
private long modTime;
private int[] numbers = new int[10]; /**
* The init method is called only when the servlet is first loaded, before the first request is processed.
* @throws ServletException
*/
public void init() throws ServletException {
// Round to nearest second (i.e, 1000 milliseconds)
modTime = System.currentTimeMillis()/1000*1000;
for(int i=0; i<numbers.length; i++){
numbers[i] = randomNum();
}
} /** Return the list of numbers that init computed. */
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
String title = "Your Lottery Numbers";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=\"#FDF5F6\">\n" +
"<H1 ALIGN=CENTER>" + title + "</H1>\n" +
"<B> Based ypon extensive research of astro-illogical statistical claptrap, we have chosen the " +
numbers.length + "best lottery numbers for you. </B>" +
"<OL>"
);
for(int i=0; i<numbers.length; i++) {
out.println(" <LI>" + numbers[i] + "</LI>");
}
out.println("</OL>" +
"<BODY></HTML>");
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
} /**
* The standard service method compares this date against any date specified in the If-Modified-Since request header.
* If the getLastModified date is later or if there is no
* If-Modified-Since header, the doGet method is called
* normally. But if the getLastModified date is the same or earlier, the service method sends back a 304 (Not Modified)
* response and does not call doGet. The browser should use it cached version of the page in such a case.
* @param req
* @return
*/
@Override
public long getLastModified(HttpServletRequest req) {
return (modTime);
} // A random int from 0 to 99
private int randomNum() {
return (int)(Math.random() * 100);
}
}

if-Modified-Since:
这个报头和if-Modified-Since正好相反:它规定仅当文档比指定的日期要旧时,操作才需要继续

Referer:标明web页面的URL。用于追踪请求来源
User-Agent:标识生成请求的浏览器或者其他客户程序

发送压缩页面
gzip文本压缩方案能极大减少HTML(或纯文本)页面的大小。大多数最近的浏览器都直达如何处理gzip压缩后的内容,所以,服务器对文档进行压缩,使得传输更小。
servlet首先检查Accept-Encoding报头,检查它是否包含有关gzip的项。如果支持,它使用PrintWriter封装GZIPOutputStream,并指定Content-Encoding响应报头值为gzip。如果不支持gzip,则使用正常的PrintWriter。浏览器禁用压缩可以在URL尾部加上?disableGzip

使用gzip压缩返回页面的例子:

package com.zhen.test.o3;

import com.zhen.util.GzipUtilities;
import com.zhen.util.ServletUtilities; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter; /**
* Created by zhen on 2017-11-05.
*/
public class LongServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
PrintWriter out;
if(GzipUtilities.isGzipSupported(req) && !GzipUtilities.isGzipDisabled(req)){
out = GzipUtilities.getGzipWriter(resp);
}else{
out = resp.getWriter();
}
String title = "Long Page";
out.println(ServletUtilities.headWithTitle(title) + "" +
"<body bgcolor=\"#FDF5E6\">\n" +
"<h1 align=\"center\">" + title + "</h1>\n");
String line = "Blah, blah, blah, blah, blah. Yadda, yadda, yadda, yadda, yadda.";
for(int i = 0; i <10000; i++){
out.println(line);
}
out.println("</body></html>");
out.close();
}
} package com.zhen.util; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.zip.GZIPOutputStream; /**
* Created by zhen on 2017-11-05.
*/
public class GzipUtilities { public static boolean isGzipSupported(HttpServletRequest request) {
String encodings = request.getHeader("Accept-Encoding");
return (encodings != null)
&& (encodings.indexOf("gzip") != -1);
} public static boolean isGzipDisabled(HttpServletRequest request) {
String flag = request.getParameter("disableGzip");
return (flag != null)
&& (!flag.equalsIgnoreCase("false"));
} public static PrintWriter getGzipWriter(HttpServletResponse response) throws IOException{
response.setHeader("Content-Encoding","gzip");
return new PrintWriter(new GZIPOutputStream(response.getOutputStream()));
}
}

区分不同的浏览器类型:
User-Agent报头标识发出的请求的具体浏览器。
注意细节:
1、仅仅在必需的时候才会使用User-Agent
2、检查是否为null
3、区分Netscape和Internet Explorer,要检查“MSIE”,而并非“Mozilla”.Netscape和Internet Explorer都在该报头的开始处列出“Mozilla”,尽管Mozilla是类Godzilla的Netscape吉祥物。这个特征是为了与javascript兼容
4、注意,该报头可以造假
根据客户的到达方式定制页面
Referer报头支出,用户单击链接到达当前页面时所处页面的位置。如果用户直接输入页面的地址。那么浏览器就不会发送Referer。
通过这个报头,可以做到:
1、创建一个工作网站,承袭链接到它的相关网站的外观感觉。
2、根据链接来自防火墙内部还是外部,更改页面的内容
3、提供相应的链接,使用户能够返回之前的页面
4、跟踪标题广告的有效性,或者记录显示您广告不同网站的点击率

标砖CGI变量的访问
存在一个有些混杂的集合,存储各种与当前请求相关的信息。有些基于http请求中的行和报头,其他来自于socket本身,还有一些取自服务器的安装参数。
servlet中CGI变量的等价物:
1、AUTH_TYPE
若提供了Authoriztion报头。这个变量给出指定的模式(basic或digest)。用request.getAuthType()来访问它。
2、CONTENT_LENGTH
调用request.getContentLength()即可访问
3、CONTENT_TYPE
调用request.getContentType()即可访问
4、DOCUMENT_ROOT
DOCUMENT_ROOT变量指定与URL http://host/对应的实际目录。用getServletContext()。getRealPath("/")对它进行访问
5、HTTP_XXX_YYY
Cookie报头成为HTTP_COOKIE, User-agent成为HTTP_USER_AGENT,Referer称为HTTP_REFERER,依次类推。servlet应该只是用request.getHeaderNames或者快捷方法
6、PATH_INFO
路径信息可以作为常规表单数据的一部分进行发送,之后用getServletContext().getRealPath进行转换。是用request.getPathInfo()访问PATH_INFO的值
7、PATH_TRANSLATED
PATH_TRANSLATED给出映射到服务器实际路径的路径信息。通过request.getPathTranslated()访问。
8、QUERY_STRING
对于get请求,这个变量以单字符串的形式给出附加的数据,这些数据依旧保持URL编码之后的状态,一般使用getParameter访问。如果您真的需要原始数据,可以通过request.getQueryString()得到它
9、REMOTE_ADDR
这个变量指出发出请求的客户机的IP地址,调用request.getRemoteAddr()对它进行访问
10、REMOTE_HOST
给出发出请求的客户机的完全限定域名,如果不能确定域名,返回ip地址。使用request.getRemoteHost()访问
11、REMOTE_USER
如果提供了Authorization报头,并经过服务器自身的解码,那么REMOTE_USER变量给出用户相关的部分。用request.getRemoteUser访问它
12、REQUEST_METHOD
通过request.getMethod()访问这个变量
13、SCRIPT_NAME
这个变量给出servlet的路径,相对于服务器的根目录。可以通过request.getServletPath()访问
14、SERVER_NAME
服务器计算机的主机名。可以用request.getServerName访问
15、SERVER_PORT
存储服务器正在侦听的端口。技术上等价于String.valueOf(request.getServerPort())
16、SERVER_PROTOCOL
标明在请求行中使用的协议名称和版本。用request.getProtocol进行访问
17、SERVER_SOFTWARE
给出web服务器的标识信息。通过getServletContext().getServletInfo()进行访问。

http请求报头的更多相关文章

  1. HTTP报头:通用报头,请求报头,响应报头和实体报头

    缓存控制优先级从高到低分别是Pragma -> Cache-Control -> Expires 报头 每一个报头都是由 [名称 + ":" + 空格 + 值 + ] ...

  2. 四种为HttpClient添加默认请求报头的解决方案

    HttpClient在Web调用中具有广泛的应用,而为它添加默认请求头是我们经常遇到的需求,本文介绍4种为HttpClient添加默认请求头的方式. 第一种方式 直接在创建的HttpClient对象的 ...

  3. 如何实现Http请求报头的自动转发[应用篇]

    如今的应用部署逐渐向微服务化发展,导致一个完整的事务往往会跨越很多的应用或服务,出于分布式链路跟踪的需要,我们往往将从上游服务获得的跟踪请求报头无脑地向下游服务进行转发.本文介绍的这个名为Header ...

  4. SpringMVC(六):@RequestMapping下使用@RequestHeader绑定请求报头的属性值、@CookieValue绑定请求中的Cookie值

    备注:我本地浏览器的报头(Request Header)信息如下: Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image ...

  5. Http请求报头设置

    1.添加一个SetHeaderValue方法: public static void SetHeaderValue(WebHeaderCollection header, string name, s ...

  6. http请求报头和响应报头(1)

    1.web端不可避免的http缓存机制,要理解缓存机制,先来了解下http的请求报文和响应报文的内容 2.请求报文  2.1请求行    请求行三部分组成:请求方法.URL以及版本协议 请求的方法有G ...

  7. HTTP请求报头及其处理

    ps:详细说明http://www.cnblogs.com/kkgreen/archive/2011/04/11/2012829.html

  8. 《HTTP协议详解》读书笔记---请求篇之消息报头

    不管是请求消息还是响应消息都包含消息报头,那么消息报头包含哪些内容?他们都代表什么含义呢?以下将带着 这些问题去学习消息报头. http消息(不管是请求消息还是响应消息)都是由开始行,消息报头(可选) ...

  9. ASP.NET Core应用针对静态文件请求的处理[3]: StaticFileMiddleware中间件如何处理针对文件请求

    我们通过<以Web的形式发布静态文件>和<条件请求与区间请求>中的实例演示,以及上面针对条件请求和区间请求的介绍,从提供的功能和特性的角度对这个名为StaticFileMidd ...

随机推荐

  1. 05_Flume_timestamp interceptor实践

    1.目标场景 2.Flume Agent配置 # specify agent,source,sink,channel a1.sources = r1 a1.sinks = k1 a1.channels ...

  2. UVa 1614 奇怪的股市

    https://vjudge.net/problem/UVA-1614 题意:输入一个长度为n的序列a,满足1<=ai<=i,要求确定每个数的正负号,使得所有数的总和为0. 思路:贪心部分 ...

  3. miRNA几大常用的数据库

    1.miRbasehttp://www.mirbase.org/2.miRDBhttp://www.mirdb.org/miRDB/policy.html3.miRandahttp://www.mic ...

  4. python argparse模块--转载

    add_argument:读入命令行参数,该调用有多个参数 ArgumentParser.add_argument(name or flags…[, action][, nargs][, const] ...

  5. [STL][C++]STACK QUEUE

    参考:http://www.cnblogs.com/mfryf/archive/2012/08/09/2629992.html stackstack 模板类的定义在<stack>头文件中. ...

  6. Activity生命周期之我见

    关于Activity生命周期的文章很多,而且大部分也说得很详细,所以作为关于这方面的内容我本来不想多说,但是大家可能跟我之前一样,在看这方面的内容的时候都能很容易地看懂,但是过几天又忘了,或者在用的程 ...

  7. 【Robot Framework 项目实战 02】SeleniumLibrary Web UI 自动化

    前言 SeleniumLibrary 是针对 Robot Framework 开发的 Selenium 库.它也 Robot Framework 下面最流程的库之一.主要用于编写 Web UI 自动化 ...

  8. mapStateToProps,mapDispatchToProps的使用姿势

    本文作者:IMWeb 黄qiong 原文出处:IMWeb社区 未经同意,禁止转载 前言 刚接触redux的时候,发现大家对mapDispatchToProps使用有几种方法,而且都跑通了,本文来介绍下 ...

  9. Html概述

    Html概述 主要思想,主要思想很重要 一.Html是什么 一种标记语言(用标签进行标记) 对要显示的文字进行标记 二.Html核心 标签(只认标签) 封装,所以必须有头尾,你才知道标签的范围,你才知 ...

  10. rsync+inotify文件同步 - 同步慢的问题

    rsync+inotify文件同步 - 同步慢的问题 我们来看网上的教程,我加了注释.(网上所有的教程基本都一模一样,尽管写法不一样,致命点都是一样的) #!/bin/bash /usr/bin/in ...