request和response

我们在前面了解了前端页面与后台的联系,以及doGet和doPost的区别,我们知道,浏览器打开一个网页,就是对服务器端的一次请求,这个请求根据get和post的请求方式进入到应该进入的doGet和doPost的方法中,进行数据的处理,按照正常来说,应该是前端对后台进行访问,发出一次请求,那么理当也应该得到一次响应,以及在前面也牵扯了一些随着请求把数据传输到后台的案例,那么,我们现在来仔细的进行分析请求和响应这两个web项目中最重要的事情。


request和response

我们现在练习的时候,一般都是利用自己电脑的浏览器访问自己做的web项目,Tomcat服务器也是跑在自己的电脑上的,浏览器地址栏里访问地址一般都以:localhost:8080/开头。我们知道以后如果工作或者自己想要开发自己上线的项目,那么这个项目一定是连接到互联网上才可以让其他人能够访问的,所以在开始了解请求和响应之前,我们应该简单的了解一下我们现在所使用的的网络环境。

Http协议

我们自己联系使用的:   localhost:8080 /项目名/资源名  ,全称为:http:// localhost:8080 /项目名/资源名

以及我们在网上进行访问的,比如csdn的官网:https://www.csdn.net/   也都是以https://开头的。(这里以https和http的区别为,https的信息是以加密形式传输的,提高了数据的安全性,其他的都和http一模一样)

以http开头进行标识的意思就是,这里所使用的网络协议,都是使用的http://协议。即使是在自己电脑上访问自己的项目,也是通过http协议进行信息传输的。

Http协议版本

现在的Http版本有1.0 、 1.1

区别为:

       1.0版本不支持常连接,也就意味着课程一个网页要对服务器发起N次连接请求,会有N次握手的机会,耽误时间。

                      例如:网站有100张图片,会连接服务器100次,握手100次。

       1.1版本支持了常连接=

                      例如:网站有100张图片,会连接服务器100次,握手1次。

                                                             现在互联网使用的版本都为1.1版本

Http协议特点为无状态性,就是一次请求对应一次响应,而下一次请求将和上一次的请求响应没有任何关系,不会对上次的请求和响应进行任何的记录,以此来提高信息传递的安全性。


response

介绍过了网络协议,我们先来了解响应:response。

我们新建一个Servlet  :

package com.yht.servlet;

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 HttpResponseTest extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//向控制台打印,表示doGet方式执行了。
		System.out.println("goGet方法执行了.....");
		
		
		//向前端页面进行传输,传输一段字符串,由浏览器进行解析。注意:这里还不能传输中文。
		PrintWriter out = response.getWriter();
		out.print("<h1> hello  </h1>");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//这里的意思是不管发过来的是什么请求,最后都转向doGet方法,在doGet方法里也可以这样调用doPost。
		doGet(request, response);
	}

}

我们可以看到doGet和doPost方法中都有两个参数,一个是HttpServletRequest对象,一个是HttpServletResponse对象。

这两个对象,就分别存储着 请求传输的所有信息, 一个存储着要进行响应的所有信息。

我们这里是想要进行响应,所以就利用response参数对服务器端进行响应。

我们运行项目,在浏览器中输入地址(推荐用火狐浏览器,因为里面大部分为中文,可以看得更清晰。)输入地址栏后不用急着回车访问,先按f12,打开配置,然后点击网络选项,然后再进行访问:

我们就会点击下图的蓝色请求,就会出现这样的框架

我们可以看到这边有着很多的参数,而这些参数,就是基于这次请求和响应的。我们先来对响应进行分析这些参数的作用和代表的意思。

响应行

上面大图中消息头里面的这部分内容,就是我们这次访问响应行。里面存储的信息为:协议及版本 | 状态码

而这里的状态码 绿色的200代表着这次访问是成功的。比如我们平常会遇到的404,也是响应码,意思是,页面没有找到。

更多响应码:http://tools.jb51.net/table/http_status_code

我们可以自己设置这次响应,返回什么状态码,以及返回的状态码所对应的信息:

依照上面的代码把doGet方法修改为:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		/*//向控制台打印,表示doGet方式执行了。
		System.out.println("goGet方法执行了.....");
		
		
		//向前端页面进行传输,传输一段字符串,由浏览器进行解析。注意:这里还不能传输中文。
		PrintWriter out = response.getWriter();
		out.print("<h1> hello  </h1>");*/
		
		response.setStatus(404);
		response.sendError(404, "sorry,sorry,sorry");

	}

