redis——对项目的一些优化方案

这是我们之前项目的业务流程,做一下简单介绍。

登录:

用户输入账号、密码、验证码。我们先判断用户输入的验证码是不是我们session存的验证码,然后去查账号密码是否正确。

如果登录成功,发送给用户一张凭证(ticket)。

登录后

之后的每次请求,用户携带ticket,服务器得到后,根据ticket去login_ticket表中查找登录信息,并且根据登录信息再查user表获得更多的用户信息。

使用Redis存储验证码


- 验证码需要频繁的访问与刷新,对性能要求较高。
- 验证码不需永久保存,通常在很短的时间后就会失效。
- 分布式部署时,存在Session共享的问题。

我们重构思路:进入登录页面会访问验证码方法,此方法会自动生成一个验证码和图片,将验证码和图片输出给浏览器,并且下发一个cookies,这个cookies里面存的是一段随机数,这段随机数作为key存在redis里面(之前是存session),value就是验证码,并设置一个过期时间;

    //验证码@RequestMapping(path = "/kaptcha", method = RequestMethod.GET)public void getKaptcha(HttpServletResponse response/*, HttpSession session*/) {// 生成验证码String text = kaptchaProducer.createText();BufferedImage image = kaptchaProducer.createImage(text);// 将验证码存入session//session.setAttribute("kaptcha", text);//验证码的归属String owner= CommunityUtil.generateUUID();Cookie cookie=new Cookie("kaptchaOwner",owner);cookie.setMaxAge(60);cookie.setPath(contextPath);response.addCookie(cookie);//存入redisString redisKey= RedisKeyUtil.getKaptchaKey(owner);redisTemplate.opsForValue().set(redisKey,text,60, TimeUnit.SECONDS);// 将图片输出给浏览器response.setContentType("image/png");try {OutputStream os = response.getOutputStream();ImageIO.write(image, "png", os);} catch (IOException e) {logger.error("响应验证码失败:" + e.getMessage());}}
    @RequestMapping(path = "/login",method = RequestMethod.POST)public String login(String username,String password,String code,boolean rememberme,Model model,/*HttpSession session,*/HttpServletResponse response,@CookieValue("kaptchaOwner") String kaptchaOwner){// 检查验证码//String kaptcha = (String) session.getAttribute("kaptcha");String kaptcha=null;if(StringUtils.isNotBlank(kaptchaOwner)){String redisKey=RedisKeyUtil.getKaptchaKey(kaptchaOwner);kaptcha=(String) redisTemplate.opsForValue().get(redisKey);}if(StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equalsIgnoreCase(code)){model.addAttribute("codeMsg", "验证码不正确!");return "/site/login";}// 检查账号,密码int expiredSeconds = rememberme ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS;Map<String, Object> map = userService.login(username, password, expiredSeconds);if (map.containsKey("ticket")) {Cookie cookie = new Cookie("ticket", map.get("ticket").toString());cookie.setPath(contextPath);cookie.setMaxAge(expiredSeconds);response.addCookie(cookie);return "redirect:/index";} else {...}}


使用Redis存储登录凭证


- 处理每次请求时,都要查询用户的登录凭证,访问的频率非常高。

登录时不存MySQL里,存redis里

    public Map<String,Object> login(String username,String password,int expiredSeconds){Map<String,Object> map=new HashMap<>();// 生成登录凭证LoginTicket loginTicket = new LoginTicket();loginTicket.setUserId(user.getId());loginTicket.setTicket(CommunityUtil.generateUUID());loginTicket.setStatus(0);loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000));//loginTicketMapper.insertLoginTicket(loginTicket);String redisKey= RedisKeyUtil.getTicketKey(loginTicket.getTicket());redisTemplate.opsForValue().set(redisKey,loginTicket);...}

查找

退出时也是改redis 

    public void logout(String ticket) {//loginTicketMapper.updateStatus(ticket, 1);String redisKey= RedisKeyUtil.getTicketKey(ticket);LoginTicket loginTicket=(LoginTicket) redisTemplate.opsForValue().get(redisKey);loginTicket.setStatus(1);redisTemplate.opsForValue().set(redisKey,loginTicket);}


使用Redis缓存用户信息


- 处理每次请求时,都要根据凭证查询用户信息,访问的频率非常高。

缓存用户信息:因为会经常根据userid来查询user对象,所以使用redis来缓存提高服务器性能。使用redis的String类型,存入user对象,会自动将整个对象转换成json字符串,同时设置过期时间;

取值:优先从redis中取,取不到的时候从mysql中取,并将数据初始化到redis中

更新:更新的时候先更新mysql中的值,然后清除缓存数据;

    // 1.优先从缓存中取值private User getCache(int userId) {String redisKey = RedisKeyUtil.getUserKey(userId);return (User) redisTemplate.opsForValue().get(redisKey);}// 2.取不到时初始化缓存数据private User initCache(int userId) {User user = userMapper.selectById(userId);String redisKey = RedisKeyUtil.getUserKey(userId);redisTemplate.opsForValue().set(redisKey, user, 3600, TimeUnit.SECONDS);return user;}// 3.数据变更时清除缓存数据private void clearCache(int userId) {String redisKey = RedisKeyUtil.getUserKey(userId);redisTemplate.delete(redisKey);}
    public User findUserById(int id) {
//        return userMapper.selectById(id);User user = getCache(id);if (user == null) {user = initCache(id);}return user;}
    public int updateHeader(int userId, String headerUrl) {//return userMapper.updateHeader(userId, headerUrl);int rows=userMapper.updateHeader(userId, headerUrl);clearCache(userId);return rows;}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445141.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度模型压缩论文(02)- BlockSwap: Fisher-guided Block Substitution for Network Compression

文章目录1.摘要和背景1.1 摘要1.2 背景2.方法和贡献2.1 方法2.2 贡献3.实验和结果3.1 实验3.2 结果4.总结和展望4.1 总结4.2 展望本系列是在阅读深度神经网络模型小型化方面论文时的笔记&#xff01;内容大部分从论文中摘取&#xff0c;也会有部分自己理解&#xff0c;有错误的…

深度模型压缩论文(01)- Meta Filter Pruning to Accelerate Deep Convolutional Neural Networks

文章目录1.摘要和介绍1.1摘要部分2.背景和方法2.1 背景2.2 贡献2.3 方法3.实验和结果3.1 实验3.2 结果4.总结和展望4.1 总结4.2 展望本系列是在阅读深度神经网络模型小型化方面论文时的笔记&#xff01;内容大部分从论文中摘取&#xff0c;也会有部分自己理解&#xff0c;有错误…

深度模型压缩论文(03)- Be Your Own Teacher: Improve the Performance of Convolutional Neural Networks via Self

文章目录1.摘要和背景1.1 摘要1.2 背景2.方法和贡献2.1 方法2.1.1 训练过程2.1.2 loss介绍2.2 贡献3.实验和结果3.1 实验3.2 结果4.总结和展望4.1 总结4.2 展望主要贡献&#xff1a;基于网络蒸馏方法&#xff0c;提出了一种提升裁剪后模型的精度的方法&#xff01;将训练时间大…

关系数据库——基础

数据库系统概论 四个基本概念 数据&#xff1a;数据库中存储的基本对象&#xff0c;描述一个事物的符号记录&#xff0c;数据和其语义不可分开说 数据库&#xff08;DB&#xff09;&#xff1a;是长期储存在计算机内、有组织的、可共享的大量数据的集合。 数据库管理系统&a…

Python(27)-模块

模块、包1.模块导入的方式2.使用as给模块取一个别名&#xff08;大驼峰命名法&#xff09;3.从模块中导入部分工具4.从模块中导入全部工具5.模块搜索顺序6__name__7.包8.发布模块、安装模块、卸载包9.pip安装第三方模块本系列博文来自学习《Python基础视频教程》笔记整理&#…

如何使用docker配置深度学习开发环境

文章目录1.底层驱动的安装1.1 操作系统的安装1.2 显卡驱动的安装1.3 cuda的安装2.使用docker配置深度学习开发环境2.1 docker的安装2.2 nvidia_docker的安装2.3 安装过程中的问题2.3.1 docker和nvidia_docker的版本不匹配的问题。2.3.2 解决每次运行docker命令的时候要加sudo.2…

反射全解

反射的概念 反射的引入&#xff1a; Object obj new Student(); 若程序运行时接收到外部传入的一个对象&#xff0c;该对象的编译类型是Object&#xff0c;但程序又需要调用该对象运行类型的方法&#xff1a; 1.若编译和运行类型都知道&#xff0c;使用 instanceof判断后&…

CRegKey 注册表操作

1.简介 CRegKey提供了对系统注册表的操作方法&#xff0c;通过CRegKey类&#xff0c;可以方便的打开注册表的某个分支或子键&#xff08;CRegKey::Open&#xff09;&#xff0c;可以方便的修改一个键的键值&#xff08;CRegKey::SetValue&#xff09;&#xff0c;也可以查询某…

进程基础

进程的基本概念 程序顺序执行的特征&#xff1a; 1&#xff09;顺序性&#xff1a;处理机严格按照程序所规定的顺序执行&#xff0c;每一步操作必须在下一步操作开始前执行 2&#xff09;封闭性&#xff1a;程序在封闭的环境下运行&#xff0c;程序独占资源&#xff0c;资源的状…

用Docker容器自带的tensorflow serving部署模型对外服务

相信很多人和我一样&#xff0c;在试图安装tensorflow serving的时候&#xff0c;翻遍了网上的博客和官网文档&#xff0c;安装都是以失败而告终&#xff0c;我也是一样&#xff0c;这个问题折磨了我两个星期之久&#xff0c;都快放弃了。幸运的是在同事的建议下&#xff0c;我…

C资源

云风最近写了一篇博客《C语言的前世今生》。作为长期使用C语言开发网络游戏服务器的程序员&#xff0c;云风是有理由写这样一篇文字&#xff0c;不过还是感觉谈的不够深入&#xff0c;C语言在业界使用的现状没有怎么描写&#xff0c;有些意犹未尽。在这里想比较系统的谈谈个人对…

面试题汇总---深度学习(图像识别,NLP内容)

文章目录1.基本概念1.1 为什么神经网络中深度网络的表现比广度网络表现好&#xff1f;1.2 推导BP算法1.3 什么是梯度消失和梯度爆炸&#xff1f;1.4 常用的激活函数有哪些&#xff1f;1.5 常用的参数更新方法有哪些&#xff1f;1.6 解决过拟合的方法&#xff1f;数据层面模型层…

Python(28)-文件,os模块

文件1. 文件2. 文件的基本操作3. 读取文件open()3.1 文件指针: 标记从哪一个位置开始读取数据.3.2 文件的打开方式mode3.3 文件按行读取3.3.1 readline()3.3.2 readlines()4.文件输出f.write(),print()5.文件复制5.1 小文件复制&#xff08;搬家&#xff09;5.2 大文件复制&…

IOCP的程序

C代码 #include <winsock2.h> #include <mswsock.h> #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <assert.h> #include "vld.h" #pragma message("automatic link to ws2_32.lib and…

PaperNotes(3)-图像分割-RCNN-FCN-Boxsup

图像分割算法对比小结1.{基本概念}2.{R-CNN}2.1R-CNN 网络结构选择性搜索算法为什么选择SVM作分类器边框回归2.2{R-CNN 训练}2.3{R-CNN实验结果}2.4{R-CNN语义分割}2.5{补充材料}2.5.1{R-CNN建议区域放缩}2.5.2{IOU阈值设置不一样的原因}2.5.3{Bounding-box回归修正}2.6{R-CNN存…

Python模块(3)--PIL 简易使用教程

PIL模块-用与记1.图片导入Image.open()2.图像显示.show()4.查看图片属性.format,.size,.mode3.图像格式转换.convert()4.图像模式“L”&#xff0c;“RGB”,"CYMK"5. 图片旋转.rotate()旋转方式1&#xff1a;旋转不扩展旋转方式2&#xff1a;旋转扩展旋转方式3&#…

输入输出系统

I/O设备&#xff1a;输入输出和存储功能的设备 I/O设备的分类 按传输的速度&#xff1a; 低速设备&#xff08;如键盘、鼠标、语音输入输出设备&#xff09; 中速设备&#xff08;如行式打印机、激光打印机等&#xff09; 高速设备&#xff08;如磁带机、磁盘机、光盘机等&…

模拟银行家算法

介绍 data.h #ifndef _Data_h_ #define _Data_h_#include <stdio.h> #include <stdlib.h> #include <string.h>#define ElemType PCB #define Status int #define true 1 #define false 0 #define OK 1 #define ERROR 0 #define RESOURCE_NUM …

js知识点汇总

1.本门课的作用&#xff08;JavaScript的作用&#xff09;所有基于Web的程序开发基础 2.一种计算机客户端脚本语言&#xff0c;主要在Web浏览器解释执行。 3.浏览器中Javascript&#xff0c;用于与用户交互&#xff0c;以及实现页面中各种动态特效 4.在HTML文件中&#xff0…

关于Java中String的问题

String 对象的两种创建方式&#xff1a; String str1 "abcd";//先检查字符串常量池中有没有"abcd"&#xff0c;如果字符串常量池中没有&#xff0c;则创建一个&#xff0c;然后 str1 指向字符串常量池中的对象&#xff0c;如果有&#xff0c;则直接将 st…