HttpServletRequest简介

Web服务器收到客户端的http请求,会针对每一次请求,创建一个用于代表请求的HttpServletRequest类型的request对象,并将"HTTP请求协议"的完整内容封装到该对象中。开发者获拿到request对象后就可以获取客户端发送给服务器的请求数据了。

HttpServletRequest的生命周期

当客户端浏览器向服务器发送请求后,服务器会根据HTTP请求协议的格式对请求进行解析。同时,服务器会创建 HttpServletRequest类型的对象,即请求对象,然后将解析出的数据封装到该请求对象中。此时HttpServletRequest实例就创建并初始化完毕了,也就是说,请求对象是由服务器创建。当服务器向客户端发送响应结束后,HttpServletRequest 实例对象被服务器销毁,HttpServletRequest对象的生命周期很短暂。
一次请求对应一个请求对象, 另外一次请求对应另外一个请求对象,即每次请求都会创建一个HttpServletRequest类型的对象,这些对象之间没有关系。

HttpServletRequest中常用的方法

  • Map<string,string[]> getParameterMap()
    获取包含所有请求参数及值的 Map 对象。需要注意,该 Map 的 value 为 String[],即一个参数所对应的值为一个数组。说明一个参数可以对应多个值。
  • Enumeration getParameterNames()
    获取请求参数 Map 的所有 key,即获取所有请求参数名。
  • String[] getParameterValues(String name)
    根据指定的请求参数名称,获取其对应的所有值。这个方法一般用于获取复选框(checkbox)数据。
  • String getParameter(String name)
    根据指定的请求参数名称,获取其对应的值。若该参数名称对应的是多个值,则该方法获取到的是第一个值。这个方法是最常用的方法。

获取客户端信息的方法:

    • getRequestURL方法返回客户端发出请求时的完整URL。
    • getRequestURI方法返回请求行中的资源名部分。
    • getQueryString 方法返回请求行中的参数部分。
    • getRemoteAddr方法返回发出请求的客户机的IP地址
    • getRemoteHost方法返回发出请求的客户机的完整主机名
    • getRemotePort方法返回客户机所使用的网络端口号
    • getLocalAddr方法返回WEB服务器的IP地址。
    • getLocalName方法返回WEB服务器的主机名
    • getMethod得到客户机请求方式
      1. /**
      2. * HttpServletRequest获取请求数据
      3. */
      4. public class RequestTest01 extends HttpServlet {
      5. private static final long serialVersionUID = 1L;
      6.  
      7. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      8. //根据html中的name的名字获取用户在input中填写的值
      9. String username = request.getParameter("username");
      10. String password = request.getParameter("password");
      11. //获取用户勾选的checkbox的值
      12. String[] hobby = request.getParameterValues("hobby");
      13.  
      14. System.out.println(username);
      15. System.out.println(password);
      16. for(String s:hobby){
      17. System.out.println(s);
      18. }
      19. }
      20.  
      21. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      22. doGet(request, response);
      23. }
      24.  
      25. }

      乱码的产生原因

      当用户通过浏览器提交一个包含 UTF-8 编码格式的两个中文请求时,浏览器会将这两个中文字符变为六个字节(一般一个 UTF-8 汉字占用三个字节),即形成六个类似%8E 的字节表示形式,并将这六个字节上传至 Tomcat 服务器。
      Tomcat 服务器在接收到这六个字节后,并不知道它们原始采用的是什么字符编码。而Tomcat 默认的编码格式为 ISO-8859-1。所以会将这六个字节按照 ISO-8859-1 的格式进行解码,解码后在控制台显示,所以在控制台会显示乱码。

      乱码的解决方案

      针对 POST 提交乱码的解决方式
      在接收请求参数之前先通过 request 的 setCharacterEncoding()方法,指定请求体的字符编码格式。这样的话,在接收到请求中的参数后,就可按照指定的字符编码进行解码。
      注意,request 的 setCharacterEncoding()方法只能解决 POST 提交方式中的乱码问题,对
      于 GET 提交方式的不起作用。因为该方法设置的是请求体中的字符编码, GET 提交中的参数不出现在请求体中,而出现在请求行。

      1. //设置post请求的字符编码
      2. request.setCharacterEncoding("utf-8");
      3.  
      4. //根据html中的name的名字获取用户在input中填写的值
      5. String username = request.getParameter("username");
      6. String password = request.getParameter("password");
      7. //获取用户勾选的checkbox的值
      8. String[] hobby = request.getParameterValues("hobby");
      9.  
      10. System.out.println(username);
      11. System.out.println(password);
      12. for(String s:hobby){
      13. System.out.println(s);
      14. }

      针对get提交乱码的解决方式
      可以通过修改 Tomcat 默认字符编码的方式来解决 GET 提交方式中携带中文的乱码问题。在 Tomcat 安装目录的 conf/server.xml 中,找到端口号为 8080 的标签,在其中添加 URIEncoding=”UTF-8″的设置,即可将 Tomcat 默认字符编码修改为 UTF-8。

      1. <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

      需要注意的是在修改时要找到正确的server.xml文件。
      双击tomcat服务器,如下图:

      上图中有三个选项,不同的选项表示使用的不同路径下的tomcat

      1. 表示使用eclipse工作空间的tomcat,该路径在工作空间目录中的.metadata.plugins\org.eclipse.wst.server.core\tmp0目录中,如果你使用的是这个(eclipse会默认使用这个),需要修改该目录中的server.xml才会生效。
      2. 表示使用我单独下载的tomcat所在的路径,我本机的是在:F:\monkey1024\apache-tomcat-9.0.0.M26中,如果你使用的是这个,需要修改该目录中的server.xml文件。
      3. 表示自定义一个位置,即手动指定web应用运行的目录位置,如果你使用的是这个,需要修改该目录中的server.xml文件。

      万能解决方案

      1. //根据html中的name的名字获取用户在input中填写的值
      2. String username = request.getParameter("username");
      3. //将数据按照ISO8859-1编码后放到字节数组中
      4. byte[] bytes = username.getBytes("ISO8859-1");
      5. //将字节数组按照UTF-8解码为字符串
      6. username = new String(bytes,"UTF-8");

      先以 ISO8859-1 的形式先对单字节的数据进行编码,并将编码后的数据存放在字节数组中。然

      后,再将字节数组中的数据,按照指定的 UTF-8 格式进行解码,即变为了需要的 UTF-8 字符
      编码的数据,解决了中文乱码问题。
      通过上面的代码就可以解决get和post的乱码问题,但是代码量较大,开发中使用较少。

