jsp文件通常用common_springboot还能这样用redis

点击蓝字 关注我们 

da9fbf1673f2d371a3e30c018cfd343d.png

作者:xfk

https://www.cnblogs.com/xfk1999/p/11347793.html

一直想在springboot上集成带缓存的redis,终于成功了。网上有1000种写法,想找到一篇合适的还真不容易?。走下流程,加深下印象。

 环境:

springboot版本:2.1.7

orm框架:mybatis

实现?:

在serviceImpl层方法上加注解@Cacheable和@CachEvict。

@Cacheable把数据放进redis,下一次需要数据直接在缓存中取;@CacheEvict使redis中的缓存失效。

关于注解的更多详细可以参考https://www.cnblogs.com/fashflying/p/6908028.html写得很详细。

准备工作:

pom.xml?:

org.springframework.bootspring-boot-starter-parent2.1.7.RELEASEorg.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-testtestjavax.servletjavax.servlet-apijavax.servletjstlorg.apache.tomcat.embedtomcat-embed-jasperorg.springframework.bootspring-boot-devtoolstruemysqlmysql-connector-java5.1.21org.mybatis.spring.bootmybatis-spring-boot-starter1.1.1org.mybatis.generatormybatis-generator-core1.3.7com.fasterxml.jackson.datatypejackson-datatype-jsr310org.springframework.bootspring-boot-starter-data-redis

application.properties文件?:

#mvcspring.mvc.view.prefix=/WEB-INF/jsp/spring.mvc.view.suffix=.jsp#mysqlspring.datasource.url=jdbc:mysql://localhost:3306/common?characterEncoding=utf-8spring.datasource.username=xfkspring.datasource.password=123456spring.datasource.driver-class-name=com.mysql.jdbc.Driver#mybatismybatis.mapper-locations=classpath:/mapper/*.xmlmybatis.type-aliases-package=com.xfk.sb.pojo#redisspring.redis.database=0spring.redis.host=127.0.0.1spring.redis.port=6379spring.redis.password=spring.redis.timeout=5000

书写:

一,允许使用缓存:

?在springboot的主启动类上添加注解@EnableCaching

SbApplication.java

package com.xfk.sb;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cache.annotation.EnableCaching;@SpringBootApplication@EnableCachingpublic class SbApplication {public static void main(String[] args) {        SpringApplication.run(SbApplication.class, args);    }}

 二,redis配置类:

?这里一个重要的点就是Serializer。RedisCache默认使用的是JdkSerializationRedisSerializer,我们要实现json格式的数据在redis上的存储。利用Jackson2JsonRedisSerializerGenericJackson2JsonRedisSerializer,其优点是存储的长度小。在这里我们用GenericJackson2JsonRedisSerializer。成功之后可以换Jackson2JsonRedisSerializer试试,看一看存储的数据有什么不同。

?cacheManager方法是用作注解@Cacheable和@CacheEvict执行service实现层方法缓存数据的,另外就是定义一个redisTemplate,哪个controller需要就在哪个controller中注入,灵活使用。

RedisConfig.java

package com.xfk.sb.config;import org.springframework.cache.annotation.CachingConfigurerSupport;import org.springframework.cache.annotation.EnableCaching;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheConfiguration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.*;import java.time.Duration;@Configuration@EnableCachingpublic class RedisConfig extends CachingConfigurerSupport {// 过期时间private Duration timeToLive = Duration.ofHours(12);@Beanpublic RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()                .entryTtl(this.timeToLive)                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))                .disableCachingNullValues();return RedisCacheManager.builder(connectionFactory)                .cacheDefaults(config)                .transactionAware()                .build();    }    @Bean(name = "redisTemplate")public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {        RedisTemplate redisTemplate = new RedisTemplate<>();        redisTemplate.setConnectionFactory(redisConnectionFactory);        redisTemplate.setKeySerializer(keySerializer());        redisTemplate.setHashKeySerializer(keySerializer());        redisTemplate.setValueSerializer(valueSerializer());        redisTemplate.setHashValueSerializer(valueSerializer());return redisTemplate;    }private RedisSerializer keySerializer() {return new StringRedisSerializer();    }private RedisSerializer valueSerializer() {return new GenericJackson2JsonRedisSerializer();    }}

三,增删改查Demo:

简单的pojo类,Student.java

package com.xfk.sb.pojo;public class Student {private int id;private String name;private int age;public Student() {    }public int getId() {return id;    }public void setId(int id) {this.id = id;    }public String getName() {return name;    }public void setName(String name) {this.name = name;    }public int getAge() {return age;    }public void setAge(int age) {this.age = age;    }@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", age=" + age +'}';    }}

