JavaWeb笔记-HTTP协议/request/response

0.HTTP协议-先修知识

注:实例说明

1. 请求消息

在这里插入图片描述

1.1. 请求消息行

- POST  /day08_02/1.html  HTTP/1.1
  • 请求方式: Get(默认) POST DELETE HEAD等

    • GET: 明文传输 不安全,数据量有限,不超过1kb
      例: GET /day08_02/1.html?uName=tom&pwd=123 HTTP/1.1
    • POST: 暗文传输,安全。数据量没有限制。
  • URI: 统一资源标识符。去协议和IP地址。
    协议/版本 : HTTP/1.1

1.2. 请求消息头
从第2行到空行处,都叫消息头
Accept: 浏览器可接受的MIME类型 ,告诉服务器客户端能接收什么样类型的文件。

  • Accept-Charset: 浏览器通过这个头告诉服务器,它支持哪种字符集
  • Accept-Encoding: 浏览器能够进行解码的数据编码方式,比如gzip
  • Accept-Language: 浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。 可以在浏览器中进行设置。
  • Host: 初始URL中的主机和端口
  • Referrer: 包含一个URL,用户从该URL代表的页面出发访问当前请求的页面
  • Content-Type: 内容类型,告诉服务器浏览器传输数据的MIME类型,文件传输的类型,application/x-www-form-urlencoded,If-Modified-Since: Wed, 02 Feb 2011 12:04:56 GMT利用这个头与服务器的文件进行比对,如果一致,则从缓存中直接读取文件。
  • User-Agent: 浏览器类型.
  • Content-Length: 表示请求消息正文的长度
  • Connection:表示是否需要持久连接。如果服务器看到这里的值为“Keep -Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接
  • Cookie: 这是最重要的请求头信息之一 (在讲会话时解析)
  • Date:Date: Mon, 22 Aug 2011 01:55:39 GMT请求时间GMT

1.3.消息正文: 当请求方式是get方式时,才能看见消息正文:uName=tom&pwd=123

2.响应消息

在这里插入图片描述

2.1. 响应消息行
-第一行 POST /day08_02/1.html HTTP/1.1
- HTTP/1.1 200 OK
- 协议/版本 响应状态码 对响应码的描述(一切正常)

  • 响应状态码:常用的就40多个。
    • 200(正常) 一切正常
    • 302/307(临时重定向)
    • 304(未修改):表示客户机缓存的版本是最新的,客户机可以继续使用它,无需到服务器请求。
    • 404(找不到) 服务器上不存在客户机所请求的资源。
    • 500(服务器内部错误)

2.2. 响应消息头

  • Location: http://www.it315.org/index.jsp指示新的资源的位置,通常和302/307一起使用,完成请求重定向
  • Server :apache tomcat指示服务器的类型
  • Content-Encoding: gzip服务器发送的数据采用的编码类型
  • Content-Length: 80 告诉浏览器正文的长度
  • Content-Language: zh-cn服务发送的文本的语言
  • Content-Type: text/html: charset=GB2312服务器发送的内容的MIME类型
  • Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT文件的最后修改时间
  • Refresh: 1;url=http://www.it315.org指示客户端刷新频率。单位是秒
  • Content-Disposition: attachment; filename=aaa.zip指示客户端下载文件
  • Set-Cookie:SS=Q0=5Lb_nQ; path=/search服务器端发送的Cookie
  • Expires: -1
  • Cache-Control: no-cache (1.1)
  • Pragma: no-cache (1.0) 表示告诉客户端不要使用缓存
  • Connection: close/Keep-Alive
  • Date: Tue, 11 Jul 2000 18:23:51 GMT

2.2. 响应正文

  • 和网页右键“查看源码”看到的内容一样。

1、HttpServletRequest

1.1 请求状态行

Get http://localhost:8080/day09/servlet/req1?username=zs http/1.1

  1. getMethod(); 获得请求方式:get
  2. getRequestURL();返回客户端发出请求时的完整URL: http://localhost:8080/day09/servlet/req1
  3. getRequestURI(); 返回请求行中的资源名部分:day09/servlet/req1
  4. getContextPath(); 当前应用的虚拟目录: /day09_01_request
  5. getQueryString() ; 返回请求行中的参数部分,即?之后:username=zs
PrintWriter out = response.getWriter(); // 
out.write(request.getMethod()+"\n"); // 获取浏览器请求方式 
out.write(request.getRequestURL().toString()+"\n");//获取请求地址
out.write(request.getRequestURI()+"\n"); // 获取请求的资源路径
out.write(request.getContextPath()+"\n"); //获取虚拟目录
out.write(request.getQueryString()+"\n"); // 获取请求参数

1.2 请求消息头

  1. String getHeader(String name) 根据头名称得到头信息值
  2. Enumeration getHeaderNames() 得到所有头信息name
  3. Enumeration getHeaders(String name) 根据头名称得到相同名称头信息值
PrintWriter out = response.getWriter();
out.write(request.getHeader("User-Agent")); // 获取浏览器信息
Enumeration<String> headerNames = request.getHeaderNames(); // 获得所有消息信息头
while (headerNames.hasMoreElements()) {
	String headerName = (String) headerNames.nextElement(); // 得到每个消息头名称
	out.write(headerName+":"+request.getHeader(headerName)+"\n"); //打印消息头名称和值
}

1.3 请求正文(重要)

1.3.1 与获取表单数据相关的方法

<input type="text" name="username" />
  1. getParameter(name) 根据表单中name属性的名,获取value属性的值方法
  2. getParameterValues(String name) 专业为复选框取取提供的方法,即获取同名的value值存在数组中
  3. getParameterNames() 得到表单提交的所有name的方法
  4. getParameterMap()得到表单提交的所有值的方法 //做框架用,非常实用
  5. getInputStream() 以字节流的方式得到所有表单数据,常用在上传文件、图片等
    例:1
    register.html
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>register.html<title>
	</head>
	<body>
		<form action="/day09_01_HttpServletRequest/ServerRegisterDemo" method="post">
			用户名:<input type="text" name="usreName"><br>
			密码:<input type="password" name="password"><br>
			性别:<input type="radio" name="sex" value="" checked="checked"><input type="radio" name="sex" value=""><br>
			爱好:
				<input type="checkbox" name="hobby" value="篮球" checked="checked">篮球
				<input type="checkbox" name="hobby" value="唱歌">唱歌
				<input type="checkbox" name="hobby" value="编码">编码
				<br>
			所在城市:
				<select name="city">
					<option>------请选择------</option>
					<option value="bj" selected="selected">北京</option>
					<option value="sh">上海</option>
					<option value="gz">广州</option>
				</select>
				<br>
				<input type="submit" value="注册">
		</form>
	</body>
</html>

ServerRegisterDemo.java

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	//告诉浏览器该用什么编码方式解析前端数据
	request.setCharacterEncoding("UTF-8");
	// 获取表单数据
	
	// 根据表单中的name属性名,过去value属性的值
	String usreName = request.getParameter("usreName");
	String password = request.getParameter("password");
	String sex = request.getParameter("sex");
	String[] hobby = request.getParameterValues("hobby");//多值的情况,几乎是专给复选框用的,即获取同名的value值存在数组中
	String city = request.getParameter("city");
	
	System.out.println("usreName:"+usreName);
	System.out.println("password:"+password);
	System.out.println("sex:"+sex);
	System.out.println("hobby:"+Arrays.toString(hobby));
	System.out.println("city:"+city);
}

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

console

usreName:tao
password:1234
sex:女
hobby:[篮球, 唱歌, 编码]
city:bj

例:2
register2.html

<!DOCTYPE html>
<html>
  <head>
    <title>register2.html</title>
	
    <meta name="keywords" content="keyword1,keyword2,keyword3">
    <meta name="description" content="this is my page">
    <meta name="content-type" content="text/html; charset=UTF-8">
    <meta charset = "utf-8">
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

  </head>
  
  <body>
  	<form action="/day09_01_HttpServletRequest/ServletRegisterDemo2" method="post">
			用户名:<input type="text" name="usreName"><br>
			密码:<input type="password" name="password"><br>
			性别:<input type="radio" name="sex" value="" checked="checked"><input type="radio" name="sex" value=""><br>
			爱好:
				<input type="checkbox" name="hobby" value="篮球" checked="checked">篮球
				<input type="checkbox" name="hobby" value="唱歌">唱歌
				<input type="checkbox" name="hobby" value="编码">编码
				<br>
			所在城市:
				<select name="city">
					<option>------请选择------</option>
					<option value="bj" selected="selected">北京</option>
					<option value="sh">上海</option>
					<option value="gz">广州</option>
				</select>
				<br>
				<input type="submit" value="注册">
		</form>
  </body>
</html>

ServletRegisterDemo1.java

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	request.setCharacterEncoding("UTF-8");
	Enumeration<String> pNames = request.getParameterNames();
	while (pNames.hasMoreElements()) {
		String pname = (String) pNames.nextElement();
		String[] pValues = request.getParameterValues(pname);
			System.out.print(pname+":");
			for (String pValue : pValues) {
			if (pValue.isEmpty()) {
				System.out.println("null");
			}else {
				System.out.println(pValue);
			}
		}				
	}
}

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

console

usreName:123
password:11233
sex:男
hobby:篮球
hobby:唱歌
city:sh
  • getParameterMap()得到表单提交的所有值的方法 //做框架用,非常实用
request.setCharacterEncoding("UTF-8");
Map<String, String[]> parameterMap = request.getParameterMap();
for (Entry<String, String[]> entry : parameterMap.entrySet()) {
	System.out.println(entry.getKey()+":"+Arrays.toString(entry.getValue()));
}

console

usreName:[3]
password:[]
sex:[男]
hobby:[篮球, 唱歌, 编码]
city:[bj]
  • 实际应用,将表单的数据封装到JavaBean中
    User.java
// 在实体类中的字段要与表单中的name名一直,约定优于编码

private String usreName;
private String password;
private String sex;
private String[] hobby;
private String city;

public String getUsreName() {
	return usreName;
}
public void setUsreName(String usreName) {
	this.usreName = usreName;
}
public String getPassword() {
	return password;
}
public void setPassword(String password) {
	this.password = password;
}
public String getSex() {
	return sex;
}
public void setSex(String sex) {
	this.sex = sex;
}
public String[] getHobby() {
	return hobby;
}
public void setHobby(String[] hobby) {
	this.hobby = hobby;
}
public String getCity() {
	return city;
}
public void setCity(String city) {
	this.city = city;
}
@Override
public String toString() {
	return "User [usreName=" + usreName + ", password=" + password + ", sex=" + sex + ", hobby="
			+ Arrays.toString(hobby) + ", city=" + city + "]";
}

原生实现对数据的封装:Servlet.java

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	request.setCharacterEncoding("UTF-8");
	User user = new User();
	System.out.println("封装数据前的user:"+user);
	
	try {
		Map<String, String[]> parameterMap = request.getParameterMap();
		for (Entry<String, String[]> entry : parameterMap.entrySet()) {
			String key = entry.getKey();
			String[] value = entry.getValue();
			
			// 创建一个属性描述器
			PropertyDescriptor pd = new  PropertyDescriptor(key, User.class);
			// 得到User类的setter方法
			Method setter = pd.getWriteMethod();
			// 设置user对象的字段
			if (value.length<2) {
				setter.invoke(user, value[0]);
			}else {
				setter.invoke(user, (Object)value);
			}
		}
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	System.out.println("封装数据后的user:"+user);

}

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

工具实现对数据的封装:Servlet.java

  • 工具包:commons-beanutils-1.8.3.jar
  • 工具包 >依赖包:commons-logging-1.1.1.jar
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	request.setCharacterEncoding("UTF-8");
	try {
		User user = new User();
		System.out.println("封装前的user:"+user);
		
		// 通过工具类BeanUtils.populate(Object bean, Map properties)封装数据;
		BeanUtils.populate(user, request.getParameterMap());
		
		System.out.println("封装后的user:"+user);
	} catch (Exception e) {
		e.printStackTrace();
	}
}

1.3.2 与操作非表单数据相关的方法(request也是一个域对象)

  1. void setAttribute(String name, Object value);
  2. Object getAttribute(String name);
  3. Void removeAttribute(String name);

1.3.3 与请求转发相关的方法

  1. RequestDispatcher getRequestDispatcher(String path) //得到请求转发或请求包含的协助对象
  2. forward(ServletRequest request, ServletResponse response) //转发的方法
  3. include(ServletRequest request, ServletResponse response) //请求包含,将被包含的Servlet里面的代码拿到包含的Servlet里执行,等于是2合一-
  • 例:. include(ServletRequest request, ServletResponse response)