HttpServletResponse简介

Web服务器收到客户端的http请求,会针对每一次请求,创建一个用于代表响应的HttpServletResponse类型的response对象,开发者可以将要向客户端返回的数据封装到response对象中。

HttpServletResponse向客户端发送数据

ServletResponse 接口有一个方法 getWriter(),用于获取到一个输出流对象 PrintWriter,
该输出流对象是专门用于向客户端浏览器中输出字符数据的,称为标准输出流。

  1. package com.monkey1024.servlet;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. /**
  9. * 使用HttpServletResponse向客户端发送数据
  10. *
  11. */
  12. public class ResponseTest01 extends HttpServlet {
  13. private static final long serialVersionUID = 1L;
  1. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2. //设置post请求的字符编码,此方式只对post请求有效
  3. request.setCharacterEncoding("UTF-8");
  4. //根据html中的name的名字获取用户在input中填写的value值
  5. String username = request.getParameter("username");
  6.  
  7. //从response中取得PrintWriter对象
  8. PrintWriter out = response.getWriter();
  9. //向客户端发送数据
  10. out.print("用户:" + username + "添加成功!<br>");
  11. out.print("感谢您的注册");
  12. //关闭PrintWriter
  13. out.close();
  14. }
  15. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  16. doGet(request, response);
  17. }
  18.  
  19. }

HttpServletResponse响应乱码的解决方案