?我使用的是mybatis的注解方式,简单的几个增删改查方法。

xml文件,studentMapper.xml

<?xml version="1.0" encoding="UTF-8"?>/span>        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">        select * from student        delete from student where id = #{id}        insert into student(id, name, age) values(null, #{student.name}, #{student.age})        update student set name=#{student.name}, age=#{student.age} where id = #{student.id}        select * from student where id = #{id} limit 1

mapper接口,StudentMapper.java

package com.xfk.sb.mapper;import com.xfk.sb.pojo.Student;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Param;import org.springframework.stereotype.Component;import java.util.List;@Mapper@Componentpublic interface StudentMapper {List selectStudent();int deleteStudent(@Param("id")int id);int createStudent(@Param("student")Student student);int updateStudent(@Param("student")Student student);Student selectStudentByPrimaryKey(@Param("id")int id);}

service层接口,StudentService.java

package com.xfk.sb.service;import com.xfk.sb.pojo.Student;import java.util.List;public interface StudentService {List selectStudent();int deleteStudent(int id);int createStudent(Student student);int updateStudent(Student student);Student selectStudentByPrimaryKey(int id);}

service实现层,StudentServiceImpl.java

package com.xfk.sb.service.implement;import com.xfk.sb.mapper.StudentMapper;import com.xfk.sb.pojo.Student;import com.xfk.sb.service.StudentService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.annotation.CacheConfig;import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.Cacheable;import org.springframework.cache.annotation.Caching;import org.springframework.stereotype.Service;import java.util.List;@Service@CacheConfig(cacheNames="students")public class StudentServiceImpl implements StudentService {private final StudentMapper studentMapper;@Autowiredpublic StudentServiceImpl(StudentMapper studentMapper) {this.studentMapper = studentMapper;    }@Cacheable(key="'students'")@Overridepublic List selectStudent() {        System.out.println("从数据库中取selectStudent");return studentMapper.selectStudent();    }@Override@Caching(evict={            @CacheEvict(key="'singleStudent'+#id"),@CacheEvict(key="'students'"),    })public int deleteStudent(int id) {        System.out.println("从数据库中删除deleteStudent");return studentMapper.deleteStudent(id);    }@Override@Caching(evict={            @CacheEvict(key="'singleStudent'+#student.id"),@CacheEvict(key="'students'"),    })public int createStudent(Student student) {        System.out.println("从数据库中创建createStudent");return studentMapper.createStudent(student);    }@Caching(evict={            @CacheEvict(key="'singleStudent'+#student.id"),@CacheEvict(key="'students'"),    })@Overridepublic int updateStudent(Student student) {        System.out.println("从数据库中更新updateStudent");return studentMapper.updateStudent(student);    }@Cacheable(key="'singleStudent'+#p0")@Overridepublic Student selectStudentByPrimaryKey(int id) {        System.out.println("从数据库中取一个selectStudentByPrimaryKey");return studentMapper.selectStudentByPrimaryKey(id);    }}

?使用@CacheConfig注解,相当于在redis数据库下建一个文件夹,以cacheNames作为文件夹的名字,统一管理这个实现层缓存的数据。正如在Redis Desktop Manager下看到的目录结构,db0下有一个students文件夹。

6bfaafbe45d1db40d54dc95a5d6f44da.png

?使用@Cacheable注解使缓存生效,以实现层的selectStudentByPrimaryKey()方法为例,从数据库中根据id查询一个Student对象。

