HttpServletRequest

HttpServletRequest
 
  • 发表于 3年前 
  • 阅读 2999 
  • 收藏 15 
  • 点赞 0 
  • 评论 0
摘要: 摘自《深入体验JAVA WEB开发内幕——核心基础》,如有版权问题,请联系我。

一、HttpServletRequest

web客户端发送给web服务器的HTTP请求消息可以分为三个部分:请求行、请求消息头、消息正文(也叫实体内容)。Servlet程序通过调用ServletRequest对象的方法可以获知客户端的请求信息,以及客户机和服务器的网络环境信息,例如获取客户发送的请求消息的各个部分和客户端IP地址。HttpServletRequest是专用于HTTP协议的ServletRequest子接口,它用于封装HTTP请求消息,增加了获取HTTP协议专有的头信息的方法,以及获取HTTP请求消息参数的功能。

二、请求消息

1、获取请求行的相关信息

HTTP请求消息的请求行可以分为三个部分:请求方式、资源路径和HTTP协议版本,如:

GET    /project/servlet/RequestURI?parm1=a&parm2=b    HTTP/1.1

RequestLineServlet.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RequestLineServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html; charset=GB2312"); 
        PrintWriter out = response.getWriter();
        
        out.println("getMethod:" + request.getMethod() + "<br>");
        // 返回位于主机和端口之后、参数部分之前的那部分内容
        out.println("getRequestURI:" + request.getRequestURI() + "<br>");
        // 返回参数部分,无参数返回null
        out.println("getQueryString:" + request.getQueryString() + "<br>");
        // 返回协议名和版本号
        out.println("getProtocol:" + request.getProtocol() + "<br>");
        // 返回Web应用程序的路径(虚拟目录),这个路径以“/”开头
        out.println("getContextPath:" + request.getContextPath() + "<br>");
        // 返回servlet映射的路径(web.xml的url-pattern属性)
        out.println("getServletPath:" + request.getServletPath() + "<br>");
    }
}

 

注:URL和URI的区别,可看http://www.cnblogs.com/gaojing/archive/2012/02/04/2413626.html

2、获取请求头的信息

ServletRequest和HttpServletRequest接口中定义了若干用于读取HTTP请求消息中的头字段的方法,其中的getHeader方法是一个通用的方法,可以读取所有的头字段。

(1)、获取所有请求头信息

RequestHeadersServlet.java

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RequestHeadersServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html; charset=GB2312");
        PrintWriter out = response.getWriter();
        
        Enumeration<?> headerNames = request.getHeaderNames();
        while(headerNames.hasMoreElements()) {
            String headerName = (String)headerNames.nextElement();
            // 同一个请求头名可能出现多次
            Enumeration<?> values = request.getHeaders(headerName);
            while(values.hasMoreElements()) {
                out.println(headerName + ":" + (String)values.nextElement() + "<br>");
            }
        }
    }
}

 

在浏览器输入访问地址:http://localhost:8888/requestHeadersServlet/servlet/RequestHeadersServlet

现增加一个html文件,从它链接到该Servlet,访问referer.html:

<a href="servlet/RequestHeadersServlet">referer test</a>

 

访问referer.html:

点击超链接,再次访问RequestHeadersServlet

注意观察:请求消息包含了referer请求头。

(2)盗链

关于“盗链”:http://baike.baidu.com/link?url=UpFE0AJdwVL2ESHqD6aF1N28Zmwi47RwoKzs50NI2t1HKBR6paci_NFhbv78hW-x

为了防止“盗链”,需要检查请求的来路,只接受本站内的页面链接进来的下载请求,而阻止其他站点的页面链接进来的下载请求。要实现这样功能,就需要检查请求消息的referer头字段是否与本站匹配。

DownManagerServlet.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
    public class DownManagerServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html; charset=GB2312");
        String referer = request.getHeader("referer");
        String sitePart = "http://" + request.getServerName();
        PrintWriter out = response.getWriter();
        
        // 增加if判断是为了下载请求必须通过本站的下载页面链接进来,也就是防止盗链
        if(referer != null && referer.startsWith(sitePart)) {
            // 处理正当的下载请求,这里只是示意
            out.println("dealing download ...");
        } else {
            // 非法下载请求(即referer为空或不匹配sitePart)跳转到本站的下载说明页
            response.sendRedirect("../down.html");
        }
    }
}

 

