JavaEE之Request

Request

概述

在 Servlet API 中,定义了一个 HttpServlet Request 接口,它继承自 ServletRequest 专门用来封装 HTTP 请求消息。由于 HTTP 请求消息分为请求行、请求消息头和请求消息体三部分,因此,在 HttpServlet Request 接口中定义了获取请求行、请求头和请求消息体的相关方法

获取请求信息方法

当访问Servlet时,会在请求消息的请求行中,包含请求方法、请求资源名,请求路径等信息,为了获取这些信息,在 HttpServler Request 接口中,定义了一系列用于获取请求行信息的方法

示例代码
public class GetHeader extends HttpServlet {
    private static final long serialVersionUID = 1L;
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取http请求头消息中请求方式(get,post)
        String method = request.getMethod();
        System.out.println(method);//GET
        //获取 URL 的主机和端口之后、参数部分之前 的部分 
        String requestURI = request.getRequestURI();
        System.out.println(requestURI);// /RequestDemo/getheader
        //GET 提交 url 地址后的参数字符串 
        String queryString = request.getQueryString();
        System.out.println(queryString);// null
        //获取 Servlet 的名称或 Servlet 所映射的路径 
        String servletPath = request.getServletPath();
        System.out.println(servletPath);// /getheader
        //获取访问者 ip 地址 
        String remoteAddr = request.getRemoteAddr();
        System.out.println(remoteAddr);// 0:0:0:0:0:0:0:1
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

获取请求消息头的方法

当请求 Servlet 时,需要通过请求头向服务器传递附加信息,例如,客户端可以接受的数据类型、压缩方式、语言等,为此,在 HttpServlet Request 接口中,定义了一系列用于获得HTTP 请求头字段的方法。

示例代码
public class GetLine extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取 http 请求头的指定字段 
        String header = request.getHeader("User-Agent");
        System.out.println(header);
        //获取指定头的多个值
//      request.getHeaders("User-Agent");
        //获取一个包含所有请求头字段的 Enumeration 对象 
        Enumeration headerNames = request.getHeaderNames();
        while(headerNames.hasMoreElements()){
            String nextElement = headerNames.nextElement();
            String header2 = request.getHeader(nextElement);
            System.out.println(nextElement+":"+header2);
        }
        //该方法用于获取Content_Length头字段的值, 结果为 int 类型
        int contentLength = request.getContentLength();
        System.out.println(contentLength);
        //获取 ContentType 头字段的值,结果为 String 类型
        String contentType = request.getContentType();
        System.out.println(contentType);
        // 获取消息实体部分字符编码 
        String characterEncoding = request.getCharacterEncoding();
        System.out.println(characterEncoding);

    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

获取请求参数

在实际开发中,经常需要获取用户提交的表单数据,例如,用户名、密码、电子邮件等,为了方便获取表单中的请求参数,在HttpServlet Request 接口中,定义了一系列获取请求参数的方法。

代码示例
public class GetParam extends HttpServlet {
    private static final long serialVersionUID = 1L;
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //获取指定名称的参数
        String username = request.getParameter("username");
        System.out.println(username);
        // 如果有多个参数同名,可以使用此方法获取
        String[] hobby = request.getParameterValues("hobby");
        System.out.println(hobby);
        // 获取所有参数对象
        Enumeration parameterNames = request.getParameterNames();
        while(parameterNames.hasMoreElements()){
            System.out.println(parameterNames.nextElement());
        }
        //以键值对的形式获取参数 
        Map parameterMap = request.getParameterMap();
        for (Map.Entryentry : parameterMap.entrySet()) {
            System.out.println(entry.getKey());
            for (String str : entry.getValue()) {
                System.out.println(str);
            }
        }
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

请求参数 乱码(POST )

上面的代码,如果输入的时中文字符,那么会产生乱码问题,如下图

是因为浏览器在传递请求参数时,默认采用 UTF-8 的编码,但是在解码时采用的是默认的ISO8859-1,因此导致控制台打印参数信息出现乱码
- 解决
在 Http ServletRequest 接口中,提供了一个 sctCharacterEncoding()方法,该方法用于设置 request 对象的解码方式

request.setCharacterEncoding(“UTF-8”);

此时就能解决问题

请求参数 乱码( GET )

使用 sctCharacterEncoding()方法解决乱码问题只针对 POST 请求,而对 GET 请求是无效的,
为了解决 GET 方式提交表单的中文乱码问题,可以先使用错误码表 ISO8859-1 将用户名重新编码,然后使用码表 UTF-8 进行解码。

//get 方式乱码解决
String username = request.getParameter(“username”);//乱码
//先用 iso8859-1 编码 在使用 utf-8 解码
username = new String(username.getBytes(“iso8859-1”),”UTF-8”);

Request域存取和请求转发

Request 域对象

Reruest 对象不仅可以获取一系列数据,还可以通过属性传递数据,在 ServletRequest 接口中,定义了一系列操作属性的方法:
- setAttribute(key, value)
向 request 域中存入一个值(键值对形式)