使用@Cacheable(key="'singleStudent'+#p0"),#p0就是形参parameter0,多个参数就是#p1,#p2,,,也可以写成#id,注意singleStudent字符串一定要用单引号扩上,然后使用字符串的拼接模式,这个变量的规则是spring的EL表达式,一定要用加上#符号,如果是一个对象则可以直接用"."引用属性,参考createStudent()方法中的#student.id 。

属性key相当于在students文件夹下的文件夹创建一条以singleStudent+#p0为名字的一条缓存数据,在Redis Desktop Manager可以看到,由于students文件夹下的文件夹没有名字,所以成功缓存数据的命名是students::singleStudent1,两个引号之间为空。这就相当以这个命名空间下的唯一key,可以根据唯一key准确的失效缓存数据。

?@CacheEvict注解使缓存失效,根据需求要保证数据库与缓存的一致性,所以操作数据库之后要同步缓存。

在更新,删除和增加后要使缓存失效,不能返回过时的信息。在这里使用@Caching的目的是使多条缓存失效,它集合了@Cacheable,@CacheEvict,@CachePut,可以很直观的管理生效与失效。还可以直接使用@CacheEvict(allEntries=true)使这个命名空间下的所有缓存失效。

到这里核心工作完成得差不多了,就还差controller返回视图层了。

controller层,StudentController.java