down.html

<a href="servlet/DownManagerServlet">down</a>

 

在浏览器输入访问地址:localhost:8888/downManagerServlet/servlet/DownManagerServlet

因为请求消息不含referer请求头,即DownManagerServlet代码中的referer为空,跳转到down.html

点击超链接,再次访问DownManagerServlet,由于这时的请求消息包含有referer请求且值与DownManagerServlet位于同一Web站点,DownManagerServlet接受下载请求。

3、获取请求消息的实体内容

以POST方式提交HTML的FORM表单时,其中的表单字段元素信息都将作为HTTP消息的实体内容(消息正文)发送给Web服务器。对应HTTP请求消息的中的实体内容,ServletRequest以输入流的方式提供给Servlet程序读取,ServletRequest接口中定义了一个getInputStream方法来返回这个字节输入流对象。为了方便读取纯文本形式的实体内容,ServletRequest接口也定义了一个getReader方法,以返回一个代表实体内容的字符输入流对象。

getInputStream与getReader方法

  • getInputStream返回输入流对象类型为ServletInputStream,如果实体内容中包含二进制数据,那么只能使用getInputStream方法返回的输入流对象来读取实体内容。

  • getReader则返回一个BufferedReader对象。

  • 调用了两者任意一个方法后,就不能再调用另一方法。

    三、获取请求参数

    HttpServletRequest对象的最基本和最广泛应用就是获取浏览器传递给Web服务器的参数信息,这些参数信息既可以是HTTP请求消息的请求行中的URL地址后的附加信息,又可以是Post方式下application/x-www-form-urlencoded编码格式的实体内容。那么,如何获取这两种参数?

    ServletRequest和HttpServletRequest接口中定义了若干方法,这些方法除了能读取HTTP请求消息的请求行的URL地址后的附件信息外,还能读取Post方式下的application/x-www-form-urlencoded编码格式的实体内容。

    • getParameter方法:如果请求消息中没有包含指定名称的参数,该方法返回null,即getParameter("firstname"),不存在这个参数返回null;如果指定名称的参数存在但没有设置值,返回一个空串;如果包含多个指定名称相同的参数,返回第一个出现的参数值。另外,该方法对参数名大小写敏感。

    • getParameterValues方法:该方法用于获取某个指定名称的所有参数的值,并以一个String数组的形式返回这些参数值。如果参数值只有一个,返回的数组的长度就为1,其中包含的元素值与getParameter方法返回的值一样。

    • getParameterNames方法:返回一个包含请求消息中所有参数名的Enumeration对象。

    • getParameterMap方法:返回一个将请求消息中所有参数名和值装进Map的Map对象

    问:何为隐藏表单字段?

    答:在form表单中可以使用隐藏表单字段元素向服务器传递参数信息,浏览器在网页上不会显示出隐藏表单字段元素,但当提交表单时,浏览器会将这个隐藏表单字段元素的name属性和value属性作为参数传递给web服务器。

    四、利用请求域属性传递消息

    ServletRequest接口的实现类通常都是采用一个HashMap对象来存储某些对象,setAttribute方法就是向这个HashMap对象中增加与某个名称绑定的对象,getAttribute方法则是根据名称从这个HashMap对象中检索对象。这种存储在ServletRequest对象中的对象称之为请求域属性。

    • setAttribute(String name, Object o),如果ServletRequest对象中已经存在指定名称的属性,若属性值对象为null则相当于removeAttribute,否则即覆盖原来对象。

    • getAttribute(String name),返回指定名称的属性对象。

    • removeAttribute(String name),删除指定名称的属性对象。

    • getAttributeNames(),返回一个包含ServletRequest对象中所有属性名的Enumeration对象。

     

    • 0
      点赞
    • 0
      收藏
      觉得还不错? 一键收藏
    • 0
      评论

    “相关推荐”对你有帮助么?

    • 非常没帮助
    • 没帮助
    • 一般
    • 有帮助
    • 非常有帮助
    提交
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值