  • getAttribute(key)
    获取 request 域中指定键的值

  • removeAttribute()
    删除 request 域中指定键的值

  • getAttributeNames()
    获取域中所有

注意:存储在 request 域中的对象数据只有当前请求有效,而对其它请求无效。

请求转发

在 ServletI 中,如果当前 Web 资源不想处理它的访问请求,可以通过 forward()方法将当前请求传递给其他的 Web 资源进行处理,这种方式称为 请求转发。
- forward()方法工作原理

当客户端访问 Servlet1 时,可以通过 forward() 方法将请求转发给其它 Web 资源,其它Web 资源处理完请求后,直接将响应结果返回到了客户端0

  • 相关方法介绍

    request.getRequestDispatcher(path);

    1. 返回封装了某个路径所指定资源的 RequestDispatcher 对象
    2. 参数 path 必须以“/”开头,用于表示当前 Web 应用的根目录。
    3. WEB-INF 目录中的内容对 RequestDispatcher 对象也是可见的,因此,传递给
      getRequestDispatcher(String path)方法的资源可以是 WEB-INF 目录中的文件
  • RequestDispatcher 接口方法介绍

    forward(ServletRequest request, ServletResponse response)

    1. 该方法用于将请求从一个 Servlet 传递给另外的一个 Web
    2. 注意:该方法必须在响应提交给客户端之前被调用,否则将抛出IllegalStateException 异常
      include(ServletRequest request,ServletResponse response)
    3. 该方法用于将其它资源当做响应内容包含进来
示例代码
public class Servlert1 extends HttpServlet {
    private static final long serialVersionUID = 1L;
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //向resquest域中存储数据
        request.setAttribute("name", "lisi");
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet2");
        requestDispatcher.forward(request, response);   
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }
}
public class Servlet2 extends HttpServlet {
    private static final long serialVersionUID = 1L;
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        Object attribute = request.getAttribute("name");
        response.getWriter().write("hello:"+attribute);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

结果:

转发和重定向的区别

  • 使用重定后,之前的 request 中存放的变量全部失效,并进入一个新的 request 作用域。

  • 试音转发后,之前的 request 中存放的变量不会失效,就像把两个页面拼到了一起。

  • 重定向两次请求,转发一次请求

  • 重定向地址栏的地址变化,转发地址不变

  • 重新定向可以访问外部网站,转发只能访问内部资源

  • 转发的性能要优于重定向

怎么选择是重定向还是转发呢?通常情况下转发更快,而且能保持 request 内的对象,所以
他是第一选择。但是由于在转发之后,浏览器中 URL 仍然指向开始页面,此时如果重载当
前页面,开始页面将会被重新调用。如果你不想看到这样的情况,则选择转发。

ServletContext 域与Request 域的生命周期

  • ServletContext

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

  • request

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

你可能感兴趣的:(Java)