文章目录
Cookie、Session简述
会话(cookie、session):用户打开一个浏览器,点击多个超链接访问服务器多个web,然后关闭浏览器,整个过程就是会话
- 会话:一次会话中包含多次请求和响应。
一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止 - 功能:在一次会话的范围内的多次请求间,共享数据。
- 方式:(1) 客户端会话技术:Cookie(2) 服务器端会话技术:Session
Cookie、Session的区别
- 数据存放位置不同:
cookie数据存放在客户的浏览器bai上,session数据放在服务器上。
- 安全程度不同:
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。
- 性能使用程度不同:
session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
- 数据存储大小不同:
单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie,而session则存储与服务端,浏览器对其没有限制。
- 会话机制不同
session会话机制:session会话机制是一种服务器端机制,它使用类似于哈希表(可能还有哈希表)的结构来保存信息。
cookies会话机制:cookie是服务器存储在本地计算机上的小块文本,并随每个请求发送到同一服务器。 Web服务器使用HTTP标头将cookie发送到客户端。在客户端终端,浏览器解析cookie并将其保存为本地文件,该文件自动将来自同一服务器的任何请求绑定到这些cookie。
cookie(客户端会话技术)
cookie简介
Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息
-
概念:客户端会话技术,将数据保存到客户端
-
使用步骤:
(1)创建Cookie对象,绑定数据
new Cookie(String name, String value)
(2)发送Cookie对象
response.addCookie(Cookie cookie)
(3) 获取Cookie,拿到数据
Cookie[] request.getCookies()
-
实现原理:基于响应头set-cookie和请求头cookie实现
-
cookie的细节
(1) 一次可不可以发送多个cookie?
可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。
(2) cookie在浏览器中保存多长时间?
①默认情况下,当浏览器关闭后,Cookie数据被销毁
② 持久化存储:
setMaxAge(int seconds)
正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
负数:默认值
零:删除cookie信息
(3) cookie能不能存中文?
在tomcat 8 之前 cookie中不能直接存储中文数据,需要将中文数据转码—一般采用URL编码(%E3)
在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析
(4)cookie共享问题?
假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
默认情况下cookie不能共享,setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录
如果要共享,则可以将path设置为"/"(5)不同的tomcat服务器间cookie共享问题?
setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享 -
Cookie的特点和作用
(1)cookie存储数据在客户端浏览器
(2)浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)
(4)作用: cookie一般用于存出少量的不太敏感的数据,在不登录的情况下,完成服务器对客户端的身份识别
cookie基础用法
@Controller
public class CookieTest {
@RequestMapping("cookie")
public String cookie(HttpServletResponse response, HttpServletRequest request, Model model) throws UnsupportedEncodingException {
// 创建一个cookie对象
Cookie cookie = new Cookie("cookie", "one");
// 将cookie添加到response响应中
response.addCookie(cookie);
// 获取请求中的所有cookie对象组成的数组
Cookie[] findCookie = request.getCookies();
// 循环输出cookie
for (Cookie cookies:findCookie){
// 解决cookie中有中文的问题
URLEncoder.encode(cookies.getValue(), "utf-8");
// 获取cookie名字
System.out.println(cookies.getName());
// 获取cookie值
System.out.println(cookies.getValue());
// 设置/修改cookie的值
cookies.setValue("two");
System.out.println(cookies.getValue());
// 设置cookie的最大生存空间
cookies.setMaxAge(5000);
// 设置cookie的path(是指cookie的path为当前web应用的虚拟路径,
// nudist是为了保证浏览器在访问当前应用下任何一个资源时都能带着cookie)
cookies.setPath("/");
// 删除cookie
cookies.setMaxAge(0);
model.addAttribute("cookie", cookies);
}
return "Cookie";
}
}
案例一:获取上次访问时间
@RequestMapping("returntime")
protected void ReturnTime(HttpServletRequest request, HttpServletResponse response) throws Exception {
Cookie[] cookies = request.getCookies();
boolean flag = false;//首次登陆无lastName cookie
response.setContentType("text/html;charset=utf-8");
if (cookies != null && cookies.length > 0) {
for (Cookie cookie : cookies) {
//获取cookie的name进行判断
if ("lastName".equals(cookie.getName())) {
flag = true;
//1. 获取上次登录的时间
String value = cookie.getValue();
//1.1 cookie的value进行url解码
String decode_value = URLDecoder.decode(value, "utf-8");
response.getWriter().write("欢迎回来,上次访问时间是" + decode_value);
//2、设置Cookie的value
//2.1获取当前的时间值,重新设置cookie的值,并重新发送
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format_date = simpleDateFormat.format(date);
//2.2使用url编码
String str_date = URLEncoder.encode(format_date, "utf-8");
//2.3 设置cookie的值
cookie.setValue(str_date);
//2.4 设置cookie的存活时间 一个月
cookie.setMaxAge(60 * 60 * 24 * 30);
//2.5 写回cookie
response.addCookie(cookie);
break;
}
}
}
//首次登录的情况
if (cookies == null || cookies.length == 0 || flag == false) {
//1 打印信息
response.getWriter().write("首次访问,欢迎您");
//2 获取当前时间
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年mm月dd日 HH:mm:ss");
String format_date = simpleDateFormat.format(date);
//3、将新的value使用url编码,写回response
String str_date = URLEncoder.encode(format_date, "utf-8");
Cookie cookie = new Cookie("lastName", str_date);
cookie.setMaxAge(60 * 60 * 24 * 30);
response.addCookie(cookie);
}
}
案例二:完成浏览记录的保存和删除
Controller
@Controller
public class ProductServlet {
@RequestMapping("product_list")
private String product_list(HttpServletRequest request, HttpServletResponse response, String id) throws ServletException, IOException {
//获取请求中的参数
String ids = request.getParameter("id");
Cookie[] cookies = request.getCookies();
Cookie findCookie = findCookie(cookies, "bshistory");
if (findCookie == null) {//第一次浏览
Cookie cookie = new Cookie("bshistory", id);
response.addCookie(cookie);
} else {//第二次浏览及以后浏览
//得到之前保存在Cookie的商品id信息
String lastId = findCookie.getValue();
//将现在点击商品id的和之前的拼接
findCookie.setValue(id + "#" + lastId);
response.addCookie(findCookie);
String value = findCookie.getValue();
System.out.println(value);
}
//跳转到商品信息页面
return "Productlnfo";
}
//根据name找到相应的cookie
private Cookie findCookie(Cookie[] cookies, String name) {
if (cookies != null) {
for (Cookie cookie : cookies) {
if (name.equals(cookie.getName())) {
return cookie;
}
}
}
return null;
}
@RequestMapping("ClearBRServlet")
public String ClearBRServlet(HttpServletRequest request, HttpServletResponse response) {
Cookie cookie = new Cookie("bshistory", "");
cookie.setMaxAge(0);//参数设置为0,Cookie立即失效,下次浏览器发送请求将不会在携带该Cookie
response.addCookie(cookie);
return "product_list";
}
}
jsp
<%@page import="org.apache.jasper.tagplugins.jstl.core.ForEach"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>商品列表</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!--需要引入JQuery-->
<script type="text/javascript" src="js/jquery-3.4.1.js" ></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6">
<a href="product_list?id=1" >苹果iPhone11</a>
<p><font color="#FF0000">价格:¥6799</font></p>
</div>
<div class="col-md-6">
<a href="product_list?id=2">华为Mate30 Pro</a>
<p><font color="#FF0000">价格:¥5799</font></p>
</div>
</div>
<div class="row">
<div class="col-md-6">
<a href="product_list?id=3">OPPO Find X</a>
<p><font color="#FF0000">价格:¥4999</font></p>
</div>
<div class="col-md-6">
<a href="product_list?id=4">vivo NEX 3</a>
<p><font color="#FF0000">价格:¥4998</font></p>
</div>
</div>
<div class="row">
<div class="col-md-6">
<a href="product_list?id=5">一加7T迈凯伦 </a>
<p><font color="#FF0000">商城价:¥5299</font></p>
</div>
<div class="col-md-6">
<a href="product_list?id=6">小米MIX Alpha</a>
<p><font color="#FF0000">商城价:¥19999</font></p>
</div>
</div>
</div>
<div class="container">
<div class="row">
<h3>浏览记录:</h3>
<%
Cookie[] cookies=request.getCookies();
if(cookies != null){
for (Cookie cookie : cookies) {
if("bshistory".equals(cookie.getName())){
String[] ids=cookie.getValue().split("#");
for(String i : ids){
%>
<%=i%> <br>
<%
}
}
}
}else{
%>
<h4>无浏览记录</h4>
<%
}
%>
</div>
</div>
<div class="container">
<div class="row">
<a href="ClearBRServlet" ><h5>清除浏览记录</h5></a>
</div>
</div>
</body>
</html>
Session(服务器端会话技术)
session简介与工作原理
Session对象存储及配特定用户会话所需的属性置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项
session的工作原理:
- 当一个session第一次被启用时,一个独一的标识被存储于本地的cookie中。
- 首先使用session_start()函数,PHP从session仓库中加载已经存储的session变量。
- 当执行PHP脚本时,通过使用session_register()函数注册session变量。
- 当PHP脚本执行结束时,未被销毁的session变量会被自动保存在本地一定路径下的session库中,这个路径可以通过php.ini文件中的session.save_path指定,下次浏览网页时可以加载使用。
Session基础用法
@Controller
public class sessionTest {
@RequestMapping("session")
public void session(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 解决乱码
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//使用request对象的getSession()获取session,如果session不存在则创建一个
HttpSession session = request.getSession();
//将数据存储到session中
session.setAttribute("data", "孤傲苍狼");
//获取session的Id
System.out.println("session的id"+session.getId());
//获取当前session对象的创建时间(要转换成时间类型)
Date CreationTime = new Date(session.getCreationTime());
System.out.println("session创建时间"+CreationTime);
//获取最后一次访问该session对象的时间
Date LastAccessedTime = new Date(session.getCreationTime());
System.out.println("最后一次访问session"+LastAccessedTime);
//设置Session最大时效
session.setMaxInactiveInterval(5000);
//获取Session最大时效
Date MaxInactiveInterval = new Date(session.getMaxInactiveInterval());
System.out.println("最大时效"+MaxInactiveInterval);
//判断session是不是新创建的
if (session.isNew()) {
response.getWriter().print("session创建成功,session的id是:"+session.getId());
}else {
response.getWriter().print("服务器已经存在该session了,session的id是:"+session.getId());
}
//获取session
HttpSession findsession = request.getSession();
// 获取session中所有的键值
Enumeration<String> attrs = findsession.getAttributeNames();
// 遍历attrs中的
while(attrs.hasMoreElements()) {
// 获取session键值
String name = attrs.nextElement().toString();
// 根据键值取session中的值
Object vakue = findsession.getAttribute(name);
// 打印结果
System.out.println("------" + name + ":" + vakue + "--------\n");
}
//销毁当前Session对象
session.invalidate();
}
}
Redis缓存
Redis简介
redis是什么
是一个开源的使用ANSI c语言编写、支持网络、可基于内存亦可持久化的日志型、key-value数据库,并提供多种语言的API。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在基础上实现了master-slave(主从同步)
免费和开源!是当下最热门的NoSQL技术之一,也被人称之为结构化数据库
redis能干什么
- 内存存储、持久化,内存中是断电即失,所以说持久化很重要(rdb、aof)
- 效率高,可以用于高速缓存
- 发布订阅系统
- 地图信息分析
- 计时器、计数器(浏览量)
redis特性
多样的数据类型、持久化、集群、事务
各个类型的应用场景
redis使用
redis学习中用到的东西
redis官网:https://redis.io/
redis中文网:http://www.redis.cn/
Windows安装
- 下载安装包:https://github.com/dmajkic/redis/releases
- 下载完毕得到压缩包
- 解压到自己电脑上的环境目录下就可以
- 开启redis,双击运行服务即可!
- 使用redis客户端连接redis
Linux安装
-
在windows上下载redis https://redis.io/download/
-
将安装包导入到linux的home目录
-
将压缩包移动到opt下解压
-
进入解压后的文件,可以看到redis的配置文件
-
基本的环境安装.
//把所有需要配置的文件都配置上 make install //查看配置 ``` 
-
redis的默认安装路径在"/usr/local/bin"
Redis实现存取数据
-
添加依赖
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.7</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>2.1.3.RELEASE</version> </dependency>
-
Mapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper
namespace="com.fz.mapper.NewsMapper">
<resultMap id="BaseResultMap" type="com.fz.entity.News">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="title" jdbcType="VARCHAR" property="title" />
<result column="body" jdbcType="VARCHAR" property="body" />
</resultMap>
<select id="query" resultType="com.fz.entity.News">
select id ,title,body from news
</select>
<select id="selectAll" resultType="com.fz.entity.News">
select id ,title,body from news
</select>
<insert id="add" keyProperty="id" useGeneratedKeys="true">
insert into news (title,body) values (#{title},#{body})
</insert>
</mapper>
- ServiceImpl
@Service
public class NewsServiceImpl implements NewsService{
@Autowired
private NewsMapper mapper;
@Override
public List<News> selectAll() throws IOException {
Jedis jedis =new Jedis();
String key = "listNews";
ObjectMapper on = new ObjectMapper(); //josn
if (jedis.exists(key)){//判断缓存有没有存在key
System.out.println("从缓存中取出数据...");
return on.readValue(jedis.get(key),new TypeReference<List<News>>(){}); //如果有就从缓存里面取数据
}//没有则从数据库去取
List<News> news = mapper.query();
jedis.set(key,on.writeValueAsString(news)); //然后设置键和数据
return news; //返回
}
@Override
public void add(News news) { //每次添加时判短键是否存在,如果存在首先删除
Jedis jedis = new Jedis();
String key="listNews";
if(jedis.exists(key))
jedis.del(key);
mapper.add(news);
} }
-
测试
RootConfig.class) public class NewsServiceImplTest { @Autowired`在这里插入代码片` private NewsServiceImpl NewsServiceImpl; @Test public void selectAll() throws IOException { List<News> news = NewsServiceImpl.selectAll(); System.out.println(news); } } }
梦想也许在今天无法实现,但重要的是,它在你心里。重要的是,你一直在努力,加油!!!