然后再次运行访问:

这里的提示信息就变成了我们预设好的提示信息。

响应头

这里面的信息,就是我们的响应头里面的信息。这里面只是显示了一部分。

这上面的东西,大部分都是了解即可。不用全部记住。知道有这些东西,真需要了再去了解具体的使用都可以。

响应头里面的信息也都是我们在后台可以自己设置的。我们来演示比较常用而且重要的:

重要响应头:

编辑代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		response.setHeader("refresh", "3;url=https://blog.csdn.net/qq_39565202");
		
	}

演示:

 

 

第二个重要响应头:

我们再次修改代码:

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

		//向前端页面进行传输,传输一段字符串,由浏览器进行解析。注意:这里还不能传输中文。
		PrintWriter out = response.getWriter();
		out.print("<h1>好吃的都给你</h1>");

	}

访问:

然后我们加上:

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

		response.setHeader("Content-Type", "text/html;charset=UTF-8");
		
		PrintWriter out = response.getWriter();
		out.print("<h1>好吃的都给你</h1>");

	}

          

这样就解决了响应的传输不能传输中文的问题。

 

第三个重要响应头:

设置代码:

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

		response.setStatus(302);
		response.setHeader("Location", "https://blog.csdn.net/qq_39565202");
		
	}

运行:

我们可以看到我们输入的地址栏是我们的servlet的地址,但是进行访问后直接跳转到了我们在代码中写入的页面。

这就是    重定向

重定向是一个非常重要的概念。

这里代码的意思是:

response.setStatus(302);    当程序运行到这句话的时候,就返回一个302状态码,意思为让浏览器去访问另一个资源

response.setHeader("Location", "https://blog.csdn.net/qq_39565202");      这句告诉浏览器要去访问的资源的地址。

 

响应体

上面的响应行其实就是响应头的第一行,他们设定了一些基本的属性,而数据的传递主要依赖的就是   : 响应体。

响应体的应用主要有以下几个方面:

第一:通过PrintWriter向浏览器端打印信息。

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//这里是响应头对信息格式的设置方法
		//response.setHeader("Content-Type", "text/html;charset:utf-8");
		
		//这里是响应体对信息格式的设置方法,两个功能是一样的,不过相比这个更加简洁一点。
		response.setContentType("text/html;charset=utf-8");
		
		PrintWriter out = response.getWriter();
		out.print("<h1>好吃的都给你<h1>");
		
	}

第二:通过Response对象获取输出流

我们上面其实也是使用的流,响应体的对象信息时无限长的,所以一般用来传输大量的信息,比如我们在网络进行的下载。

而上面的只是对文字进行打印。是字符流,里面进行文字的解析,如果是html语句,浏览器会自动进行解析。我们还可以使用字节流进行文件的传输。这里还是先对文本进行传输表示一下可以对字节型数据进行传输。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//这里是响应头对信息格式的设置方法
		//response.setHeader("Content-Type", "text/html;charset:utf-8");
		
		//这里是响应体对信息格式的设置方法,两个功能是一样的,不过相比这个更加简洁一点。
		response.setContentType("text/html;charset:utf-8");
		
		/*PrintWriter out = response.getWriter();
		out.print("<h1>好吃的都给你<h1>");*/
		
		
		OutputStream os = response.getOutputStream();
		os.write("<h1>前程有梦乘帆远行</h1>".getBytes());//因为参数类型为字节,或者字节数组,所以这里转换为字节数组
		
	}

                            在编码格式里,使用字节流时   charset=utf-8  改成了  charset:utf-8   一定要修改,否则会乱码


		//这里是响应头对信息格式的设置方法
		//response.setHeader("Content-Type", "text/html;charset:utf-8");
		
		//这里是响应体对信息格式的设置方法,两个功能是一样的,不过相比这个更加简洁一点。
                response.setContentType("text/html;charset:utf-8");
		/*
		 *  设置响应体的编码字符集为utf-8
			设置浏览器的解码字符集为utf-8
			告知浏览器响应体里是html代码,需要进行解析
			乱码解决的设置代码,必须放在获取字节流/字符流之前
                        还有一点就是,在一次响应里,不能够字节流和字符流共有,只可以有一个,否则会报错。
		 */
		

                                   