String path = "/demo"
request.getRequestDispatcher(path).include(request, response);
  • 例:
    -ServletDemo5_RequestDispatcher.java
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	request.setCharacterEncoding("UTF-8");
	response.setContentType("text/html;charset=UTF-8");
	System.out.println("A:我想办事");
	System.out.println("B:我办不了,但是我可以找人帮你办");
	
	// 将非表单数据添加到request域中
	request.setAttribute("file", "办事材料");
	
	// request请求转发,服务器将直接进行重定向,所以浏览器的地址栏的地址不会发生变化
	// request请求转发与response的重定向不同,response的重定向是服务器将需要重定向的操作告诉浏览器,由浏览器来决定要不要重定向
	
	RequestDispatcher rd = request.getRequestDispatcher("/ServletDemo6_RequestDispatcher");
	rd.forward(request, response);
	
	System.out.println("B:找人帮你办理了");
}

ServletDemo6_RequestDispatcher.java

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	request.setCharacterEncoding("UTF-8");
	response.setContentType("text/html;charset=UTF-8");
	
	System.out.println("B:帮A办点事");
	
	// 获取request域中传递的数据
	String file = (String)request.getAttribute("file")
	
	System.out.println("C:材料齐全--" + file );
	System.out.println("C:A的事儿办好了");
}

console

A:我想办事
B:我办不了,但是我可以找人帮你办
B:帮A办点事
C:材料齐全--办事材料
C:A的事儿办好了
B:找人帮你办理了

1.3.4 与请求编码相关的方法:

  1. request.setCharacterEncoding(“UTF-8”); //解决post方式编码,告诉服务器客户端什么编码,只能处理post请求方式

  2. String name = new String(name.getBytes(“iso-8859-1”),”UTF-8”); //解决get方式编码

2、HttpServletResponse

2.1 响应状态行

/*  告诉浏览器重定向:
	重定向的理解:
	1.浏览器先访问servlet1
	2.servlet1收到浏览器的请求后,告诉浏览器你的请求我没法帮你完成,请你重定向到servlet2,她可以给你完成,同时把需要重定向的信息"302",和重定向地址一起反馈给浏览器 
	3.浏览器收到servlet1的反馈信息"302"后,知道需要重定向,根据反馈的地址重新访问servlet2,(相当于重新在地址栏输入servlet2的地址,进行访问)
*/
response.setStatus(302); // 302 代表需要重定向
response.setHeader("location", "/day09_00_HttpServletResponse/ServletDemo8"); //重定向地址
// 重定向需要以上两句话同时使用
/*关于重定向的地址:在这里是返回去浏览器在重定向,所以这里的地址是从服务器的根目录"/"下面的网站的根目录"/day09_00_HttpServletResponse"下去找到servlet; 
如果是在服务器去访问,那么"/"就是代表的是当前网站的根目录也就是:"day09_00_HttpServletResponse/"*/

// 重定向方法二,等于上面的两行合在一起
response.sendRedirect("/day09_00_HttpServletResponse/ServletDemo8");// 直接给出浏览器需要重新访问的地址

2.2 响应消息头

// 设置头 告诉浏览器不使用缓存
response.setHeader("pragma", "no-cache");
response.setHeader("cache-control", "no-cache");
response.setHeader("expires", "0");

response.setHeader("refresh","3;url=...") // 告诉3秒钟后刷新,跳转到...页面

// 告诉浏览器下载文件
fileName = URLEncoder.encode(fileName, "utf-8"); // 将不安全的文件名改为utf-8格式
response.setHeader("content-disposition","attachment;filename=" + fileName); // 告诉浏览器下载文件

2.3 响应正文

response.setCharacterEncoding("UTF-8"); // 告诉服务用什么编码方式

response.setHeader("content-type","text/html;charset=UTF-8"); // 告诉浏览器使用什么编码方式

response.setContentType("text/html;charset=UTF-8"); // 同时告诉服务器和浏览器用什么编码方式

response.getWrite().write("你好"); // 字符输出流

response.getOutputStream().write("你好".getBytes());  // 字节输出流 

2.4 response注意细节

  1. getOutputStream()和getWrite()方法分别用于得到输出二进制数据和输出文本数据的ServletOutputStreamh和Printwriter对象。
  2. getOutputStream()和getWrite()两个方法互相排斥,在一个Servlet中只能调用一个方法。
  3. Servlet程序向getOutputStream或者getWrite对象中写入的数据,将被Servlet引擎(如:tomcat服务器)从response里面获取,Servlet引擎将这些数据当做响应消息的正文,然后在于响应状态行和各种响应头组合后输出到客户端。
  4. Servlet的service方法结束后,Servlet引擎将检查getOutputStream()/getWrite()方法返回的输出流对象是否调用close()方法,如果没有,Servlet引擎将会自动调用close()方法关闭该输出流对象。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值