1.Servlet容器
常见的Servlet容器 [WebLogic] [Tomcat] [Jetty] [JBoss] [Resin] [WebSphere]
这里我使用 Tomcat 服务器 @Tomcat安装
Tomcat目录的解释
修改默认端口号为80 方便访问 注意 后期做Tomcat集群的时候,就不会使用80端口了
修改虚拟主机配置
2.Servlet和JSP
Servlet规范
1.约束了服务器 因为服务器需要解析Servlet和Jsp
2.约束项目的结构 JavaWeb项目必须遵守一定的项目目录结构
3.Servlet是一个JavaEE的组件
Servlet是属于JavaEE的范畴,只依赖JavaEE是不能开发的 需要JavaEE的jar
此处我使用 Idea+Maven 开发所以创建一个 webapp 骨架 然后编写标准JavaWeb(JavaEE)结构 其中编译之后的字节码文件放在 classes 文件夹
在WEB-INF下 被隐藏了
必须的 pom.xml 依赖
<!-- Servlet 包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- jsp 包 -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<!-- jstl 包 -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!-- taglibs包 -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
第一个Servlet程序
package cn.icanci.javaweb;
import javax.servlet.*;
import java.io.IOException;
/**
* @Author: icanci
* @ProjectName: javaweb
* @PackageName: cn.icanci.javaweb
* @Date: Created in 2020/2/6 19:37
* @ClassAction:
*/
public class Test1Servlet implements Servlet {
@Override
public void init(ServletConfig config) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("hello");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
配置web.xml 告诉Tomcat来管理此类
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>Test1Servlet</servlet-name>
<servlet-class>cn.icanci.javaweb.Test1Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Test1Servlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
配置Tomcat @Idea配置Tomcat服务器
浏览器运行
控制台打印
Servlet的生命周期
0. 构造器 如何判断一定调用的就是调用公共的无参数构造器,使用 private 修饰 构造器,那就会报错 500 如果共有有参数,没有无参数共有,也会 500 因为底层是 通过反射创建对象 类.newInstance();
1. 创建servlet实例 Servlet是单例的
由服务器创建 不需要程序员手动创建
2. 初始化init
默认在第一次访问servlet的时候执行 并且只执行一次
3. service 核心业务逻辑
调用业务逻辑
4.服务器关闭执行destory方法
代码
package cn.icanci.javaweb;
import javax.servlet.*;
import java.io.IOException;
/**
* @Author: icanci
* @ProjectName: javaweb
* @PackageName: cn.icanci.javaweb
* @Date: Created in 2020/2/6 19:37
* @ClassAction:
*/
public class Test1Servlet implements Servlet {
public Test1Servlet() {
System.out.println("Servlet初始化");
}
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("Test1Servlet.init");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("服务启动");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("Test1Servlet.destroy");
}
}
Servlet的执行过程
1.首先浏览器发送请求到达服务器
2.到达服务器后会将请求中的数据打包
3.封装成一个对象,HttpServletRequest接口的实现类的对象
4.同时创建一个响应对象,HttpServletResponse接口实现类的对象
5.服务器根据请求路径查看web.xml找到对应的Servlet
6.并调用其中的service(doGet/doPost)方法
7.调用时将创建的请求对象与响应对象交给service方法
8.service方法中根据请求中的数据处理核心业务逻辑
9.并提供响应的视图 比如html
10.服务器根据响应对象生成的响应结果发送给客户端
11.客户端根据响应结果将内容展示在页面中
Servlet的继承体系
获取初始化参数
package cn.icanci.javaweb;
import javax.servlet.*;
import java.io.IOException;
/**
* @Author: icanci
* @ProjectName: javaweb
* @PackageName: cn.icanci.javaweb
* @Date: Created in 2020/2/6 19:37
* @ClassAction:
*/
public class Test1Servlet implements Servlet {
private String encoding;
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("Test1Servlet.init");
encoding = config.getInitParameter("encoding");
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println(encoding);
System.out.println("服务启动");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void destroy() {
System.out.println("Test1Servlet.destroy");
}
}
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>Test1Servlet</servlet-name>
<servlet-class>cn.icanci.javaweb.Test1Servlet</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Test1Servlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
Servlet的继承体系
public class Test2Servlet extends HttpServlet {
}
public abstract class HttpServlet extends GenericServlet
implements java.io.Serializable
{
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{}
}
public abstract class GenericServlet
implements Servlet, ServletConfig, java.io.Serializable
{
public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
}
public interface Servlet {
public void init(ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();
public String getServletInfo();
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
public void destroy();
}
HttpServletRequest 接口和常见的方法
package cn.icanci.javaweb;
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;
/**
* @Author: icanci
* @ProjectName: javaweb
* @PackageName: cn.icanci.javaweb
* @Date: Created in 2020/2/6 23:15
* @ClassAction:
*/
@WebServlet("/req")
public class Test2Servlet extends HttpServlet {
@Override
public void init() throws ServletException {
super.init();
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(req.getMethod());
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()){
System.out.println(headerNames.nextElement());
}
System.out.println(req.getContextPath());
System.out.println(req.getServletContext());
String[] names = req.getParameterValues("name");
for (int i =0 ; i < names.length; i++) {
System.out.println(names[i]);
}
}
}
Servlet获取表单数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<form action="/jweb/login" method="get">
username:<input type="text" name="username" /><br>
password:<input type="password"name="password" /><br/>
<input type="submit" value="提交" />
</form>
</body>
</html>
package cn.icanci.javaweb;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(req.getParameter("username"));
System.out.println(req.getParameter("password"));
}
}
请求参数乱码问题解决
//对于post请求可以设置请求的编码 必须在获取参数之前设置 只对post优先
String encoding = getInitParameter("encoding");
System.out.println(encoding);
req.setCharacterEncoding(encoding);
//对于get请求 修改Tomcat/conf/server.xml文件 URIEncoding
<Connector connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>
get和post请求的区别
第一方面:安全性
get把数据追加在url上,明文显示,不安全,而post不是明文显示,相对安全。
第二方面:数据允许大小
get允许传递的数据只有2kb,而post则不限,
get只能向服务器发送ASCII字符,而post则可以发送整个ISO10646中的字符
第三方面:数据流
get只能传递字符型数据,不能传递二进制流数据,而post既可传递字符流也可传递二进制流。
第四方面:get和post对应的enctype属性有区别
enctype有两个值,默认值为application/x-www-form-urlencoded
而另一个值multipart/form-data只能用于post。
第五方面:由于一个get得到的结果直接对应到一个URI
所以get的结果页面有可能被浏览器缓存。而post一般则不能。
HttpServletResponse接口以及方法
package cn.icanci.javaweb;
import java.io.PrintWriter;
import java.io.OutputStream;
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.io.PrintWriter;
/**
* @Author: icanci
* @ProjectName: javaweb
* @PackageName: cn.icanci.javaweb
* @Date: Created in 2020/2/7 10:36
* @ClassAction:
*/
@WebServlet("/test1")
public class Test4Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// OutputStream os = resp.getOutputStream();
// os.write("spring is coming".getBytes());
//设置输出数据的编码方式 和 MIME类型 必须先设置 在获取流
resp.setContentType("text/html;charset=utf-8");
//网页输出流
PrintWriter pw = resp.getWriter();
pw.println("hello");
pw.println("我是中国人");
pw.println("hello</br> 我是中国人");
pw.close();
}
}
Servlet3.0对应JavaEE6,对应Tomcat7
使用注意:在web.xml中可以设置是否启用注解
也就是有一个注解: metadata-complete="false". 缺省情况就是这个
@WebServlet("/req")
@WebServlet(value = "/req",initParams = {
@WebInitParam(name = "encoding",value ="UTF-8"),
@WebInitParam(name = "encoding",value ="UTF-8")
})
一般,xml做通用配置,特别案例使用注解配置
启动Servlet就创建对象,并且加载相关参数 的配置 在启动服务器的时就创建对象,数值越小越优先优先创建,在SpringMVC框架的前端控制器就是如此配置
<load-on-startup>1</load-on-startup>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>Test1Servlet</servlet-name>
<servlet-class>cn.icanci.javaweb.Test1Servlet</servlet-class>
<!-- 在启动服务器的时候就创建对象,数值越小越优先优先创建,在SpringMVC框架的前端控制器就是如此配置 -->
<load-on-startup>1</load-on-startup>
</servlet>
</web-app>
Servlet线程不安全的问题 根本是原因是Servlet是单例的
如果定义为类非静态成员变量,那么此变量就会不安全,所以应该把成员变量设置为局部变量 使得每一个Service都对应一个值
Web组件之间跳转的方式
- 请求转发(forward)
请求转发从Servlet1,请求转发到Servlet2
Servlet1先完成一部分的功能,然后Servlet2再完成剩下的功能 语法如下
- 请求转发(forward)
req.getRequestDispatcher("/for/s2").forward(req,resp);
特点:
1.地址栏不发生改变
2.只发送了一个请求
3.共享请求中的数据
4.最终响应给了浏览器的是目标的内容
5.不可以跨域访问
6.可以访问WEB-INF中的资源
- URL重定向
语法
- URL重定向
resp.sendRedirect("/index.jsp");
1.浏览器地址发生该改变
2.发送了两次请求
3.因为是两次独立的请求,所以不能共享数据
4.可以跨域访问
5.不能访问WEB-INF中的资源
6.最终响应给浏览器的有最后一个请求决定
- 请求包含
在一个页面中可以包含其他的页面内容 在Servlet中没有意义,在JSP中有意义
- 请求包含
Servlet的三大作用域对象
目的:共享数据
request : 每一次请求都是一个新的request对象 ,如果需要在web组件之间共享同一个请求的数据,只能使用请求转发
session:每一次会话都是一个新的session对象,如果需要在一次会话多个请求之间需要共享数据,只能使用请求转发
application:应用对象,Tomcat启动到关闭,表示整个应用,在一个应用中只有一个application对象,作用于整个web应用,可以实现多次会话之间的数据共享
对象名称 和 类型
request HttpServletRequest
session HttpSession
servletContext(application) ServletContext
作用域如何共享数据
1.设置和修改
xxx.setAttribute(name,value);
2.获取
xxx.getAttribute(name)
3.删除
xxx.removeAttribute(name)
全局的初始化参数
<web-app>
<context-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</context-param>
</web-app>
Servlet的缺陷
Servlet不擅长做界面输出
擅长的
接收请求参数 封装成对象
调用业务方法,处理请求
控制页面跳转
Jsp的执行过程 (JSP本质就是Servlet)
Web容器处理JSP文件请求的执行过程主要包括以下4个部分:
1. 客户端发出Request请求
2. JSP Container 将JSP转译成Servlet的源代码
3. 将产生的Servlet源代码经过编译后,并加载到内存执行
4. 把结果Response(响应)至客户端
很多人都会认为JSP的执行性能会和Servlet相差很多,其实执行性能上的差别只在第一次的执行。因为JSP在执行第一次后,会被编译成Servlet的类文件,即.class,当再重复调用执行时,就直接执行第一次所产生的Servlet,而不再重新把JSP编译成Servelt。因此,除了第一次的编译会花较久的时间之外,之后JSP和Servlet的执行速度就几乎相同了。
在执行JSP网页时,通常可以分为两个时期:转译时期(Translation Time)和请求时期(Request Time)
转译时期:JSP网页转移成Servlet类。
请求时期:Servlet类执行后,响应结果至客户端。
转译期间做了两件事情:
转译时期:将JSP网页转移为Servlet源代码 .java.
编译时期:将Servlet 源代码 .java编译成 Servlet类 .class.
当JSP网页在执行时,JSP Container 会做检查工作,如果发现JSP网页有更新修改时,JSP Container 才会再次编译JSP成 Servlet; 如果JSP没有更新时,就直接执行前面所产生的Servlet.
http响应常用的状态码有哪些?分别是什么含义?
常用状态码:
状态码 | 代表状态 |
---|---|
200 | 成功 |
302 | 重定向的状态码 |
404 | 资源不存在 访问命令寻找不到 |
405 | 请求方式不正确 |
500 | 服务器内部异常 代码出现异常 |
状态码<400 | 成功 |
状态码>=400 | 失败 |
JSP的基本语法
1.JSP的注释 作用:注释Java脚本的代码 语法 <%-- 这是JSP注释 --%>
2.JSP的Java脚本表达式 <%=表达式>
3.JSP的Java脚本片段(实际开发,应该做到不能出现一行Java代码) <% int x = 0; %>
4.JSP的声明 定义类的成员变量 <%! int y = 1;%>
原理:其中的语句会原封不动的别服务器翻译到对应的Servlet类中,做为成员和方法
JSP的三大指令
JSP的标准指令:设定JSP网页的整体配置信息
特点:
1.并不向客户端输入任何输出
2.指令在JSP整个文件有效
3.为翻译阶段提供了全局信息
JSP的三大指令
1.page
2.include
3.taglib
page指令
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" errorPage="404.jsp" isErrorPage="false" %>
页面异常处理
除了可以使用上面的 page指令中的errorPage="404.jsp" isErrorPage="false" 也可以在web.xml中配置全局的错误页面
<!-- 全局的错误页面 开始 -->
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
JSP的四大作用域
作用域 | 范围 |
---|---|
pageContext | 当前界面 |
request | 同一个请求 |
session | 同一个会话 |
application | 整个应用 |
Jsp的九大内置对象 去哪儿看?
通过查看 Jsp 编译之后的 对象字节码文件来看
1.page
当前jsp页面本身 相当于this
2.pageContext
当前页面的上下文
可以用来获取其他内置对象
使用pageContext可以访问page request session application范围内的数据
3.request
请求对象 向客户端请求数据
4.response
响应对象
5.out
输出流对象 向客户端输出数据
6.session
会话 用来保存用户的信息
7.config
serlvetConfig类型的
用来配置servlet初始化参数
8.application
整个应用 整个工程
服务启动时 会为每个已经部署的项目 创建一个唯一对象
该对象实现 了ServletContext接口 由服务器实现
该对象一直存在。
通过该对象 可以获取与整个应用有关的一些方法。
作用:绑定数据 可以访问全局初始化参数
9.exception
异常对象
只能出现在 isErrorPage=true的页面中
3.MVC思想
顾名思义,三层架构分为三层,分别是“数据访问层”、“业务逻辑层”、“表示层”。
数据访问层:数据访问层在作业过程中访问数据系统中的文件,实现对数据库中数据的读取保存操作。
表示层:主要功能是显示数据和接受传输用户的数据,可以在为网站的系统运行提供交互式操作界面,
表示层的应用方式比较常见,例如Windows窗体和Web页面。
业务逻辑层:将用户的输入信息进行甄别处理,分别保存。
建立新的数据存储方式,在存储过程中对数据进行读取,将“商业逻辑”描述代码进行包含。
三层架构软件系统为用户的数据传输、提取、储存创造了便利条件。
在应用数据时,信息划分架构开发项目,
对各层次之间的工作职责进行清晰规划,这样就降低了网站系统的维护风险。
4.Cookie
HTTP是无状态的,服务端是不知道上一次是谁访问的自己,所以多个请求之间无法共享数据
解决方案
1.使用参数传递机制解决参数传递的问题 但是数据不安全
pw.println("<a href='/req/test?name='+"+name+">下一页</a>");
2.Cookie
1.创建Cookie对象
Cookie cookie = new Cookie("name","icanci");
参数:
name:当前Cookie的唯一一个名字
value:当前Cookie的值
2.把Cookie放入到相应中,响应给浏览器,把共享的数据存储到浏览器中
resp.addCookie(cookie);
3.获取Cookie的信息 因为Cookie是在请求头中,所以应该使用request获取
Cookie[] cookies = req.getCookies();
for(Cookie c : cookies){
System.out.println(c.getName());
System.out.println(c.getValue());
}
Cookie的细节
1.Cookie处理中文乱码的问题
System.out.println(URLDecoder.decode(c.getValue(),"UTF-8"));
2.修改Cookie中的指定属性名的属性值 同名会覆盖
Cookie cookie = new Cookie("name", "icanci");
Cookie c = new Cookie("name", "icanci.cn");
resp.addCookie(c);
Cookie cookie = new Cookie("name", "icanci");
cookie.setValue("icanci.cn");
resp.addCookie(cookie);
3.Cookie的分类
会话Cookie:关闭浏览器之后就没了 缺省情况
持久化Cookie:Cookie可以保存指定的时间段
设置Cookie的最大存活时间 时间单位是秒
Cookie cookie = new Cookie("name", "icanci");
cookie.setValue("icanci.cn");
cookie.setMaxAge(10 * 60);
seconds == 0 删除 cookie
seconds < 0 会话 cookie
seconds > 0 指定时间 cookie
4.Cookie的路径和缺陷
1.多个人使用同一个电脑,可以查看浏览器的Cookie,不安全
2.Cookie存储中文中文比较麻烦
3.Cookie的value是String类型,一个Cookie只能存储一个数据,如果需要存储多个数据,就需要有N的Cookie
4.一个站点对Cookie是有限制的 大小为 4K 一台服务器在一台客户端最多保存20个Cookie 一个浏览器最多保存300个Cookie
5.在设计上就有问题 Cookie 只能在一个地方保存,不能在服务器保存
5.HttpSession
Session是服务端技术 当访问服务器否个网页的时候,会在服务器端的内存里开辟一块内存,这块内存就叫做session,而这个内存是跟浏览器关联在一起的。这个浏览器指的是浏览器窗口,或者是浏览器的子窗口,意思就是,只允许当前这个session对应的浏览器访问,就算是在同一个机器上新启的浏览器也是无法访问的。而另外一个浏览器也需要记录session的话,就会再启一个属于自己的session
Session本质就是一个会话Cookie(浏览器关闭之后,Session就失效了)
1.创建Session对象
HttpSession session = req.getSession(true);//先找,没有就创建返回,有就返回
HttpSession session = req.getSession(false);//先找,没有就返回null,有就返回
HttpSession session = req.getSession();//先找,没有就创建返回,有就返回
2.向Session中存储取出数据
session.setAttribute("username","icanci");
session.getAttribute("username")
3.Session的细节
1.一般的,我们存储的Session中的属性名称要唯一.
习惯:XXX_IN_SESSION 比如:USERNAME_IN_SESSION
简述cookie和session的区别
2.如果需要存储的多个数据放到Session中,可以封装到对象中去
一般的,用的比较多的就是登陆信息
3.如果太多服务器之间需要共享Session,此时Session就要实现 java.io.Serializable接口
序列化[把对象存储为二进制文件]和反序列化 [把二进制文件恢复为对象]
4.删除Session
- 1.删除Session中指定属性名的值 session.removeAttribute("username");
- 2.销毁Session对象 session.invalidate(); [此处使用较多的是 退出网站]
5.Session的超时管理 //单位是秒 Tomcat默认是30分钟
session.setMaxInactiveInterval(15 * 60); //单位是秒
用户的两次操作时间不能超过15分钟,超过了就销毁session 就只能重新登陆
可以修改项目的web.xml 的<web-app> </web-app>标签内部配置文件设置超时时间 一把不修改
<web-app>
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
6.URL重写
Session是特殊的Cookie,浏览器可以禁用Cookie
此时可以在每一个资源后面添加sessionUID
String s = resp.encodeURL("/session/list");
System.out.println(s);
自动拼接
注意:在开发中都不会取消接收Cookie的
cookie 和session 的区别:
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗 考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。
当访问增多,会比较占用你服务器的性能 考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,
很多浏览器都限制一个站点最多保存20个cookie。
cookie 和session 的联系: session是通过cookie来工作的,可以考虑将登陆信息等重要信息存放为session
其他信息如果需要保留,可以放在cookie中。
在购物网站中通常将用户加入购物车的商品联通session_id记录到数据库中,
当用户再次访问是,通过sessionid就可以查找到用户上次加入购物车的商品。
因为sessionid是唯一的,记录到数据库中就可以根据这个查找了。
cookie | session |
---|---|
保存在客户端中 | 保存在服务器中 |
只能保存字符串 | 可以保存任意类型数据 |
保存的数据大小和浏览器有关 一般在4k左右 | 保存的数据大小理论上没有限制 只要服务器内存够用就行 |
相对安全性较低 | 安全性较高 |
分担了服务器的压力 | 增加了服务器压力 |