总结来说,响应的应用主要有:

①利用响应行:查看和设置响应状态码

②利用响应头或者响应行:设置编码格式

③利用响应体:获取流来进行数据的传输

 

而请求的应用和重要性,相对来说是超过响应的。


request

我们来做这样一个网页:

<!DOCTYPE html>
<html>   
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="aaa"/>
<script src="vvv"></script>
</head>
<body>
	<img src="xxx" />
</body>
</html>

这个网页什么也没有,我们可以访问一下,然后再f12在网络界面中观察。

(最后一个是 Tomcat 服务器的小猫的 图标的请求,可以忽略)

 

我们对比可以看到,这里面一共有四个主要的请求,分别是html文件本身 以及  link   img   script  等标签发出来的,所以我们可以得知,所有想要访问服务器端资源的都会发出一次请求,而不是整体发出一次请求(超链接或者按钮等是点击时会进行发送请求)

请求行

我们来观察:

这里就是显示出来的请求行部分的信息,但是其实远不止这些,我们可以通过以下方法来获取请求行中的信息:

方法声明

功能描述

String getMethod()

该方法用于获取HTTP请求消息中的请求方式(如GET、POST等)

 

忽略大小写判断请求方式

 

String getRequestURI()

该方法用于获取请求行中资源名称部分,即位于URL的主机和端口之后、参数部分之前的部分

 

仅获取资源名,不包含参数列表

 

String getQueryString()

该方法用于获取请求行中的参数部分,也就是资源路径后面问号(?)以后的所有内容

String getProtocol()

该方法用于获取请求行中的协议名和版本,例如,HTTP/1.0或HTTP/1.1

String getContextPath()

该方法用于获取请求URL中属于WEB应用程序的路径,这个路径以“/”开头,表示相对于整个WEB站点的根目录,路径结尾不含“/”。如果请求URL属于WEB站点的根目录,那么返回结果为空字符串("")

 

动态获取项目名称。

例如:/day12

 

String getServletPath()

该方法用于获取Servlet的名称或Servlet所映射的路径

 

url-pattern

String getRemoteAddr()

该方法用于获取请求客户端的IP地址,其格式类似于“192.168.0.3”

 

本机:

0:0:0:0:0:0:0:1

localhost

127.0.0.1

 

统计IP

 

String getRemoteHost()

该方法用于获取请求客户端的完整主机名,需要注意的是,如果无法解析出客户机的完整主机名,该方法将会返回客户端的IP地址

int getRemotePort()

该方法用于获取请求客户端网络连接的端口号

String getLocalAddr()

该方法用于获取Web服务器上接收当前请求网络连接的IP地址

String getLocalName()

该方法用于获取Web服务器上接收当前网络连接IP所对应的主机名

int getLocalPort()

该方法用于获取Web服务器上接收当前网络连接的端口号

接收请求的端口号

String getServerName()

该方法用于获取当前请求所指向的主机名,即HTTP请求消息中Host头字段所对应的主机名部分

int getServerPort()

该方法用于获取当前请求所连接的服务器端口号,即如果HTTP请求消息中Host头字段所对应的端口号部分

发送响应的端口号

String getScheme()

该方法用于获取请求的协议名,例如http、https或ftp

StringBuffer getRequestURL()

该方法用于获取客户端发出请求时的完整URL,包括协议、服务器名、端口号、资源路径等信息,但不包括后面的查询参数部分。注意,getRequestURL()方法返回的结果是StringBuffer类型,而不是String类型,这样更便于对结果进行修改

 

获取到包含http协议的资源路径,不包含参数列表

 

演示:

package com.yht.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RequestTest1Servlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		String method = request.getMethod();
		System.out.println("访问方法::"+method);
		
		String url = request.getRequestURL().toString();
		System.out.println("访问地址:"+url);
		
		String uri = request.getRequestURI();
		System.out.println("uri:"+uri);//资源标志符
		
		String protocal = request.getProtocol();
		System.out.println("协议版本:"+protocal);
		
		String scheme = request.getScheme();
		System.out.println("协议名:"+scheme);
		
		String contextPath = request.getContextPath();
		System.out.println("项目名:"+contextPath);
		
		String id = request.getRemoteAddr();
		System.out.println("客服端ip地址"+id);
		
		String queryString = request.getQueryString();
		System.out.println("参数(?后带的值):"+queryString);
		
	}


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

}