package com.xfk.sb.web;import com.xfk.sb.pojo.Student;import com.xfk.sb.service.StudentService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.*;import java.util.List;@Controllerpublic class StudentController {private final StudentService studentService;private final StringRedisTemplate redis;@Autowiredpublic StudentController(StudentService studentService, StringRedisTemplate redis) {this.studentService = studentService;this.redis = redis;    }@GetMapping("/students")public String listStudent(Model model){        List students = studentService.selectStudent();        model.addAttribute("students", students);return "listStudent";    }@DeleteMapping("/students/{id}")public String deleteStudent(@PathVariable("id")int id) throws Exception{        studentService.deleteStudent(id);return "redirect:/students";    }@PutMapping("/students")public String updateStudent(Student student){        studentService.updateStudent(student);return "redirect:/students";    }@PostMapping("/students")public String createStudent(Student student){        studentService.createStudent(student);return "redirect:/students";    }@GetMapping("/students/{id}")public String editStudent(@PathVariable("id")int id, Model model){        Student s = studentService.selectStudentByPrimaryKey(id);        model.addAttribute("student", s);return "editStudent";    }@RequestMapping("/test")public String test(Model model){        List students = studentService.selectStudent();        model.addAttribute("students", students);return "test";    }@RequestMapping("/getOne")public String getOne(Model model){       // 获取id为1的Student对象到test.jsp        Student student = studentService.selectStudentByPrimaryKey(1);        model.addAttribute("student", student);return "test";    }}

?使用的restful风格,返回的jsp页面,/test和/getOne用来验证缓存是否生效。

小贴一下jsp:

listStudent.jsp

students    增加:    name: 
idnameage编辑删除${each.id}${each.name}${each.age}修改删除验证你的jquer是否生效 $(function(){ $(".deleteStudent").click(function(){var href = $(this).attr("value"); alert(href); $("#deleteType").attr("action", href).submit(); }) $(".hhh").click(function(){ alert("你的jquer已生效"); }) })

editStudent.jsp

editStudent    name:    age :返回主页

test.jsp

test
${each.id}, ${each.name}, ${each.age}
得到一个Student${student.id}, ${student.name}, ${student.age}

 

四,验证测试:

?步骤:

1,/getOne

由于StudentServiceImpl.java中的System.out.println("从数据库中取一个selectStudentByPrimaryKey"); 查看后台控制台,可以知道这条数据是从数据库中获取的。

/getOne获取的Student的id为1,所以会在Redis Desktop Manager中看到一条singleStudent1的缓存记录。

http://localhost:8080/getOne

5dcb7798a1ecfe2b55a50e77ba723885.png

2,更改Redis Desktop Manager中的记录

?比如redis库中原来的数据是

91413db1d0bc19bd1c7dfcbd0116a1e1.png

?更改数据,因为这里改的数据是redis的,mysql里的数据还是没变,这样就知道了是从缓存中读取的数据

cff9fabe29e05f2d7975dde42a6f51ae.png

?点击save之后,刷新http://localhost:8080/getOne

a8cd222c15f68fa0364b16091cf9e18c.png

 成功!????? 然后@CacheEvict是一样的逻辑,指定失效的key就好了

在看不好意思,那就点个赞吧

2431e23c89e774db9ad83117595572bf.gif

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

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

相关文章

takePic and Videos

2019独角兽企业重金招聘Python工程师标准>>> //// ViewController.m// UIImagePickerController// Created by Kenshin Cui on 14/04/05.// Copyright (c) 2014年 cmjstudio. All rights reserved.//AVFoundation.framework//MediaPlayer.framework//MobileCore…

uap--studio设置文本字体

转载于:https://www.cnblogs.com/zzzzw/p/4920460.html

可变悬挂调节软硬_【5040地推合作品牌】荷兰高性能减震器及悬挂系统品牌—KONI...

GT Show“5040计划”&#xff0c;深入全国各地省市地区&#xff0c;全方位覆盖全国改装门店、一二类维修厂、五大车型(奥迪、宝马、奔驰、保时捷、雷克萨斯)原厂升级店、高端综合店&#xff0c;深挖长三角六大城市后市场门店。GT Show不仅关注传统改装门店&#xff0c;而且全方…

【Alpha 冲刺】 2/12

今日任务总结 人员今日原定任务完成情况遇到问题贡献值胡武成完成API文档编写由于外出比赛&#xff0c;故推迟无0孙浩楷1.完成VUE框架搭建 2.寻找在线编辑图片插件已完成WEB在线编辑图片插件加载速度慢&#xff0c;需要再想办法解决2 0.5胡冰完成MVP框架搭建已完成由于之前有做…

钻井缸套排量_中国石化顺北特深层及川渝页岩气钻完井关键技术集成:碳酸盐岩酸压技术、优快钻井技术、页岩气强化体积改造技术、高温高压窄间隙固井技术...

点击蓝字关注“油媒方”近年来&#xff0c;中国石化围绕顺北、川渝等重点探区&#xff0c;通过技术攻关与现场实践&#xff0c;初步形成了顺北8000&#xff5e;9000m特深层钻井完井关键技术、川渝页岩气钻井完井关键技术&#xff0c;支撑了中国石化在特深层油气、非常规油气资源…

爬虫如何监听插件_Go 爬虫之 colly 从入门到不放弃指南

Go语言中文网&#xff0c;致力于每日分享编码、开源等知识&#xff0c;欢迎关注我&#xff0c;会有意想不到的收获&#xff01;最近发现知乎上感兴趣的问题越来越少&#xff0c;于是准备聚合下其他平台技术问答&#xff0c;比如 segmentfault、stackoverflow 等。要完成这个工作…

多款优秀的 JS MVC 框架对比

2019独角兽企业重金招聘Python工程师标准>>> 正如之前说的&#xff0c;产品生产有功能时代转入体验时代&#xff0c;产品为王&#xff0c;体验为王&#xff0c;已经是时代趋势。体验经济的到来&#xff0c;说明前端的技术要求越来越高&#xff0c;完成功能是不行的&…

在WordPress文章中插入表格的四种方法,史上最全

https://boke112.com/4553.html/all td, tr {border: 1px solid #000000;text-align: center;padding: 10px;} 在做 WordPress 网站的时候&#xff0c;很多时候文章中都会用到 table 表格&#xff0c;今天就来总结分享四种在WordPress 文章中插入 table 表格的方法。 一、最简…

(转)在Eclipse中用TODO标签管理任务(Task)

背景&#xff1a;eclipse是一款功能十分强大的编辑&#xff0c;如果能够熟练运用&#xff0c;必定事半功倍&#xff0c;但如果不求甚解&#xff0c;无疑是给自己制造麻烦。 1 标签的使用 1.1 起因 如上图所示&#xff0c;在程序中有很多todo的标签出现&#xff0c;但是却不知道…

制作启动U盘与定制多系统启动

制作启动U盘与定制多系统启动 说明&#xff1a;本文将讲述有关bootmgr引导启动与grub引导启动制作的相关经验&#xff0c;文中提到的知识谈不上完全正确&#xff0c;只是一些个人在制作U盘启动获得的心得&#xff0c;但我会尽力正确的解释清楚。 制作启动U盘 所需工具&#xf…

wordpress footer置底

/* 通过calc()函数让内容区块自动伸缩 */ .my-body{min-height: calc(71.7vh - 80px); } footer{height:50px; } 参考&#xff1a;https://www.jianshu.com/p/6efe2c76a2dd 当我们要设置网页中的footer置底&#xff08;sticky footer&#xff09;&#xff0c;我们可以这样办 …

电脑公司 GHOST WIN10 X64 装机专业版 V2018.04(64位)

http://www.xitongzhijia.net/win10/201804/123923.html 系统简介 电脑公司 GHOST WIN10 X64 装机专业版 V2018.04 系统维护和美化工具&#xff0c;常用软件一站到位&#xff0c;自带安全软件&#xff0c;自动屏蔽木马病毒阻止病毒运行&#xff0c;阻挡填出IE插件&#xff0c;G…

浅谈JavaScript中闭包

引言 闭包可以说是JavaScript中最有特色的一个地方&#xff0c;很好的理解闭包是更深层次的学习JavaScript的基础。这篇文章我们就来简单的谈下JavaScript下的闭包。 闭包是什么&#xff1f; 闭包是什么&#xff1f;通俗的解释是&#xff1a;有权访问另一个函数作用域中变量的函…

WordPress 查询数据库 操作数据库

https://www.168seo.cn/jianzhan/wordpress/advance-wordpress-tutorial/24692.html 插件位置 需要注意的是&#xff0c;由于在WordPress中可以配置wp-content/plugins/目录的位置&#xff0c;所以你必须使用plugin_dir_path()和plugins_url()两个函数来获取插件的路径。 Wor…

std string与线程安全_C++标准库多线程简介Part1

Part1:线程与互斥量本篇文章将简单的介绍一下C的标准线程库&#xff0c;本篇内容十分基础&#xff0c;如果你有C多线程相关的使用经验或者知识&#xff0c;就不必在这篇文章上浪费时间了...如果你认为本篇文章对你有帮助&#xff0c;请点赞&#xff01;&#xff01;&#xff01…

secilog 1.17 发布 增加了英文版本等新功能

2019独角兽企业重金招聘Python工程师标准>>> 日志分析软件 secilog 1.17发布&#xff0c;增加了英文版本&#xff0c;对日志导入增加了日志机器ip和日志机器名&#xff0c;或者日志ip和日志域名的关系。上篇文章1.16&#xff0c;有兴趣可以了解一下。本次升级主要增…

用clipboard.js实现纯JS复制文本到剪切板

以前很多人都是用ZeroClipboard.js来实现网页复制内容&#xff0c;火端也是用它。ZeroClipboard是利用flash来实现的&#xff0c;ZeroClipboard兼容性很好&#xff0c;但是由于现在越来越多的浏览器不支持flash&#xff0c;导致一些没法正常使用了。 今天火端开始使用clipboard…

vbs获取程序窗体句柄_PyQt5 GUI程序的基本框架

本节先通过一个简单的示例程序介绍PyQt5 GUI应用程序的基本框架。启动Python自带的编程和交互式环境IDLE&#xff0c;点击“File”→“New File”菜单项&#xff0c;打开一个文件编辑窗口&#xff0c;在此窗口中输入下面的程序&#xff0c;并保存为文件demo2_1Hello.py&#xf…

【学神】1-4 用户及用户组管理

用户及用户组管理本节所述内容&#xff1a;用户和组的相关配置文件管理用户和组 进入单用户模式找回root身份一、用户和组的相关配置文件1.用户的分类&#xff08;1&#xff09;根据帐号的位置&#xff1a;本地帐号、远程&#xff08;域&#xff09;帐号、LDAP&…

阿里REDIS优化

转载于:https://www.cnblogs.com/isoftware/p/3745956.html