C/S架构的程序:
B/S架构的程序:
Web服务器
对外提供web服务的软件。
我们要使用的web服务器:
-
tomcat 不要钱。
-
nginx 并发处理能力特强。
Tomcat
下载的网址:https://tomcat.apache.org/download-80.cgi
安装使用。 开箱即用...
在bin目录下双击:
启动
启动之后在浏览器访问: http://localhost:8080
Tomcat的端口修改:
端口被占用的情况:启动tomcat的时候会闪退。查看日志:
修改:打开
在tomcat上部署一个web程序:
将写好的web应用程序直接赋值到webapps中:
在浏览器中访问: http://localhost:8888/0107-demo/main.html
在IDEA中配置tomcat
在IDEA中创建web项目
创建新项目:
Servlet
创建servlet需要添加servlet需要的jar文件,和之前添加JDBC驱动的jar的操作方式一致。这次选择的是tomcat中的servlet-api.jar文件
自己定义一个类,继承HttpServlet
public class HelloServlet extends HttpServlet {
在项目的webapp/WEB-INF/web.xml中添加配置:
启动tomcat在浏览器中访问: http://localhost8080/web/hello
serlvet执行流程分析
[1]启动tomcat
tomcat已启动就会读取我们的WEB-INF/web.xml文件。
[2]在浏览器中访问:
http://localhost:8080/web/hello
localhost 指向本机
8080: 找到了tomcat
/web : 找到当前的项目
/hello : 要访问/web项目的 /hello
[3]tomcat通过"/hello" 找打对应的servlet
tomcat找到对应的servlet类,加载这个类,创建这个类的类对象。执行其中的doGet方法:
[4]浏览器接收到响应结果
认识一下servlet
狭义上:就是一个接口
package javax.servlet;
import java.io.IOException;
public interface Servlet {
// 初始化servlet对象的方法
void init(ServletConfig var1) throws ServletException;
// 获取servletconfig对象
ServletConfig getServletConfig();
// 处理请求的方法
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
// 得到servlet的字符串表达形式
String getServletInfo();
// 释放资源的方法
void destroy();
}
广义上说servlet就是我们自己实现的servlet类:
tomcat其实本身只是认识Servlet接口而已,根本就不知道我们自己写的类。
我们自己写的servlet,当tomcat加载之后,会把我们的servlet看作Servlet接口来使用。所以我们写的类只要实现了Servlet接口,tomcat就认识,就能加载运行,并不一定要继承HttpServlet和GenericServlet类。
servlet的API“研究”
先看接口源码:
package javax.servlet;
import java.io.IOException;
public interface Servlet {
// 初始化servlet对象的方法
void init(ServletConfig var1) throws ServletException;
// 获取servletconfig对象
ServletConfig getServletConfig();
// 处理请求的方法
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
// 得到servlet的字符串表达形式
String getServletInfo();
// 释放资源的方法
void destroy();
}
tomcat加载和运行的过程:
[1]加载我们的HelloServlet类,根据这个类会创建一个HelloServlet对象。
[2]创建好对象之后立刻初始化。 执行方法:
void init(ServletConfig var1) throws ServletException;
这个方法本身是在GenericServlet中实现的。
[3]当请求到达这个HelloServlet的时候,默认会执行:
// 处理请求的方法
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
这个方法也是GenericServlet实现的
tomcat就是通过“反射”调用HelloServlet对象的service方法,并且创建了两个对象ServletRequest和ServletResponse。 ServletRequest封装了所有的客户端的请求信息。 ServletResponse使用响应客户端的一个对象。
init方法的实现
在GenericServlet中实现:
public abstract class GenericServlet implements Servlet, ServletConfig,
java.io.Serializable {
// 实现的接口中申明的init方法。
init() : 空实现的方式,就让子类按需重写。
service方法的实现
在GenericServlet中并未实现这个方法:
public abstract class GenericServlet implements Servlet, ServletConfig,
java.io.Serializable {
//..............
public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
}
肯定是在HttpServlet中实现的:
public abstract class HttpServlet extends GenericServlet { // 对父类/接口中的方法的实现 @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { //HttpServletRequest 是 ServletRequest的子接口 //HttpServletResponse 是 ServletResponse的子接口 // 申明了两个对象。 HttpServletRequest request; HttpServletResponse response; try { // tomcat传入的req对象本身就是子接口HttpServletRequest的对象 // 将父类对象强制类型转换为子类类型 request = (HttpServletRequest) req; response = (HttpServletResponse) res; } catch (ClassCastException e) { throw new ServletException(lStrings.getString("http.non_http")); } // 如果没有异常,调用了另外一个重载的方法 service(request, response); } // 在HttpServlet中自己定义的一个重载的service的方法 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取HTTP的请求方法。HTTP请求有多个方法(GET,POST,PUT,DELETE,HEAD,TRACE,OPTIONS) String method = req.getMethod(); // 如果请求方法是get if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic // 调用doGet doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); } catch (IllegalArgumentException iae) { // Invalid date header - proceed as if none was set ifModifiedSince = -1; } if (ifModifiedSince < (lastModified / 1000 * 1000)) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); // 调用doGet doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); // 处理head请求 doHead(req, resp); } else if (method.equals(METHOD_POST)) { // 处理post请求 doPost(req, resp); } else if (method.equals(METHOD_PUT)) { // 处理put请求 doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { // 处理Delete请求 doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { // // Note that this means NO servlet supports whatever // method was requested, anywhere on this server. String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } } // doXxxx的实现 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 这里的代码的作用是:当发送了get请求的时候,判断子类是否重写了这个方法,如果没有重写就报异常,如果重写了就执行子类的方法 String msg = lStrings.getString("http.method_get_not_supported"); sendMethodNotAllowed(req, resp, msg); } }
所以我们自己的servlet只要根据需要实现对应的doXxx方法即可,如果没有按照需求实现,就会出现405错误
之前的案例中地址栏直接输入 http://localhost:8080/web/hello 就是一个GET请求,我在servlet中要实现doGet处理GET请求。
destroy方法
destroy是在Servlet接口中申明的,使用卸载servlet对象之前调用的,专门用来释放资源优先象finally代码块。
这个方法在GenericServlet中实现的,是一个空实现。空实现,就是让我们自己按需重写的。
测试这些API的执行情况:
public class HelloServlet extends HttpServlet { @Override public void init() throws ServletException { System.out.println("初始化HelloServlet"); } @Override public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException { System.out.println("执行了service方法"); // 通过super调用父类的service方法方法 super.service(req, resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("执行了doGet方法"); resp.getWriter().write("<h1>Hello world!</h1>"); } @Override public void destroy() { System.out.println("执行了destroy方法"); } }
启动tomcat,并且 重复访问这个servlet两次:
tomcat启动的时候,这些方法都没有执行。
停止tomcat:
tomcat的生命周期:
当tomcat加载servlet之后, 创建servlet类对象,对象已创建,立刻执行init方法,进行初始化。 当请求到大servlet的时候,tomcat会调用servlet的service方法处理请求。(service内部会自动调用对应的doXxxx方法) 当我们停止tomcat/卸载servlet的时候,在卸载之前会执行destroy方法释放资源。
HTTP协议
所谓HTTP协议就是,规定客户端和服务器端发送消息的格式和内容。
本质上客户端和服务端都是一台机器,通过一个软件进行通信(浏览器和tomcat)。为了让这两个软件可以通信,就规定了一套通信的消息格式。有了这个格式,它们相互就能”理解“相互发的消息。
研究HTTP协议,就是稍微看看HTTP的协议中的消息格式大致是啥样子?
我们请求一个网站:
请求头消息:
请求行: GET / HTTP/1.1
分为3部分:
-
GET 请求方法,请求方法分为7中:GET,POST,PUT,DELETE,OPTIONS,HEAD,TRACE
-
/ 请求资源的路径。 / 表示请求首页。 /login.html 表示登陆页面
-
HTTP/1.1 请求协议版本
我们案例的请求头消息:
所有的请求头都是以 key : value的形式发送。具体的key : value是什么,是不确定。
响应头消息
响应行: HTTP/1.1 200
-
HTTP/1.1 协议版本
-
200 响应状态码。
响应状态码的说明:
-
200 表示响应正常。
-
500 服务器内部错误,程序出异常,无法正常响应。
-
404 表示请求的资源不存在。
-
405 请求的方法不被支持。对应的doXxx方法没有被实现。
-
406 响应的数据类型不正确,
-
400 请求的数据类型不正确。
-
304 获取的数据是从缓存中获取的,没有向服务器发送请求。
Request
当然我们说的是HttpServletRequest这个类型。
在我们自己写的doXxx方法中有一个参数HttpServletRequest类型,这个参数一个对象, 这个对象封装了所有的请求内容。所谓请求内容,就是客户端发送的请求行信息,以及请求头信息。tomcat会将客户端的请求内容进行解析,并且封装到HttpServletRequest对象中,并且将这个对象传递到我们的doXxx方法内部。
我们通过request可以轻松获取所有的请求内容:
请求内容:
-
请求行中的内容: 请求方法,请求的资源的路径,协议版本。
-
请求头的所有内容。
-
请求参数
请求参数是什么?
我们在京东搜索一个商品
①search.jd.com 京东的域名。 域名就是我们写的 localhost:8080
② /Search 请求的资源路径 /web/hello
③ keyword=尤克里里&enc=utf-8
GET请求的请求参数是直接使用?连接在url后面的。 形式: key=value&key=value&....
POST请求的参数是放在一个专门的数据区域中,但是依然是key=value的形式。
使用tomcat传入的request对象获取所有的请求内容:
准备一个RequestTestServlet,在web.xml中添加配置:
<servlet> <servlet-name>RequestTest</servlet-name> <servlet-class>com.qidian.web.servlet.RequestTestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RequestTest</servlet-name> <url-pattern>/requestTest</url-pattern> </servlet-mapping>
public class RequestTestServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 从request中获取所有的请求内容 // 获取请求方法 String method = request.getMethod(); System.out.println("请求方法是:"+method); // 获取请求路径 String url = request.getRequestURL().toString(); System.out.println("请求路径:"+url); // 获取请求头 System.out.println("请求头:----------------"); Enumeration<String> headerNames = request.getHeaderNames(); while(headerNames.hasMoreElements()){ String name = headerNames.nextElement(); System.out.println(name+":"+request.getHeader(name)); } // 获取请求参数 username,age // 传入的是参数的名字,返回参数的值 这个方法返回的永远都是String类型 String username = request.getParameter("username"); String ageStr = request.getParameter("age"); int age = Integer.parseInt(ageStr); System.out.println("请求参数:--------------"); System.out.println("username = "+username); System.out.println("age = "+age); } }
请求测试:
http://localhost:8080/web/requestTest?username=qimukakaxi&age=185
控制台输出的内容:
请求方法是:GET 请求路径:http://localhost:8080/web/requestTest 请求头:---------------- host:localhost:8080 connection:keep-alive sec-ch-ua:" Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98" sec-ch-ua-mobile:?0 sec-ch-ua-platform:"Windows" upgrade-insecure-requests:1 user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 sec-fetch-site:none sec-fetch-mode:navigate sec-fetch-user:?1 sec-fetch-dest:document accept-encoding:gzip, deflate, br accept-language:zh-CN,zh;q=0.9,en;q=0.8 请求参数:-------------- username = qimukakaxi age = 185
Response
HttpServletResponse 是tomcat创建的一个对象,这个对象直接连接者客户端,我们可以通过这个对象响应客户端。
// 使用response响应客户端 response.setCharacterEncoding("utf-8");// 防止中文乱码 response.getWriter().write("这是响应给客户端的内容,它可以是一段HTML代码 <h2>你看!是吧!</h2>");
图书管理
添加图书
web项目添加驱动:在WEB-INF目录下创建一个lib文件夹,将驱动文件放在lib中,添加到classpath
添加一个POJO类:
public class Book { // 图书编号,对应g_book的isbn private String isbn; // 图书标题,对应g_book的title private String title; // 图书成本,对应g_book的cost private float cost; // 图书售价,对应g_book的price private float price; // 图书出版社编号,对应g_book的pid private String pid; // 图书类别编号,对应g_book的categoryId private int categoryId; // setter和getter省略 }
添加BookDAO接口:
public interface BookDAO { // 保存一本图书 int save(Book book); // 根据isbn查询一本图书信息 Book getByIsbn(String isbn); // 修改一本图书信息 int update(Book book); // 查询所有的图书 ArrayList<Book> queryAll(); // 分页查询 ArrayList<Book> queryByPage(int page, int size); // 查询总条数 int queryTotal(); }
在web目录下创建一个book-add.html页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加图书</title> </head> <body> <!-- 添加一个表单 --> <form method="post" action="book-add"> <p> 图书编号:<input type="text" name="isbn"> </p> <p> 图书标题: <input type="text" name="title"> </p> <p> 成本:<input type="text" name="cost"> </p> <p> 价格: <input type="text" name="price"> </p> <p> 出版社编号: <input type="text" name="pid"> </p> <p> 类别编号: <input type="text" name="categoryId"> </p> <p> <input type="submit" value="提交"> </p> </form> </body> </html>
输入内容,点击提交按钮
请求头:
由于是POST请求,请求参数不在url后, 而是在一个专门的数据区域
使用一个Servlet获取这些请求参数,并且将这些数据保存到数据库
web.xml的配置:
在servlet中使用request.getParamter(" 参数名"); 这里的参数名,就是表单的input中的name属性的值。
public class BookSaveServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse resposne) throws ServletException, IOException { // 获取所有的请求参数 String isbn = request.getParameter("isbn"); String title = request.getParameter("title"); String costStr = request.getParameter("cost"); float cost = Float.parseFloat(costStr); String priceStr = request.getParameter("price"); float price = Float.parseFloat(priceStr); String pid = request.getParameter("pid"); String categoryIdStr = request.getParameter("categoryId"); int categoryId = Integer.parseInt(categoryIdStr); // 准备一个Book对象 Book book = new Book(); // 将获取的请求参数数据全部设置到book对象中 book.setIsbn(isbn); book.setTitle(title); book.setCategoryId(categoryId); book.setCost(cost); book.setPid(pid); book.setPrice(price); // 准备一个BookDAO对象 BookDAO bookDAO = new BookDAOImpl(); int result = bookDAO.save(book); String info = "保存失败"; if(result == 1){ info = "保存成功"; } resposne.setCharacterEncoding("gbk"); resposne.getWriter().write(info); } }
整个流程:
乱码问题
两种情况的乱码:
情况1:数据库与应用程序之间乱码。
解决方案:在数据库连接的url中添加字符集的设置。
情况2:web请求响应中的乱码问题
响应的乱码解决:
①如果响应的是HTML: resp.setContentType("text/html;charset=utf-8");
②如果响应的是字符串: resp.setCharacterEncoding("utf-8");
请求中的乱码:
产生的原因是:客户端提交的编码和服务的编码不一致导致的。
tomcat8以前 tomcat的默认编码是 iso8859-1
. 无论请求是什么格式,在请求中中文参数都会乱码。
tomcat8之后,tomcat的默认编码为utf-8。 我们现在使用的是8.5. 默认就是utf-8。
目前的tomcat8.5中 GET请求的中文不乱码。 POST请求会乱。
POST请求中乱码的解决:
在获取请求参数之前,设置request对象的编码为utf-8.
web项目打包发布
在idea中:
最终tomcat看到的是out这个文件夹下的内容。
Ajax
常说的异步请求。。
第一个ajax应用
我们使用ajax来完成一个简单的请求。
[2]准备一个HTML页面, 添加下面的程序
-
浏览器地址栏直接输入访问地址,开始请求
-
超链接(和直接写地址是一样的)
-
JS实现超链接
location.href=xxxx?xxx
-
提交表单
上面的所有的提交数据的方式都是由浏览器完成具体的请求。
Ajax的测试程序分析
[1]这个程序中Servlet有没有特殊的要求?
Ajax本身和后端的任何技术都是没有关系。
[2]Ajax不是通过浏览器发送的请求,而是通过XMLHttpRequest对象发送的请求。
[3]XMLHttpRequest的状态(设置回调函数)
XMLHttpRequest本身是有状态的,状态属性是:readyState,有如下几个值:
-
0 (uninitialized) or (request not initialized)(请求对象还没有被创建)
-
1 (loading) or (server connection established)(和服务器完成连接)
-
2 (loaded) or (request received)(请求已经发送)
-
3 (interactive) or (processing request)(正在请求中)
-
4 (complete) or (request finished and response is ready)(请求完成, 响应结果已经收到)
readyState的值一旦发送改变就会触发XMLHttpRequest上的一个事件:onreadystatechange。
所以我们通过设置onreadystatechange的函数,来设置回调函数。
// 打开请求 (请求方法,请求的url路径,是否异步请求)
httpRequest.open("GET","ajax?name=kakaxi&age=222",true);
请求方法一般都是GET/POST
GET请求,请求参数在url后面。
第三个参数表示是否异步。
如果是true:表示异步,请求发送之后,响应回来之前,后面的处理程序继续执行。
如果是false:表示同步,请求发送之后,响应回来之前,后面的处理程序不能执行。
// 发送请求 (POST请求的时候,这个参数才有用)
httpRequest.send(null);
httpRequest.send('name=kakaix&age=180');
Ajax的POST请求
如果参数依然写在URL后面,是可以携带的。
但是如果参数是在专门的数据区域 send(xxxx)。必须设置一个请求头:
在opne之后,send之前:
// 设置一个Header
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
[1]将我们在idea中写的前端的程序直接复制到VSCode中。将url地址修改为完整的访问地址:
[2]在VSCode中或者其他的前端编辑器也一样:
确保我们的HTML页面是在服务器上运行的,不是本地文件打开的
[3]请求服务器测试
浏览器告诉我们,不允许跨域请求。
解释这个问题:
①域名
俗话说的网址: www.baidu.com
任何一个域名都要绑定到一个ip地址上,我们在浏览器中输入的域名,会被DNS服务器解析为IP地址。
②跨域 (一级域名)
所谓跨域请求的意思是:从a域名下的程序中发出ajax请求去请求b域名下的数据。
而跨域是不被允许的......... 浏览器不允许跨域请求数据。
[1]script标签的跨域
浏览器不允许跨域请求,但是允许script标签跨域请求。
<script src="http://localhost:8080/web/abc.js"></script>
这个可以请求。
在idea中添加一个JS文件
启动tomcat。
在VSCode的某一个页面中使用script引入上面写的JS文件
页面效果:
[2]利用jsonp实现跨域请求数据
需求,根据用户的id跨域请求用户的名字。在后端实现一个servlet:
public class UserGetNameServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userId = req.getParameter("userId");
System.out.println("userId = "+userId);
// 响应客户端
resp.getWriter().write("卡卡西");
}
}
在前端的任何页面中加入如下的script标签:
tips:script标签的 src就是要请求的接口的url,并且get请求携带参数。
script理论获取的是script的代码,但是这个服务器端返回的数据是一个字符串。
如果我们返回一个可执行的script代码,是不是就可以直接执行了???
思路:
在前端定义一个js函数,这个函数接收一个参数,参数就是username,然后在后端返回调用这个函数的js代码,并且将后端的用户名传入即可。
<script>
let uname = undefined;
function getUsername(username){
uname = username;
}
// 手动调用
// getUsername("卡卡西");
</script>
<script src="http://localhost:8080/web/getName?userId=789"></script>
<script>
console.log("uname = " + uname);
</script>
修改后端的返回值:
原理:
[1]封装一个基础的ajax
在任意一个页面引入上面的js文件:
<!-- 引入ajax封装的文件 -->
<script src="js/qidian-ajax.js"></script>
<script>
function doAjax(){
// 调用我们自己分装的ajax请求的函数
qdAjax({
type:"GET",
url:"ajax",
data:"name=卡卡西&age=222",
success:function(res){
document.getElementById("result").value=res;
}
});
}
</script>
</head>
<body>
<input type="text" id="result"><input type="button" value="请求" onclick="doAjax()">
<p></p>
<script>
function doPostAjax(){
qdAjax({
type:"POST",
url:"ajax",
data:"name=佐助&age=18",
success:function(res){
document.getElementById("spanResult").innerText=res;
}
})
}
</script>
<span id="spanResult"></span> | <a href="javascript:doPostAjax()">POSTAjax请求</a>
</body>
</html>
JSON的基本的语法:
所有的属性都应该使用“”包裹。属性值:字符串必须使用“”包裹,数字可以不使用“”。
一个对象:{"name":"卡卡西","age":28,"skill":"千年杀"}
[
{"name":"卡卡西","age":28,"skill":"千年杀"},
{"name":"卡卡西","age":28,"skill":"千年杀"},
....
]
一个复杂的对象:
{
"name":"大锤",
"age": 28,
"dog":{"name":"大黄","age":5},
"girlfriends":[
{"name":"如花","age":18},
{"name":"翠花","age":19},
......
]
}
将JSON字符串转换为对象:
<script>
let stu = '{"name":"佐助","age":18,"skill":"写轮眼"}';
console.log(typeof stu);
// 将字符串转换为对象
let student = JSON.parse(stu);
console.log(typeof student);
// 当转换为对象之后,就可以使用其中的属性了
console.log(student.name);
// 将对象转换为json字符串
let dog = new Object();
dog.name = "大黄";
dog.age = 5;
console.log(typeof dog);
let dogStr = JSON.stringify(dog);
console.log(typeof dogStr);
</script>
在java中将对象转换字符串:拼接字符串。 将字符串转换为对象:解析字符串,创建新的对象,并且赋值。
登陆和登陆状态校验
session知识点
一句话:HTTP协议是无状态的协议。所谓无状态就是服务器不记录客户端的访问状态。在通俗一些,就是你每次对服务器的访问,服务器都不知道你是谁。它只知道有一个请求,然后就按照请求给出正确响应。
一个现象:在网页上登陆的淘宝,选了商品加入购物车,准备结算。这时室友喊你去吃饭,吃完饭回来,发现这个淘宝需要重新登陆。
如果服务器不记录状态:你请求购物车页面是一次请求。请求登陆也是一次请求。对于服务器来说这两次请求是没有关系的。显示情况是有关系的。
web项目就是靠session解决HTTP协议无状态的问题。
session处理“会话跟踪”:
当客户端第一次请求服务器的时候,服务器会在服务器端创建一个session(会话)对象,并且给session一个编号(sessionid)。将个这个编号放在cookie中,并且将这个cookie发送给客户端(浏览器,手机端)。客户端下次来访问的时候会带上这个cookie,带上session编号。服务器就根据session编号找到之前的session对象。session本身是一个容器,可以存储一些信息。比如登陆状态信息。如果浏览器清空cookie,再访问服务器的时候,就是一个新的请求,之前的session就失效了。还有个问题,服务器无法检测客户端是否清理了cookie。所以session是否还能继续使用服务器不知道。所以为了防止session一致存在在服务中。如果超过了半小时没有使用的session,直接销毁。
cookie是不能跨域的。
本文来自博客园,作者:{潇潇消消气},转载请注明原文链接:{https://www.cnblogs.com/xiaoxiaodeboke/}