页面调用:

<!DOCTYPE html>
<html>   
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a href="RequestTest1Servlet?name=yht&age=22">查看请求行内容</a>
</body>
</html>

访问页面点击超链接结果:

访问方法::GET
访问地址:http://localhost:8080/Servlet02/RequestTest1Servlet
uri:/Servlet02/RequestTest1Servlet
协议版本:HTTP/1.1
协议名:http
项目名:/Servlet02
客服端ip地址127.0.0.1
参数(?后带的值):name=yht&age=22

其他的都不太重要,有兴趣的可以自行演示。

 

请求头

这些是我们浏览器里f12网络栏里的请求头信息。同样,与response不同的是,这里都是只读信息,不能进行更改。

这些都存在于request中,我们也可以进行获取。

修改上面的Servlet代码为:

package com.yht.servlet;

import java.io.IOException;
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 RequestTest1Servlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		String agent = request.getHeader("User-agent");
		System.out.println("浏览器版本为:"+agent);
		
		String conn = request.getHeader("Connection");
		System.out.println("连接方式为:"+conn);
		
		System.out.println("------------以下为全部---------------");
		
		Enumeration<String> headerNames = request.getHeaderNames();
		while(headerNames.hasMoreElements()){
			String key = headerNames.nextElement();
			System.out.println(key+"-----"+request.getHeader(key));
		}
	}


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

}

访问页面,点击超链接,观察后台控制台:

浏览器版本为:Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0
连接方式为:keep-alive
------------以下为全部---------------
host-----localhost:8080
user-agent-----Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0
accept-----text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
accept-language-----zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
accept-encoding-----gzip, deflate
connection-----keep-alive
referer-----http://localhost:8080/Servlet02/requestTest.html
upgrade-insecure-requests-----1

请求体

请求体其实就是我们进行请求时从前端传给后台主要数据的通道,get方式是没有请求体的,因为它的参数都通过url上直接进行传输了。

只有post请求方式时会产生请求体。不过通过get请求方式发送的参数和post产生的请求体里的参数都可以通过同样的方法获取。

我们进行post请求的请求体内的参数和get请求后面url后面如果缀的有参数的话都会显示到:

编写一个页面:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <form action="ServletRequestServlet2" method="post">
	username:<input type="text" name="username" /><br/>
	password:<input type="text" name="password" /><br/>
	hobby:<input type="checkbox" name="hobby" value="python">python
			<input type="checkbox" name="hobby" value="c">c
			<input type="checkbox" name="hobby" value="java">java<br/>
	address:<select name="address" >
		<option value="bj">北京</option>
		<option value="sh">上海</option>
		<option value="zz">郑州</option>
		
	</select><br/>
	<input type = "submit"  value ="提交">
	</form>
</body>
</html>

观察下面参数:

然后我们在去接受数据的Servlet中进行接受:

package com.yht.servlet;

import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		/*String username = request.getParameter("username");
		String password = request.getParameter("password");
		String[] hobby = request.getParameterValues("hobby");
		String address = request.getParameter("address");
		System.out.println(username+"\t"+password+"\t"+Arrays.toString(hobby)+"\t"+address);*/
		
		//yht	yht	[python, c, java]	sh
		
		/*Enumeration<String> re = request.getParameterNames();
		while(re.hasMoreElements()){
			String key = re.nextElement();
			System.out.println(key+"-----"+request.getParameter(key));
		}*/
		
		/*
		 *  username-----yht
			password-----yht
			hobby-----python
			address-----sh
		 */
		
		Map<String, String[]> map = request.getParameterMap();
		Set<Entry<String, String[]>> entrySet = map.entrySet();
		for(Map.Entry<String, String[]> entry:entrySet){
			System.out.println(entry.getKey()+"-----"+Arrays.toString(entry.getValue()));
		}
		/*
		 *  username-----[yht]
			password-----[yhttt]
			hobby-----[python, c, java]
			address-----[sh]
		 */
		
	}

}

三种接收方式,第一种当数据很多时比较好费时间,第二种无法接收传输类型为数组的全部元素,只能接收第一个,第三种较为完善。


到此,所有相关request和response的差不多都已经介绍完了。如果有看到这篇博客的盆友对此篇有问题,欢迎下面评论留言。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值