HttpServletRequest和HttpServletResponse对象详解

Servlet生命周期》一文提到,在 Servlet 生命周期的运行阶段,Servlet 容器会为当前的客户端请求创建一个 HttpServletRequest 对象和一个 HttpServletResponse 对象(这两个对象分别继承自 ServletRequest 和 ServletResponse),其中:

  • HttpServletRequest 对象封装了客户端的请求信息,比如 IP 地址、域名、端口号等,该消息会附带在 HTTP 请求中一起发送给服务器;
  • HttpServletResponse 对象用来封装 HTTP 响应消息,比如状态码、编码格式、内容类型等,该消息会跟随 HTTP 请求一起发送给客户端。

HttpServletRequest 对象

HttpServletRequest 对象代表客户端(浏览器)的请求,当客户端通过 HTTP 协议访问服务器时,HTTP 请求中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。

以下是 HttpServletRequest 对象获取请求信息的一些方法以及代码示例:

获取客户端信息
getRequestURL() 返回客户端发出请求时的完整 URL。
getRequestURI() 返回请求行中的资源名部分。
getQueryString() 返回请求中的参数部分。
getRemoteAddr() 返回发出请求的客户机的 IP 地址 。
getRemoteHost() 返回发出请求的客户机的完整主机名。
getRemotePort() 返回客户机所使用的网络端口号。
getLocalAddr() 返回 WEB 服务器的 IP 地址。
getLocalName() 返回 WEB 服务器的主机名 。
getMethod() 根据客户机的请求方式,返回生成这个请求的HTTP方法名称(GET、    POST等)。
获得客户端请求头
getHeader(String name) 以 String 的形式返回指定请求头的值。
getHeaders(String name) 以 String 对象的 Enumeration 形式返回指定请求头的所有值。
getHeaderNames() 返回此请求包含的所有头名称的枚举。
获得客户机请求参数(客户端提交的数据)
getParameter(String name) 根据 name 获取请求参数的值。
getParameterMap() 返回的是一个 Map 类型的值,该返回值记录着客户端所提交的请求参数和请求参数值的映射关系。

下面是一段简单的演示代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception {
    System.out.println("getRequestURL: " + request.getRequestURL());
    System.out.println("getRequestURI: " + request.getRequestURI());
    System.out.println("getQueryString: " + request.getQueryString());
    System.out.println("getRemoteHost: " + request.getRemoteHost());
    System.out.println("getRemotePort: " + request.getRemotePort());
    System.out.println("getLocalAddr: " + request.getLocalAddr());
    System.out.println("getLocalName: " + request.getLocalName());
    System.out.println("getLocalPort: " + request.getLocalPort());
    System.out.println("getMethod: " + request.getMethod());
    System.out.println("-------request.getParamterMap()-------");
    // 得到请求的参数Map,注意map的value是String数组类型
    Map map = request.getParameterMap();
    Set<String> keySet = map.keySet();
    for (String key : keySet) {
        String[] values = (String[]) map.get(key);
        for (String value : values) {
            System.out.println(key + "=" + value);
        }
    }
    System.out.println("--------request.getHeader()--------");
    // 得到请求头的name集合
    Enumeration<String> em = request.getHeaderNames();
    while (em.hasMoreElements()) {
        String name = (String) em.nextElement();
        String value = request.getHeader(name);
        System.out.println(name + "=" + value);
    }
}

在浏览器地址栏中访问下面的 URL:

http://127.0.0.1:8080/ServletDemo01/Servlet01?name=yanchangsheng&password=123456

?后面跟的是参数,多个参数之间用&连接。

控制台输出结果:

getRequestURL: http://127.0.0.1:8080/ServletDemo01/Servlet01
getRequestURI: /ServletDemo01/Servlet01
getQueryString: name=yanchangsheng&password=123456
getRemoteHost: 127.0.0.1
getRemotePort: 57603
getLocalAddr: 127.0.0.1
getLocalName: 127.0.0.1
getLocalPort: 8080
getMethod: GET
——-request.getParamterMap()——-
name=yanchangsheng
password=123456
——–request.getHeader()——–
host=127.0.0.1:8080
connection=keep-alive
cache-control=max-age=0
upgrade-insecure-requests=1
user-agent=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36
accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
accept-encoding=gzip, deflate, br
accept-language=zh-CN,zh;q=0.9

HttpServletResponse 对象

与 HttpServletRequest 相反,HttpServletResponse 对象是专门用来封装 HTTP 响应消息的。客户端发出了请求,得对人家有所回应呀,HttpServletResponse 就是做这项工作的。

