http
1. http简介
HTTP(HyperText Transfer Protocol)即超文本传输协议,是一种详细规定了浏览器和万维网服务器之间互相通信的规则,它是万维网交换信息的基础,它允许将HTML(超文本标记语言)文档从Web服务器传送到Web浏览器。
它的发展是万维网协会(World Wide Web Consortium)和Internet工作小组IETF(Internet Engineering Task Force)合作的结果,(他们)最终发布了一系列的RFC,RFC 1945定义了HTTP/1.0版本。其中最著名的就是RFC 2616。RFC 2616定义了今天普遍使用的一个版本——HTTP 1.1。
HTTP是一种无状态的协议,无状态是指Web浏览器与Web服务器之间不需要建立持久的连接,这意味着当一个客户端向服务器端发出请求(Request),然后Web服务器返回响应(Response),连接就被关闭了,在服务器端不保留连接的有关信息。也就是说,HTTP协议永远都是客户端发起请求,服务器回送响应。
HTTP工作流程
1 首先客户机与服务器需要建立连接。只要单击某个超级链接,HTTP的工作开始。
2 建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。
3 服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。
4 客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上,然后客户机与服务器断开连接。
一次HTTP操作称为一个事务,某一步出现错误,那么产生错误的信息将返回到客户端。
在客户端与服务器进行交换信息的时候,Request和Response相当于两个人在写信交流,而Cookie和Session则相当于两个人各自写下日记,记录着自己或者对方的信息。在JavaWeb编程中,正确操作这四个对象是非常重要的,因此下文将会介绍如何用java 调用servlet中关于Request、Response、Cookie和Session的方法。
http之Request
Request对象,又称为请求对象,是由客户端发起的请求,包括用户提交的信息以及客户端的一些信息。客户端可通过HTML表单或在网页地址后面提供参数的方法提交数据,然后服务器通过request对象的相关方法来获取这些数据。
Request与Response的的运行流程
Request之get与post
http有多种请求方式,其中最为常用的get和post。
get相对不安全,因为get的数据会被放在请求的URL中一并发出,并且get传送的数据量较小,受url长度限制。
post的所有操作对用户来说都不可见,且Post传送的数据量较大,一般被默认为不受限制。
请求消息
请求消息包括请求行(request line)、请求头部(header)、空行和请求数据,如下图所示。
请求头的常见头部字段名
Server:服务器版本信息
Date:日期
Content-Type:实际返回的内容的内容类型
Content-Length:描述HTTP消息实体的传输长度
User-Agent:浏览器版本信息
Java处理Request
Request这个对象不用事先声明,就可以在JSP网页中使用,在编译为Servlet之后,它会转换为HttpServletRequest形态的对象,HttpServletRequest对象是有关于客户端所发出的请求的对象,只要是有关于客户端请求的信息,都可以藉由它来取得,例如请求标头、请求方法、请求参数、客户端IP,客户端浏览器等等信息。
Request继承结构
ServletRequest接口
|- 继承
HttpServletRequest接口
|- org.apache.catalina.connector.RequestFacade 实现类 (tomcat提供)
有关HttpServletRequest方法,想要更全面的信息请访问HttpServletRequest api文档 http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServletRequest.html 下文会介绍常用的HttpServletRequest 方法
1.获取请求行信息
getMethod();获取请求方式
getRequestURL();方法返回客户端发出请求时的完整URL。
getRequestURI();方法返回请求行中的资源名部分。
getQueryString(); 方法返回请求行中的参数部分。
getPathInfo();方法返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以“/”开头。
getRemoteAddr();方法返回发出请求的客户机的IP地址。
getRemoteHost();方法返回发出请求的客户机的完整主机名。
getRemotePort();方法返回客户机所使用的网络端口号。
getLocalAddr();方法返回WEB服务器的IP地址。
getLocalName();方法返回WEB服务器的主机名。
jsp代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form method="post" action="/test">
<input type="submit" value="提交">
</form>
</body>
</html>
servlet代码:
package com.southwind.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("req.getMethod()= "+req.getMethod());
System.out.println("req.getRequestURL()= "+req.getRequestURL());
System.out.println("req.getRequestURI()= "+req.getRequestURI());
System.out.println("req.getQueryString()= "+req.getQueryString());
System.out.println("req.getPathInfo()= "+req.getPathInfo());
System.out.println("req.getRemoteAddr()= "+req.getRemoteAddr());
System.out.println("req.getRemoteHost()= "+req.getRemoteHost());
System.out.println("req.getRemotePort()= "+req.getRemotePort());
System.out.println("req.getLocalAddr()= "+req.getLocalAddr());
System.out.println("req.getLocalName()= "+req.getLocalName());
}
}
输出:
req.getMethod()= POST
req.getRequestURL()= http://localhost:8080/test
req.getRequestURI()= /test
req.getQueryString()= null
req.getPathInfo()= null
req.getRemoteAddr()= 0:0:0:0:0:0:0:1
req.getRemoteHost()= 0:0:0:0:0:0:0:1
req.getRemotePort()= 57041
req.getLocalAddr()= 0:0:0:0:0:0:0:1
req.getLocalName()= 0:0:0:0:0:0:0:1
2.获取请求头信息
getHeader(string name);方法:String
getHeaders(String name);方法:Enumeration
getHeaderNames();方法
jsp代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form method="post" action="/test">
<input type="submit" value="提交">
</form>
</body>
</html>
servlet代码:
package com.southwind.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取所有请求头字段
Enumeration<String> headerNames = req.getHeaderNames();
while(headerNames.hasMoreElements()){
String name = headerNames.nextElement();
//获取字段对应的值
String value = req.getHeader(name);
System.out.println(name+": "+value);
}
}
}
输出:(所有头信息字段及其值)
host: localhost:8080
connection: keep-alive
content-length: 0
cache-control: max-age=0
upgrade-insecure-requests: 1
origin: http://localhost:8080
content-type: application/x-www-form-urlencoded
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
sec-fetch-site: same-origin
sec-fetch-mode: navigate
sec-fetch-user: ?1
sec-fetch-dest: document
referer: http://localhost:8080/test.jsp
accept-encoding: gzip, deflate, br
accept-language: zh-CN,zh;q=0.9
cookie: JSESSIONID=4385440600ABA12937C60FDD40D10661
3.获取传递参数
String getParameter(String name) 返回name指定参数的参数值
String[] getParameterValues(String name) 返回包含参数name的所有值的数组
4.共享数据
void setAttribute(String,Object) 存储此请求中的属性
Object getAttribute(String name) 返回指定属性的属性值
要注意,只有先set了才能get到。
5.转发
getRequestDispatcher(String url).forward(request,response);
由转发后的地址来对转发的请求进行响应。
http之Response
Response对象用于动态响应客户端请示,控制发送给用户的信息,并将动态生成响应。Response对象只提供了一个数据集合cookie,它用于在客户端写入cookie值。若指定的cookie不存在,则创建它。若存在,则将自动进行更新。结果返回给客户端浏览器。
和HttpServletRequest类似,HttpServletResponse也继承了ServletResponse 接口,这个对象中封装了向客户端**发送数据、发送响应头,发送响应状态码**的方法。我们可以直接调用HttpServletResponse的方法来操作Response。
Response主要包含响应行、响应头和响应体。
响应行:协议版本 状态 描述
响应头:必要信息
响应体:返回的数据
Java处理Response
HttpServletRequest的API库:http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServletResponse.html 1.向客户端发送数据
resp.getOutputStream();
resp.getWriter();
getOutputStream
和getWriter
方法分别用于得到输出二进制数据ServletOuputStream对象和输出文本数据的Printwriter对象。并且两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。
这两个方法写入的数据会作为响应消息的正文,与响应状态行和各响应头组合后输出到客户端。Serlvet的service
方法结束后,web容器将检查getWriter
或getOutputStream
方法返回的输出流对象是否已经调用过close方法,如果没有,web容器将调用close方法关闭该输出流对象。
在向服务端发送数据的时候,可能会发现自己要传输的中文显示成乱码,那么这时候需要设置编码格式,以下两种选一即可,但都需要在向客户端发送数据之前执行才能生效,二者区别在于前者不仅发送到浏览器的内容会使用UTF-8编码,而且还通知浏览器使用UTF-8编码方式进行显示。所以总能正常显示中文。
resp.setContentType(“text/html; charset=UTF-8”);//更稳妥
resp.setCharacterEncoding(“UTF-8”);
2.实现重定向
resp.sendRedirect(String url);
有细心的人看到这里应该会想到,request有转发,response有重定向,二者的功能类似,都是将页面跳转,那么这两者有什么区别呢?
首先, RequestDispatcher.forward
方法只能将请求转发给同一个WEB应用中的其他资源; sendRedirect
方法还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。
request的转发是在服务器端实现的。一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理,称之为请求转发。调用RequestDispatcher.forward
方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
而response的重定向是在客户端实现的。一个web资源收到客户端请求后,通知客户端的浏览器去访问另外一个web资源,称之为请求重定向。所以调用HttpServletResponse.sendRedirect
方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL。
从本质上看,转发是请求实现的,这意味着是将请求给转发给另外一个网址,而重定向是响应实现的,那么因此是对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求。
最终表现出来转发:浏览器地址不变,重定向:浏览器地址变成新的url
3.设置响应头
setDateHeader(String name, long date);用一个给定的名称和日期值设置响应头,这里的日期值应该是反映自1970-1-1日(GMT)以来的精确到毫秒的长整数。如果响应头已经被设置,新的值将覆盖当前的值。
setHeader(String name, String value);用一个给定的名称和域设置响应头。如果响应头已经被设置,新的值将覆盖当前的值。
setHeader(String name, String value);用一个给定的名称和整形值设置响应头。如果响应头已经被设置,新的值将覆盖当前的值。
setStatus(int statusCode);这个方法设置了本次响应的状态码,如果状态码已经被设置,新的值将覆盖当前的值。
addCookie(Cookie cookie);在响应中增加一个指定的cookie
containsHeader(String name);返回布尔值,检查是否设置了指定的响应头。
httpResponse状态消息
五种状态码:
- 1xx:信息提示,表示请求已被成功接收,继续处理
- 2xx:请求被成功提交。 3xx:客户端被重定向到其他资源。
- 4xx:客户端错误状态码,格式错误或者不存在资源。
- 5xx:描述服务器内部错误。
常见的状态码:
200:客户端请求成功,是最常见的状态。
302:重定向。
404:请求资源不存在,是最常见的状态。
400:客户端请求有语法错误,不能被服务器所理解。
401:请求未经授权。
403:服务器收到请求,但是拒绝提供服务。
500:服务器内部错误,是最常见的状态,通常是代码写错了。
503:服务器当前不能处理客户端的请求。
http之Cookie
1.什么是Cookie
Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息 。
它是存储在浏览器中的小型文本文件,携带用户信息,方便服务端提供服务,同时也可能会导致个人信息的泄漏。
创建cookie
Cookie cookie = new Cookie(String name,String value);
添加cookie
resp.addCookie(Cookie cookie);
2.Cookie的方法使用
Cookie API文档:http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/Cookie.html
setMaxAge(int expiry);设置cookie有效时间,秒。如果不设置则仅在本次session会话中有效.
getMaxAge();获取cookie有效时间
getName();获取cookie name值
getValue();获取cookie value值
setValue();设置新的cookie value值
setPath(String url);设置cookie的访问域
getPath();取出cookie的访问域
setComment(String str);指定描述cookie用途的注释
getComment();取出注释
getSecure();如果浏览器仅通过安全协议发送cookie,则返回true。如果浏览器可以使用任何协议发送cookie,则返回false。
jsp代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form method="post" action="/test2">
<input type="submit" value="提交">
</form>
</body>
</html>
----------------------------------------------------
servlet代码:
package com.southwind.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/test2")
public class Test2Servlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//编码
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
//测试代码
Cookie cookie = new Cookie("name","tom");
cookie.setMaxAge(1000);
resp.getWriter().println("getMaxAge()= "+cookie.getMaxAge()+"<br/>");
resp.getWriter().println("getName()= "+cookie.getName()+"<br/>");
resp.getWriter().println("getValue()= "+cookie.getValue()+"<br/>");
cookie.setComment("注释");
resp.getWriter().println("getComment()= "+cookie.getComment()+"<br/>");
resp.getWriter().println("getSecure()= "+cookie.getSecure()+"<br/>");
}
}
网页输出:
http之Session
1.什么是session
Session是另一种记录客户状态的机制。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。
获取Session对象
HttpSession session = req.getSession();
2.session与cookie的区别
- Cookie保存在客户端浏览器中,而Session保存在服务器上。
- Session保存数据为Object类型,Cookie为String类型
- Session会长期保存,并且会存放重要的数据
3.session的方法使用
Session API文档:http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpSession.html
setAttribute(String attribute, Object value);存入对象
getAttribute(String attribute);取出对象
removeAttribute(String attribute) 移除Session属性
getCreationTime();返回创建此会话的时间,以毫秒为单位,自1970年1月1日零点起计算。常被转化为Date类型,例如:Date createTime = new Date(session.getCreationTime())
getId() 返回Session的ID。该ID由服务器自动创建,不会重复
getLastAccessedTime() 返回Session的最后活跃时间。返回类型为long
getMaxInactiveInterval() 返回Session的超时时间。单位为秒。
测试代码:
jsp代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form method="post" action="/test3">
<input type="submit" value="提交">
</form>
</body>
</html>
------------------------分割线----------------------------------------------
servlet代码:
package com.southwind.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/test3")
public class SessionServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
HttpSession session = req.getSession();
session.setAttribute("name","tom");
resp.getWriter().println("setAttribute()= "+session.getAttribute("name"));
resp.getWriter().println("getCreationTime()= "+session.getCreationTime());
resp.getWriter().println("getId()= "+session.getId());
resp.getWriter().println("getLastAccessedTime()= "+session.getLastAccessedTime());
resp.getWriter().println("getMaxInactiveInterval()= "+session.getMaxInactiveInterval());
}
}
输出: