request

Posted 暴走小骚年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了request相关的知识,希望对你有一定的参考价值。

本节内容:

  • HttpServletRequest概述
  • request的运行流程
  • 通过抓包工具抓取Http请求
  • 通过request获得请求行
  • 通过request获得请求头
  • 通过request获得请求体
  • request的其他功能
  • 示例:注册
  • 示例:登录

 

一、HttpServletRequest概述

我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应response。

service方法中的request的类型是ServletRequest,而doGet/doPost方法的request的类型是HttpServletRequest,HttpServletRequest是ServletRequest的子接口,功能和方法更加强大。

 

二、request的运行流程

 

三、通过抓包工具抓取Http请求

 

request代表请求,我们可以通过该对象分别获得Http请求的请求行,请求头和请求体。

注意:GET方式是没有请求体的。现阶段只有表单,并且表单的方法是post的是POST提交,其他都是GET提交。

 

四、通过request获得请求行

获得客户端的请求方式:String getMethod()

获得请求的资源:

  • String getRequestURI():所有的资源地址,比如C:\\a.txt,还有相对地址
  • StringBuffer getRequestURL():一般情况指的是网络资源,比如http
  • String getContextPath():获取web应用的名称
  • String getQueryString():获取get方式提交url地址后的参数字符串,比如username=zhangsan&password=123
  • request.getRemoteAddr():获得访问的客户端IP地址

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <form action="/WEB15/line" method="get"> <!-- get和post都测试下-->
        <input type="text" name="username"><br>
        <input type="password" name="password"><br>
        <input type="submit" value="提交"><br>
    </form>
</body>
</html>
form.html
public class LineServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        //1、获得请求方式
        String method = request.getMethod();
        System.out.println("method:"+method);
        //2、获得请求的资源相关的内容
        String requestURI = request.getRequestURI(); 
        StringBuffer requestURL = request.getRequestURL();
        System.out.println("uri:"+requestURI); // /WEB15/line
        System.out.println("url:"+requestURL); // http://localhost:8080/WEB15/line
        //获得web应用的名称
        String contextPath = request.getContextPath();
        System.out.println("web应用:"+contextPath); // /WEB15
        //地址后的参数的字符串
        String queryString = request.getQueryString();
        System.out.println(queryString); // GET方式才有值,POST方式提交为null
        //3、获得客户机的信息---获得访问者IP地址
        String remoteAddr = request.getRemoteAddr();
        System.out.println("IP:"+remoteAddr);
        
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
LineServlet.java

 

五、通过request获得请求头

  • long getDateHeader(String name)
  • String getHeader(String name):header都是键值对。
  • Enumeration getHeaderNames():获取所有header头的名字。返回类型是枚举。
  • Enumeration getHeaders(String name):某些头可能有多个值。基本不用,因为基本不会有同名的头。
  • int getIntHeader(String name)
public class HeaderServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        //1、获得指定的头
        String header = request.getHeader("User-Agent");
        System.out.println(header);
        //2、获得所有的头的名称和值
        Enumeration<String> headerNames = request.getHeaderNames(); //Enumeration,枚举类型,你可以认为它是一个集合,现在用的不多了
        while(headerNames.hasMoreElements()){
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            System.out.println(headerName+":"+headerValue);
        }
        
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
HeaderServlet.java

 

referer头的作用:执行该此访问(请求)的的来源。即这次请求来源于哪个资源。

【示例】:在页面中写一个a标签,一点击访问HeaderServlet。header中就有referer。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <a href="/WEB15/referer">访问headerServlet资源</a>
</body>
form.html
public class HeaderServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        //1、获得指定的头
        String header = request.getHeader("User-Agent");
        System.out.println(header);
        //2、获得所有的头的名称和值
        Enumeration<String> headerNames = request.getHeaderNames(); //Enumeration,枚举类型,你可以认为它是一个集合,现在用的不多了
        while(headerNames.hasMoreElements()){
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            System.out.println(headerName+":"+headerValue);
        }
        
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
HeaderServlet.java

浏览器访问http://localhost:8080/WEB15/form.html,点击a标签,查看eclipse控制台打印的header结果,发现有个refer:

referer:http://localhost:8080/WEB15/form.html

 