由于 HTTP 响应消息分为状态行、响应消息头、响应消息体三部分,因此,在 HttpServletResponse 接口中定义了向客户端发送响应状态码、响应消息头、响应消息体的方法。

1) 发送状态码相关的方法

① void setStatus(int status)
该方法用于设置 Http 响应消息的状态码,并生成响应状态行。

由于响应状态行中的状态描述信息直接与状态码相关,而 HTTP 版本由服务器确定,因此,只要通过 setStatus() 方法设置了状态码,即可实现状态行的发送。

需要注意的是,在正常情况下,Web 服务器会默认产生一个状态码为 200 的状态行。

② void sendError(int sc)
该方法用于发送表示错误信息的状态码。例如,404 状态码表示找不到客户端请求的资源。

HttpServletResponse 对象提供了两个重载的 sendError(int sc) 方法,具体如下:

public void sendError(int code) throws java.io.IOException
public void sendError(int code,String message)throws java.io.IOException

在上面重载的两个方法中,第一个方法只发送错误信息的状态码,而第二个方法除了发送状态码以外,还可以增加一条用于提示说明的文本信息,该文本信息将出现在发送给客户端的正文内容中。

2) 发送响应消息头相关的方法

方法声明 功能描述
void addHeader(String name,String value) 这两个方法都是用来设置 HTTP 协议的响应头字段,其中:

  • 参数 name 用于指定响应头字段的名称;
  • 参数 value 用于指定响应头字段的值。

不同的是,addHeader() 方法可以增加同名的响应头字段,而 setHeader() 方法则会覆盖同名的头字段。

void setHeader(String name,String value)
void addIntHeader(String name,int value)这两个方法专门用于设置包含整数值的响应头,避免了「使用 addHeader() 与 setHeader() 方法时需要将 int 类型的设置值转换为 string 类型」的问题。
void setIntHeader(String name,int value)
void setContentLength(int len)该方法用于设置响应消息的实体内容的大小,单位为字节。对于 HTTP 协议来说,这个方法就是设置 Content-Length 响应头字段的值。
void setContentType(String type)该方法用于设置 Servlet 输出内容的 MIME 类型。对于 HTTP 协议来说,就是设置 Content-Type 响应头字段的值。举例说明:

  • 如果发送到客户端的内容是 jpeg 格式的图像数据,就需要将响应头字段的类型设置为image/jpeg
  • 如果响应的内容为文本,则该方法还可以设置字符编码,例如text/html;charset=UTF-8
void setLocale(Locale loc) 该方法用于设置响应消息的本地化消息。对 HTTP 来说,就是设置 Content-Language 响头字段和 Content-Type 头字段中的字符集编码部分。

需要注意的是,如果 HTTP 消息没有设置 Content-Type 头字段,setLocale() 方法设置的字符编码则没有效果,如果调用 setCharacterEncoding() 或 setContentType() 方法指定了响应头内容的字符集编码,则 setLocale() 方法将不再具有指定字符集编码的功能。

void setCharacterEncoding(String charset)该方法用于设置 out 输出流中所采用的编码。对 HTTP 协议来说,就是设置 Content-Type 头字段中的字符集编码部分。如果没有设置 Content-type 头字段,setCharacterEncoding() 方法设置的字符集编码则没有效果。

该方法的优先级比setContentType()和setLocale()方法要高,它的设置结果将覆盖setContentType()和setLocale()方法所设置的字符编码。

3) 发送响应消息体相关的方法

① ServletOutputStream getOutputStream()方法
该方法所获取的字节输出流对象为 ServletOutputStream 类型。

由于 ServletOutputStream 是 OutputStream 的子类,它可以直接输出字节数组中的二进制数据,因此,要想输出二进制格式的响应正文,就需要使用 getOutputStream() 方法。

② PrintWriter getWriter()方法
它返回了一个可以向客户端发送文本的的 Java.io.PrintWriter 对象。

由于 PrintWriter 类型的对象可以直接输出字符文本内容,因此,要想输出内容全为字符文本的网页文档,需要使用 getWriter() 方法。

默认情况下,PrintWriter 对象使用 ISO-8859-1 编码(该编码在输入中文时会发生乱码,乱码问题后面章节会讲到)。

注意:虽然HttpServletResponse 对象的 getOutSream() 和 getWriter() 方法都可以发送响应消息体,但是他们之间相互排斥,不可以同时使用,否则会发生异常。

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/23928.html

(0)
上一篇 2021年7月20日
下一篇 2021年7月20日

相关推荐

发表回复

登录后才能评论