响应时会产生乱码的原因是在 HTTP 协议中规定,默认响应体的字符编码为ISO-8859-1。所以,若要解决乱码问题,就需要修改响应体的默认编码。一般情况下,有两种方式可以修改:

  • 方法一:HttpServletResponse 的 setCharacterEncoding(“utf-8”)方法,将编码修改为utf-8,然后再通过setHead(“Content-type”,”text/html;charset=UTF-8″);方法告诉客户端浏览器的编码方式。
    代码:

    1. response.setCharacterEncoding("UTF-8");
    2. response.setHead("Content-type","text/html;charset=UTF-8");
  • 方法二:为了简便操作,开发者可以直接使用HttpServletResponse 的 setContentType(“text/html;charset=utf-8”)方法,告诉浏览器的编码方式,该方法相当于方法一种的两条代码。
    代码:
    1. response. setContentType("text/html;charset=UTF-8");

注意:设置响应编码时必须在 PrintWriter 对象产生之前先设置,否则将不起作用。

转发:

  1. /**
  2. * 转发
  3. */
  4. public class Forward01 extends HttpServlet {
  5. private static final long serialVersionUID = 1L;
  6.  
  7. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  8. //设置字符编码
  9. request.setCharacterEncoding("UTF-8");
  10. //获取请求参数
  11. String username = request.getParameter("username");
  12. String password = request.getParameter("password");
  13.  
  14. request.setAttribute("username", username);
  15. request.setAttribute("password", password);
  16.  
  17. //转发
  18. request.getRequestDispatcher("Other").forward(request, response);
  19. }
  20.  
  21. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  22. doGet(request, response);
  23. }
  24.  
  25. }

重定向:

  1. /**
  2. * 重定向
  3. */
  4. public class Redirect01 extends HttpServlet {
  5. private static final long serialVersionUID = 1L;
  6.  
  7. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  8. //设置字符编码
  9. request.setCharacterEncoding("UTF-8");
  10. //获取请求参数
  11. String username = request.getParameter("username");
  12. String password = request.getParameter("password");
  13.  
  14. request.setAttribute("username", username);
  15. request.setAttribute("password", password);
  16.  
  17. //重定向到上面的Other servlet中
  18. response.sendRedirect("Other");
  19. }
  20.  
  21. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  22. doGet(request, response);
  23. }
  24.  
  25. }

当点击之后注意浏览器地址栏中的url是会发生变化的,url后面请求的路径变为了Other。

如果想要重定向到另外一个项目的servlet上时,只需要在sendRedirect加上项目的访问名:

  1. response.sendRedirect("/other-app/Other");

其中other-app是另外项目的访问名。

转发和重定向的区别

  • 请求转发
    1. 浏览器只发出一次请求,收到一次响应
    2. 请求所转发到的servlet2中可以直接获取到请求中所携带的数据
    3. 浏览器地址栏显示的为用户所提交的请求路径
    4. 只能跳转到当前应用的资源中
  • 重定向
    1. 浏览器发出两次请求,接收到两次响应
    2. 重定向到的servlet2不能直接获取到用户提交请求中所携带的数据
    3. 浏览器地址栏显示的为重定向的请求路径,而非用户提交请求的路径。也正因为如此,重定向的一个很重要作用是:防止表单重复提交
    4. 重定向不仅可以跳转到当前应用的其它资源,也可以跳转到到其它应用中资源

请求转发与重定向的选择

  • 若需要跳转到其它应用,则使用重定向。
  • 若是处理表单数据的Servlet1要跳转到另外的Servlet2上,则需要选择重定向。为了防止表单重复提交。
  • 若对某一请求进行处理的 Servlet 的执行需要消耗大量的服务器资源(CPU、内存),此时这个 Servlet 执行完毕后,也需要重定向。
  • 其它情况,一般使用请求转发。