【示例】:利用referer头做防盗链。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <a href="/WEB15/referer">访问headerServlet资源</a>
    <form action="/WEB15/line" method="get">
        <input type="text" name="username"><br>
        <input type="password" name="password"><br>
        <input type="submit" value="提交"><br>
    </form>
</body>
</html>
form.html
public class RefererServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        //对该新闻的来源的进行判断
        String header = request.getHeader("referer");
        if(header!=null&&header.startsWith("http://localhost")){ //企业里面可以把localhost换成域名
            //是从我自己的网站跳转过来的 可以看新闻
            response.setContentType("text/html;charset=UTF-8");
            response.getWriter().write("中国确实已经拿到100块金牌....");
        }else{
            response.getWriter().write("你是盗链者,可耻!!");
        }    
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
RefererServlet.java

 

六、通过request获得请求体

请求体中的内容是通过post提交的请求参数,格式是:

username=zhangsan&password=123&hobby=football&hobby=basketball

以上面参数为例,通过一下方法获得请求参数:

  • String getParameter(String name)
  • String[] getParameterValues(String name)
  • Enumeration getParameterNames()
  • Map<String,String[]> getParameterMap()
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <form action="/WEB15/content" method="post"> <!-- post和get都试下,后台写代码都是可以获取到请求参数的>
        <input type="text" name="username"><br>
        <input type="password" name="password"><br>
        <input type="checkbox" name="hobby" value="zq">足球
        <input type="checkbox" name="hobby" value="pq">排球
        <input type="checkbox" name="hobby" value="ppq">乒乓球<br>
        <input type="submit" value="提交"><br>
    </form>
</body>
</html>
form.html
public class ContentServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        //1、获得单个表单值
        String username = request.getParameter("username");
        System.out.println(username);
        String password = request.getParameter("password");
        System.out.println(password);
        //2、获得多个表单的值 --比如checkbox的多值情况
        String[] hobbys = request.getParameterValues("hobby");
        for(String hobby:hobbys){
            System.out.println(hobby);
        }
        //3、获得所有的请求参数的名称
        Enumeration<String> parameterNames = request.getParameterNames();
        while(parameterNames.hasMoreElements()){
            System.out.println(parameterNames.nextElement());
        }
        System.out.println("------------------");
        //4、获得所有的参数 参数封装到一个Map<String,String[]>
        /*
        username                [zhangsan]
        password                [123]
        hobby                [football,basketball]
        */
        Map<String, String[]> parameterMap = request.getParameterMap();
        for(Map.Entry<String, String[]> entry:parameterMap.entrySet()){
            System.out.println(entry.getKey());
            for(String str:entry.getValue()){
                System.out.println(str);
            }
            System.out.println("---------------------------");
        }
        
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
ContentServlet.java

【注意】:get请求方式的请求参数,上述的方法一样可以获得。

 

七、request的其他功能

1. request是一个域对象

request对象也是一个存储数据的区域对象,所以也具有如下方法:

  • setAttribute(String name, Object o)
  • getAttribute(String name)
  • removeAttribute(String name)

注意:request域的作用范围:一次请求中。每次访问都会产生新的request和response对象。

 

2. request完成请求转发 

先获得请求转发器 --path是转发的地址
RequestDispatcher getRequestDispatcher(String path)

在通过转发器对象的forward方法转发

requestDispathcer.forward(ServletRequest request, ServletResponse response)

public class Servlet1 extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        //想request域中存储数据
        request.setAttribute("name", "tom");
        
        //servlet1 将请求转发给servlet2
        RequestDispatcher dispatcher = request.getRequestDispatcher("/servlet2");
        //执行转发的方法
        dispatcher.forward(request, response);
        
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
Servlet1.java
public class Servlet2 extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        //从request域中取出数据
        Object attribute = request.getAttribute("name");
        
        response.getWriter().write("hello haohao..."+attribute);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
Servlet2.java

 

ServletContext域与Request域的生命周期比较?

ServletContext域:

创建:服务器启动
销毁:服务器关闭
域的作用范围:整个web应用
request域:

创建:访问时创建request
销毁:响应结束request销毁
域的作用范围:一次请求中

 

转发与重定向的区别?

1)重定向是两次请求,转发是一次请求
2)重定向地址栏的地址变化,转发地址不变
3)重新定向可以访问外部网站(比如可以重定向到百度),转发只能访问内部资源(转发给内部的地址)。
4)转发的性能要优于重定向

 

