Javaweb:Request和Response

Http协议简介

HTTP协议即超文本传输协议。是客户端和服务端交互时,数据的格式规范。分为HTTP请求和HTTP响应。

  • 浏览器向服务器请求某个web资源时,称之为浏览器向服务器发送了一个http请求。
  • 一个HTTP响应代表着服务器向浏览器回送数据。

简单来说就是:请求:客户端发送给服务端的数据;响应:服务端发送给客户端的数据。

请求和响应分为行,头,体。先有请求后有响应,没有请求就没有响应。

HttpServletRequest

概述

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。

request就是将请求文本封装而成的对象,所以通过request能获得请求文本中的所有内容,请求头、请求体、请求行

一个请求的例子:

请求行、请求头、请求体

请求行

  • 本次请求的基本信息
  • 格式:请求方式 请求资源 协议版本
  • 例如POST /day29/demo01 HTTP/1.1

请求头

  • 本次请求的附加信息
  • 格式:一行一个键值对,一个键值对是一个请求头,一次请求可以有多个请求头
  • 例如:Referer:http://localhost:8080/day29/_01http.html
  • 相关方法:
    • String getHeader(String name) 根据头名称得到头信息值
    • long getDateHeader(java.lang.String name) 获得指定头内容Date
    • int getIntHeader(java.lang.String name) 获得指定头内容int
    • Enumeration getHeaderNames() 得到所有头信息name
    • Enumeration getHeaders(String name) 根据头名称得到相同名称头信息值

代码示例:

Enumeration<String> headerNames = req.getHeaderNames();
        while(headerNames.hasMoreElements()){
            String key = (String)headerNames.nextElement();
            String value = req.getHeader(key);
            System.out.println(key+"="+value);
        } 

请求体

  • 本次请求的正文数据,是提交的表单参数
  • 格式:表单数据的提交格式 name=value&name=value&…
  • 例如:username=lisi
  • 注意:只有是POST提交,必须有带name属性的表单项,这时候请求体里才有数据;否则没有请求体
  • 与表单获取相关的方法:
    • String getParameter(name) :根据表单中name属性的名,获取value属性的值方法
    • String[] getParameterValues(String name):专为复选框取取提供的方法
    • getParameterNames():得到表单提交的所有name的方法
    • Map<String , String[]> getParameterMap(): 得到表单提交的所有值的方法 //做框架用,非常实用
    • getInputStream: 以字节流的方式得到所有表单数据
  • 与操作非表单数据相关的方法(request也是一个域对象):
    • void setAttribute(String name, Object value);
    • Object getAttribute(String name);
    • Void removeAttribute(String name);
  • 与请求转发相关的方法:
    • RequestDispatcher getRequestDispatcher(String path) //得到请求转发或请求包含的协助对象
    • forward(ServletRequest request, ServletResponse response) //转发的方法
    • include(ServletRequest request, ServletResponse response) //请求包含
  • 与编码相关的方法:
    • 解决post方式编码
      • request.setCharacterEncoding("UTF-8") :告诉服务器客户端什么编码,只能处理post请求方式
    • 解决get方式编码
      • String name = new String(name.getBytes(“iso-8859-1”),”UTF-8”);

补充:其他常用请求方法

  • getMethod();
  • getRequestURL();
  • getRequestURI();
  • getServerName();
  • getServerPort();
  • getContextPath();
  • getServletPath();
  • getQueryString();
  • getRemoteAddr();
  • getProtocol();

示例:

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //1.统一资源标记符   /Web_Servlet/ServletTest3
    String uri = req.getRequestURI();
    System.out.println(uri);
    //2.统一资源定位符    http://localhost:6060/Web_Servlet/ServletTest3 
    StringBuffer url = req.getRequestURL();
    System.out.println(url);
    //3.协议和版本    HTTP/1.1
    String potocol = req.getProtocol();
    System.out.println(potocol);
    //4.协议    http
    String scheme = req.getScheme();
    System.out.println(scheme);
    //5.主机(域名)  localhost,如果你使用的是ip地址,就显示ip地址
    String serverName = req.getServerName();
    System.out.println(serverName);
    //6.端口  6060(这是我自己修改了的端口,默认是8080)
    int port = req.    getServerPort();
    System.out.println(port);
    //7.发布到tomcat下的项目名称  /Web_Servlet
    String contextPath = req.getContextPath();
    System.out.println(contextPath);
    //8.servlet路径    /ServletTest3 
    String servletPath = req.getServletPath();
    System.out.println(servletPath);
    //9.获取所有请求参数,即?之后所有东西。    username=faker&password=mid
    String queryString = req.getQueryString();
    System.out.println(queryString);
    //10.远程主机的ip地址    0:0:0:0:0:0:0:1
    String remoteAddr = req.getRemoteAddr();
    System.out.println(remoteAddr);   
}