HttpRequest,HttpResponse,乱码,转发和重定向的更多相关文章

  1. JavaWeb(一)Servlet中乱码解决与转发和重定向的区别

    前言 前面其实已经把Servlet中所有的内容都介绍完了,这篇讲补充一点乱码和重定向与转发之间的区别! 一.request请求参数出现乱码问题 1.1.get请求 1)乱码示例 get请求的参数是在u ...

  2. spring mvc 请求转发和重定向(转)

    spring mvc controller间跳转 重定向 传参 url:http://zghbwjl.blog.163.com/blog/static/12033667220137795252845/ ...

  3. spring mvc 请求转发和重定向

    spring mvc controller间跳转 重定向 传参 url:http://zghbwjl.blog.163.com/blog/static/12033667220137795252845/ ...

  4. [摘]HttpContext, HttpRequest, HttpResponse, HttpRuntime, HttpServerUtility

    [摘]http://www.cnblogs.com/fish-li/archive/2011/08/21/2148640.html HttpRuntime HttpRuntime公开了一个静态方法 U ...

  5. Django——20141014深入理解Django HttpRequest HttpResponse的类和实例

    深入理解Django HttpRequest HttpResponse的类和实例 了解META选项 了解中间件 理清所有模板传输模板变量的方式,并作出选择 Django模板系统:如何利用Django模 ...

  6. Servlet中转发和重定向的区别

    Servlet中页面的跳转有两种方式:转发和重定向. 1.转发和重定向的区别 ①转发是服务器行为,重定向是客户端行为. ②转发是浏览器发生了一次请求,重定向至少是两次请求. ③转发地址栏中的url不会 ...

  7. JavaWeb学习之转发和重定向、会话技术:cookie、session、验证码实例、URLConnection使用(下载网页)(4)

    1.转发和重定向 HttpServletResponse response 转发: RequestDispatcher dispatcher = request.getRequestDispatche ...

  8. servlet的转发与重定向

    转发和重定向都能让浏览器获得另外一个URL所指向的资源,但两者的内部运行机制有着很大的区别. 1.转发:有两种方式获得转发对象(RequestDispatcher):一种是通过HttpServletR ...

  9. http页面转发和重定向的区别

    一.调用方式 我们知道,在servlet中调用转发.重定向的语句如下:request.getRequestDispatcher("new.jsp").forward(request ...

随机推荐

  1. Weex开发中的应用小笔记

    内容: 获取输入或其他操作使得值一直改变并在一段不改变的时间后执行下一步操作(输入搜索关键字并执行搜索) https://vuejs.org/v2/guide/computed.html?spm=a2 ...

  2. Django创建项目基本步骤

    1.新建项目 django-admin startproject cmdb(项目名) 2.启动服务python manage.py runserver 0.0.0.0:8000(表示服务监听在8000 ...

  3. python中的向上取整向下取整以及四舍五入的方法

    import math #向上取整print "math.ceil---"print "math.ceil(2.3) => ", math.ceil(2. ...

  4. Jmeter跨线程组传递参数

    Jmeter的线程组之间是相互独立的,各个线程组互不影响,所以线程组A中输出的参数,是无法直接在线程组B中被调用的. 但有时候为了方便,可以把不同模块接口放在不同线程组,就涉及不同线程组传参问题,比如 ...

  5. js动态改变setInterval的时间

    <!DOCTYPE html> <html> <head> <!--meta name="viewport" content=" ...

  6. jeecg自定义datagrid查询

    为什么要写这篇文章? 我们了解,使用 jeecg 提供的 CriteriaQuery 查询方式,确实能满足绝大数的需求,但是往往有那么个比较复杂的情况,需要我们直接去写 sql,比如多表查询呀等等等等 ...

  7. SharePoint 已在此服务器场中安装 ID 为 XXXXXXXXX 的功能。请使用强制属性显式地重新安装此功能。解决方法

    图1: 图2: 解决方法: stsadm -o deploysolution -name ***.wsp -immediate -allowGacDeployment -url http://*** ...

  8. PowerBI更新2019/04 - 解决方案架构 - PowerBI Solution Architecture(一图胜万字!)

    Power BI 架构图 (2019/04) 1) Power BI Desktop 是一个免费的工具.它可以用来准备和管理数据模型:包括链接各种数据:做数据清洗:定义关系:定义度量值和层级关系:应用 ...

  9. CJSON parse.c

    #include <stdio.h> #include <stdlib.h> #include "cJSON.h" void printJson(cJSON ...

  10. 使用Apache JMeter对SQL Server、Mysql、Oracle压力测试(一)

    前段时间面试被问到了数据库方面的知识:比如选择什么样的数据库,如何优化,怎么加索引,于是想到了自己动手测试一下常用数据库的性能: 第一步,下载好JMeter之后打开运行.话说这个JMeter打开还真是 ...