客户端地址与服务器端地址的写法?

客户端地址:是客户端去访问服务器的地址,属于服务器外部的地址,就是从外部访问服务器资源。特点:需要写上web应用名称。

  • 直接输入地址
  • 重定向


服务器端地址:服务器内部资源的跳转的地址,特点:不需要写web应用的名称。

  • 转发

 

八、示例:注册

表:

CREATE TABLE `user` (
  `uid` varchar(50) NOT NULL,
  `username` varchar(20) DEFAULT NULL,
  `password` varchar(20) DEFAULT NULL,
  `name` varchar(20) DEFAULT NULL,
  `email` varchar(30) DEFAULT NULL,
  `telephone` varchar(20) DEFAULT NULL,
  `birthday` varchar(20) DEFAULT NULL,
  `sex` varchar(10) DEFAULT NULL,
  `state` int(11) DEFAULT NULL,
  `code` varchar(64) DEFAULT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 页面:

<div class="container"
    style="width: 100%; background: url(\'image/regist_bg.jpg\');">
    <div class="row">
        <div class="col-md-2"></div>
        <div class="col-md-8"
            style="background: #fff; padding: 40px 80px; margin: 30px; border: 7px solid #ccc;">
            <font>会员注册</font>USER REGISTER
            <form class="form-horizontal" style="margin-top: 5px;" action="/WEB15_request/register" method="post">
                <div class="form-group">
                    <label for="username" class="col-sm-2 control-label">用户名</label>
                    <div class="col-sm-6">
                        <input type="text" class="form-control" id="username" name="username"
                            placeholder="请输入用户名">
                    </div>
                </div>
                <div class="form-group">
                    <label for="inputPassword3" class="col-sm-2 control-label">密码</label>
                    <div class="col-sm-6">
                        <input type="password" class="form-control" id="inputPassword3" name="password"
                            placeholder="请输入密码">
                    </div>
                </div>
                <div class="form-group">
                    <label for="confirmpwd" class="col-sm-2 control-label">确认密码</label> <!-- 确认密码不需要传到数据库 -->
                    <div class="col-sm-6">
                        <input type="password" class="form-control" id="confirmpwd"
                            placeholder="请输入确认密码">
                    </div>
                </div>
                <div class="form-group">
                    <label for="inputEmail3" class="col-sm-2 control-label">Email</label>
                    <div class="col-sm-6">
                        <input type="email" class="form-control" id="inputEmail3" name="email"
                            placeholder="Email">
                    </div>
                </div>
                <div class="form-group">
                    <label for="usercaption" class="col-sm-2 control-label">姓名</label>
                    <div class="col-sm-6">
                        <input type="text" class="form-control" id="usercaption" name="name"
                            placeholder="请输入姓名">
                    </div>
                </div>
                <div class="form-group opt">
                    <label for="inlineRadio1" class="col-sm-2 control-label">性别</label>
                    <div class="col-sm-6">
                        <label class="radio-inline"> <input type="radio"
                            name="sex" id="inlineRadio1" value="male"></label> <label class="radio-inline"> <input type="radio"
                            name="inlineRadioOptions" id="inlineRadio2" value="female"></label>
                    </div>
                </div>
                <div class="form-group">
                    <label for="date" class="col-sm-2 control-label">出生日期</label>
                    <div class="col-sm-6">
                        <input type="date" class="form-control" name="birthday">
                    </div>
                </div>

                <div class="form-group">
                    <label for="date" class="col-sm-2 control-label">验证码</label>
                    <div class="col-sm-3">
                        <input type="text" class="form-control">

                    </div>
                    <div class="col-sm-2">
                        <img src="./image/captcha.jhtml" />
                    </div>

                </div>

                <div class="form-group">
                    <div class="col-sm-offset-2 col-sm-10">
                        <input type="submit" width="100" value="注册" name="submit"
                            style="background: url(\'./images/register.gif\') no-repeat scroll 0 0 rgba(0, 0, 0, 0); height: 35px; width: 100px; color: white;">
                    </div>
                </div>
            </form>
        </div>

        <div class="col-md-2"></div>

    </div>
</div>
register.jsp

处理注册的Servlet:

public class RegisterServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //设置request的编码,request编码默认也是ISO-8859-1 ---只适合post方式
        request.setCharacterEncoding("UTF-8");
        
        //get方式乱码解决,该方式也适用POST方式。但是表单一般都是POST方式提交
        //String username = request.getParameter("username");//乱码
        //先用iso8859-1编码 在使用utf-8解码
        //username = new String(username.getBytes("iso8859-1"),"UTF-8");
         
        
        //1、获取数据
        //String username = request.getParameter("username");
        //System.out.println(username);
        //String password = request.getParameter("password");
        //.....

        //2、将散装的封装到javaBean,这种比较麻烦,一般都不用,用BeanUtils工具
        //User user = new User();
        //user.setUsername(username);
        //user.setPassword(password);

        //使用BeanUtils进行自动映射封装。依赖两个包commons-beanutils-1.8.3.jar和commons-logging-1.1.1.jar
        //BeanUtils工作原理:将map中的数据 根据key与实体的属性的对应关系封装
        //只要key的名字与实体的属性 的名字一样 就自动封装到实体中
        Map<String, String[]> properties = request.getParameterMap(); //如果是get方式提交的,要循环这个Map,去解码编码,防止中文乱码
        User user = new User();
        try {
            BeanUtils.populate(user, properties);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        //到目前为止,user对象已经封装好了。但是user表有个uid字段,它是个主键
        //手动封装uid----使用uuid产生随机不重复的字符串32位--但是java代码生成后是36位
        user.setUid(UUID.randomUUID().toString());

        //3、将参数传递给一个业务操作方法
        try {
            regist(user);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        
        //4、认为注册成功跳转到登录页面
        response.sendRedirect(request.getContextPath()+"/login.jsp");

    }

    //注册的方法
    public void regist(User user) throws SQLException{
        //操作数据库
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        String sql = "insert into user values(?,?,?,?,?,?,?,?,?,?)";
        
        runner.update(sql,user.getUid(),user.getUsername(),user.getPassword(),user.getName(),
                user.getEmail(),null,user.getBirthday(),user.getSex(),null,null);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}
RegisterServlet.java

 

http请求提交时,post方式提交时数据在请求体,get方式提交时数据是请求行中。request对请求行和请求体的处理是不一样的。

解决post提交方式的乱码:request.setCharacterEncoding("UTF-8");

解决get提交的方式的乱码:
parameter = new String(parameter.getbytes("iso8859-1"),"utf-8");

 

 

九、示例:登录

转发:

<body>

    <!-- 引入header.jsp -->
    <jsp:include page="/header.jsp"></jsp:include>


    <div class="container"
        style="width: 100%; height: 460px; background: #FF2C4C url(\'images/loginbg.jpg\') no-repeat;">
        <div class="row">
            <div class="col-md-7">
                <!--<img src="./image/login.jpg" width="500" height="330" alt="会员登录" title="会员登录">-->
            </div>

            <div class="col-md-5">
                <div
                    style="width: 440px; border: 1px solid #E7E7E7; padding: 20px 0 20px 30px; border-radius: 5px; margin-top: 60px; background: #fff;">
                    <font>会员登录</font>USER LOGIN
                    <div><%=request.getAttribute("loginInfo")==null?"":request.getAttribute("loginInfo") %>></div>
                    <form class="form-horizontal" action="/WEB15_request/login" method="post">
                        <div class="form-group">
                            <label for="username" class="col-sm-2 control-label">用户名</label>
                            <div class="col-sm-6">
                                <input type="text" class="form-control" id="username" name="username"
                                    placeholder="请输入用户名">
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="inputPassword3" class="col-sm-2 control-label">密码</label>
                            <div class="col-sm-6">
                                <input type="password" class="form-control" id="inputPassword3" name="password"
                                    placeholder="请输入密码">
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="inputPassword3" class="col-sm-2 control-label">验证码</label>
                            <div class="col-sm-3">
                                <input type="text" class="form-control" id="inputPassword3"
                                    p

以上是关于request的主要内容,如果未能解决你的问题,请参考以下文章

C#-WebForm-★内置对象简介★Request-获取请求对象Response相应请求对象Session全局变量(私有)Cookie全局变量(私有)Application全局公共变量Vi(代码片段

推进学说代码片段

Motan在服务provider端用于处理request的线程池

[未解决问题记录]python asyncio+aiohttp出现Exception ignored:RuntimeError('Event loop is closed')(代码片段

你如何在 python 中处理 graphql 查询和片段?

request.getParameter讲解