总结几个常用的方法

  • 获取请求行的数据

    • 获取请求方式数据
      • 语法:Request对象.getMethod():
      • 方法返回对应的请求方式字符串 (常见的请求方式 get/post)
      • 一般默认请求方式都是get,只有指定了post才会有post请求。
    • 获取请求行中项目路径
      • 语法:Request对象.getContextPath();
      • 方法返回对应的项目路径字符串
    • 获取客户端IP
      • 语法:Request对象.getRemoteAddr();
      • 方法返回访问客户的IP地址
  • 获取请求头的数据

    • 获取指定请求头的值
      • 语法:Request.getHeader(键)
      • 在请求头中,数据以键值对的方式进行存储,传入键,获取值
    • 获取所有请求头的值
      • 语法:Request.getHeaderNames()
      • 以枚举对象的形式,返回所有请求头的值.
  • 获取请求体的数据

    • 获取单值参数:String value = request.getParameter(标签体的name属性)
    • 获取多值参数:String[] values = request.getParametreValues(标签体的name属性)
    • 获取所有参数:Map<String, String[]> map = request.getParameterMap()

获取表单数据出现乱码的问题

Get方式不会出现乱码,因为Tomcat 8版本以上的为我们解决了。

Post方式则会出现乱码问题:一切乱码原因都是因为解码和编码方式不同

  • request默认采用iso-8859字符集解码,而我们的页面是utf-8字符集编码
  • 解决方法:修改解码方式,语法:Request.setCharacterEncoding(“utf-8”)
  • 注意:必须在接收参数之前执行

request域对象的理解

Request是域对象,由Servlet规范提供的,能够存取数据的对象,在其作用范围里可以共享数据。

不同域对象的区别:作用范围不同

域对象存取数据的方法:

  • 存数据:setAttribute(String name, Object value)
  • 取数据:getAttribute(String name)
  • 删数据:removeAttribute(String name)

request域对象的作用范围:

  • 何时创建:一次请求开始
  • 何时销毁:一次请求结束
  • 作用范围:一次请求期间

Request底层原理图

HttpServletResponse

概述

Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。request和response对象即然代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了。要向容器输出数据,只需要找response对象就行了。
HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法。

先看一个图片总览来对response建立印象

Response响应数据

如上图所示,我们能很快发现response的几个关键术语,比如响应头、响应体、状态码等

在一个访问过程中我们可以看到如下图所示的响应信息:

响应行的数据表示http协议版本为HTTP/1.1,状态码为200,这个状态码的描述是OK。

关于响应状态码

响应状态码:服务器告诉客户端(浏览器)本次请求和响应的一个状态

状态码都是3位数字

  • 1xx:服务器接收客户端消息,但没有接收完成,等待一段时间以后,发送1xxx状态码
  • 2xx:成功,代表:200
  • 3xx:重定向,代表:302(重定向)304(访问缓存)
  • 4xx:客户端错误,代表404(请求路径中没有响应的资源)405(请求方式与处理方法没有对应)
  • 5xx:服务端错误,代表500(服务器内部错误)

响应头中的数据

  • Content-Type: text/html —— 表示数据类型
  • Content-Length: 137 —— 表示数据长度
  • Date: Sun, 01 Mar 2020 10:19:50 GMT —— 日期

可以对应上面的图片来查看响应头的相关信息。

Response工作流程

相关方法

  • setStatus(int sc) 设置响应状态码
  • setHeader(String name, String value) 设置响应头信息
  • getWrite(); 字符输出流
  • getOutputStream(); 字节输出流
  • setCharacterEncoding(String charset) 告知服务器使用什么编码
  • setContentType(String type) 告诉响应的内容类型(text/html,application/json等)

题外话1:两种setCharacterEncoding

request.setCharacterEncoding()指定后可以通过getParameter()则直接获得正确的字符串,如果不指定,则默认使用iso8859-1编码。值得注意的是在执行setCharacterEncoding()之前,不能执行任何getParameter()。而且,该指定只对POST方法有效,对GET方法无效。
分析原因,应该是在执行第一个getParameter()的时候,Java将会按照编码分析所有的提交内容,而后续的getParameter()不再进行分析,所以setCharacterEncoding()无效。而对于GET方法提交表单是,提交的内容在URL中,一开始就已经按照编码分析提交内容,setCharacterEncoding()自然就无效。

response.setCharacterEncoding设置HTTP 响应的编码,如果之前使用response.setContentType设置了编码格式,则使用response.setCharacterEncoding指定的编码格式覆盖之前的设置.与response.setContentType相同的是,调用此方法,必须在getWriter执行之前或者response被提交之前

request和response经常会涉及到重定向和转发,将在下一个专题中提及。

原文地址:https://www.cnblogs.com/kylinxxx/p/14234544.html