開啟遠程訪問:
找到redis中的redis.conf文件并編輯(在安裝路徑中找到)
vim?./redis.conf
1、找到bind 127.0.0.1并注釋掉
默認127.0.0.1只能本地訪問,注釋掉即可ip訪問
2、修改 protected-mode 屬性值為no
注釋掉并把保護模式禁用以后可以IP訪問
3、修改daemonize屬性將no 改為yes
將daemonize設置為yes即啟動后臺運行
4、開放6379端口
/sbin/iptables?-I?INPUT?-p?tcp?--dport?6379?-j?ACCEPT
默認不對外開放6379
5、啟動redis
redis-server?/myconf/redis.conf
redis-server默認在/usr/local/bin路徑下,redis.conf在redis的安裝路徑下
6、測試連接
redis-cli?-h?192.168.126.129?-p?6379
redis-cli -h redis服務器IP -p 6379 -a 密碼(沒有設置redis密碼不要寫空,否則報錯)
Java代碼編寫:
項目源碼結構
一個user表
代碼:
pom.xml文件(可以根據自己的需要來添加或修改)
<dependencies> ????????<dependency> ????????????<groupid>org.springframework.boot</groupid> ????????????<artifactid>spring-boot-starter-web</artifactid> ????????</dependency> ????????<!-- mybatis 與 spring boot 2.x的整合包 --> ????????<dependency> ????????????<groupid>org.mybatis.spring.boot</groupid> ????????????<artifactid>mybatis-spring-boot-starter</artifactid> ????????????<version>1.3.2</version> ????????</dependency> ????????<!--mysql JDBC驅動 --> ????????<dependency> ????????????<groupid>mysql</groupid> ????????????<artifactid>mysql-connector-java</artifactid> ????????????<version>5.1.39</version> ????????</dependency> ????????<dependency> ????????????<groupid>org.springframework.boot</groupid> ????????????<artifactid>spring-boot-starter-test</artifactid> ????????????<scope>test</scope> ????????</dependency> ????????<dependency> ????????????<groupid>org.springframework.boot</groupid> ????????????<artifactid>spring-boot-starter-data-redis</artifactid> ????????</dependency> ????????<dependency> ????????????<groupid>org.springframework.boot</groupid> ????????????<artifactid>spring-boot-starter-cache</artifactid> ????????</dependency> ????</dependencies>
下面是springboot的配置文件application.yml,配置redis(里面都有注釋解釋)
server: ??port:?8081 ? #數據庫連接 spring: ??datasource: ????url:?jdbc:mysql://localhost:3306/mytest_springboot_cache?useUnicode=true ????driver-class-name:?com.mysql.jdbc.Driver ????username:?root ????password:?lzh ? ??##?Redis?配置 ??redis: ????##?Redis數據庫索引(默認為0) ????database:?0 ????##?Redis服務器地址 ????host:?192.168.126.129 ????##?Redis服務器連接端口 ????port:?6379 ????##?Redis服務器連接密碼(默認為空) ????password: ????jedis: ??????pool: ????????##?連接池最大連接數(使用負值表示沒有限制) ????????#spring.redis.pool.max-active=8 ????????max-active:?8 ????????##?連接池最大阻塞等待時間(使用負值表示沒有限制) ????????#spring.redis.pool.max-wait=-1 ????????max-wait:?-1 ????????##?連接池中的最大空閑連接 ????????#spring.redis.pool.max-idle=8 ????????max-idle:?8 ????????##?連接池中的最小空閑連接 ????????#spring.redis.pool.min-idle=0 ????????min-idle:?0 ????##?連接超時時間(毫秒) ????timeout:?1200 ? ??#將themilef的默認緩存禁用,熱加載生效 ??thymeleaf: ????cache:?false ? ??#mybatis的下劃線轉駝峰配置 ??configuration: ????map-underscore-to-camel-case:?true ? ????#另外一種打印語句的方式 ????log-impl:?org.apache.ibatis.logging.stdout.StdOutImpl ? #打印sql時的語句 logging: ??level: ????com: ??????acong: ????????dao:?debug ??file:?d:/logs/bsbdj.log
接著是實體類,這個比較簡單就不多說了
package?com.lzh.springbootstudytest.bean; ? import?java.io.Serializable; ? /** ?*?@author?lzh ?*?create?2019-09-18-22:32 ?*/ public?class?User?implements?Serializable?{ ? ????private?static?final?long?serialVersionUID?=?1L; ????private?int?uid; ????private?String?userName; ????private?String?passWord; ????private?int?salary; ????public?int?getUid()?{ ????????return?uid; ????} ????public?void?setUid(int?uid)?{ ????????this.uid?=?uid; ????} ????public?String?getUserName()?{ ????????return?userName; ????} ????public?void?setUserName(String?userName)?{ ????????this.userName?=?userName; ????} ????public?String?getPassWord()?{ ????????return?passWord; ????} ????public?void?setPassWord(String?passWord)?{ ????????this.passWord?=?passWord; ????} ????public?int?getSalary()?{ ????????return?salary; ????} ????public?void?setSalary(int?salary)?{ ????????this.salary?=?salary; ????} ????public?User(int?uid,?String?userName,?String?passWord,?int?salary)?{ ????????super(); ????????this.uid?=?uid; ????????this.userName?=?userName; ????????this.passWord?=?passWord; ????????this.salary?=?salary; ????} ????public?User()?{ ????????super(); ????} }
?這是controller類,用于暴露接口訪問
package?com.lzh.springbootstudytest.controller; ? import?com.lzh.springbootstudytest.bean.User; import?com.lzh.springbootstudytest.service.UserService; import?org.springframework.beans.factory.annotation.Autowired; import?org.springframework.stereotype.Controller; import?org.springframework.web.bind.annotation.RequestMapping; import?org.springframework.web.bind.annotation.RequestParam; import?org.springframework.web.bind.annotation.ResponseBody; import?org.springframework.web.bind.annotation.RestController; ? import?java.util.HashMap; import?java.util.List; import?java.util.Map; ? /** ?*?@author?lzh ?*?create?2019-09-18-22:36 ?*/ @RestController public?class?TestController?{ ? ????@Autowired ????private?UserService?userService; ? ????@RequestMapping("/queryAll") ????public?List<user>?queryAll(){ ????????List<user>?lists?=?userService.queryAll(); ????????return?lists; ????} ? ????@RequestMapping("/findUserById") ????public?Map<string>?findUserById(@RequestParam?int?id){ ????????User?user?=?userService.findUserById(id); ????????Map<string>?result?=?new?HashMap(); ????????result.put("uid",?user.getUid()); ????????result.put("uname",?user.getUserName()); ????????result.put("pass",?user.getPassWord()); ????????result.put("salary",?user.getSalary()); ????????return?result; ????} ? ????@RequestMapping("/updateUser") ????public?String?updateUser(){ ????????User?user?=?new?User(); ????????user.setUid(1); ????????user.setUserName("cat"); ????????user.setPassWord("miaomiao"); ????????user.setSalary(4000); ? ????????int?result?=?userService.updateUser(user); ? ????????if(result?!=?0){ ????????????return?"update?user?success"; ????????} ? ????????return?"fail"; ????} ? ????@RequestMapping("/deleteUserById") ????public?String?deleteUserById(@RequestParam?int?id){ ????????int?result?=?userService.deleteUserById(id); ????????if(result?!=?0){ ????????????return?"delete?success"; ????????} ????????return?"delete?fail"; ????} }</string></string></user></user>
配置redistemplate序列化
package?com.lzh.springbootstudytest.config; ? import?com.fasterxml.jackson.annotation.JsonAutoDetect; import?com.fasterxml.jackson.annotation.PropertyAccessor; import?com.fasterxml.jackson.databind.ObjectMapper; import?org.springframework.cache.CacheManager; 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.cache.RedisCacheWriter; import?org.springframework.data.redis.connection.RedisConnectionFactory; import?org.springframework.data.redis.core.*; import?org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import?org.springframework.data.redis.serializer.StringRedisSerializer; ? import?java.time.Duration; ? /** ?*?@author?lzh ?*?create?2019-09-24-15:07 ?*/ @Configuration @EnableCaching public?class?RedisConfig?extends?CachingConfigurerSupport?{ ? ????/** ?????*?選擇redis作為默認緩存工具 ?????*?@param?redisConnectionFactory ?????*?@return ?????*/ ????/*@Bean ????//springboot?1.xx ????public?CacheManager?cacheManager(RedisTemplate?redisTemplate)?{ ????????RedisCacheManager?rcm?=?new?RedisCacheManager(redisTemplate); ????????return?rcm; ????}*/ ????@Bean ????public?CacheManager?cacheManager(RedisConnectionFactory?redisConnectionFactory)?{ ????????RedisCacheConfiguration?redisCacheConfiguration?=?RedisCacheConfiguration.defaultCacheConfig() ????????????????.entryTtl(Duration.ofHours(1));?//?設置緩存有效期一小時 ????????return?RedisCacheManager ????????????????.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)) ????????????????.cacheDefaults(redisCacheConfiguration).build(); ????} ? ????/** ?????*?retemplate相關配置 ?????*?@param?factory ?????*?@return ?????*/ ????@Bean ????public?RedisTemplate<string>?redisTemplate(RedisConnectionFactory?factory)?{ ? ????????RedisTemplate<string>?template?=?new?RedisTemplate(); ????????//?配置連接工廠 ????????template.setConnectionFactory(factory); ? ????????//使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值(默認使用JDK的序列化方式) ????????Jackson2JsonRedisSerializer?jacksonSeial?=?new?Jackson2JsonRedisSerializer(Object.class); ? ????????ObjectMapper?om?=?new?ObjectMapper(); ????????//?指定要序列化的域,field,get和set,以及修飾符范圍,ANY是都有包括private和public ????????om.setVisibility(PropertyAccessor.ALL,?JsonAutoDetect.Visibility.ANY); ????????//?指定序列化輸入的類型,類必須是非final修飾的,final修飾的類,比如String,Integer等會跑出異常 ????????om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); ????????jacksonSeial.setObjectMapper(om); ? ????????//?值采用json序列化 ????????template.setValueSerializer(jacksonSeial); ????????//使用StringRedisSerializer來序列化和反序列化redis的key值 ????????template.setKeySerializer(new?StringRedisSerializer()); ? ????????//?設置hash?key?和value序列化模式 ????????template.setHashKeySerializer(new?StringRedisSerializer()); ????????template.setHashValueSerializer(jacksonSeial); ????????template.afterPropertiesSet(); ? ????????return?template; ????} ? ????/** ?????*?對hash類型的數據操作 ?????* ?????*?@param?redisTemplate ?????*?@return ?????*/ ????@Bean ????public?HashOperations<string>?hashOperations(RedisTemplate<string>?redisTemplate)?{ ????????return?redisTemplate.opsForHash(); ????} ? ????/** ?????*?對redis字符串類型數據操作 ?????* ?????*?@param?redisTemplate ?????*?@return ?????*/ ????@Bean ????public?ValueOperations<string>?valueOperations(RedisTemplate<string>?redisTemplate)?{ ????????return?redisTemplate.opsForValue(); ????} ? ????/** ?????*?對鏈表類型的數據操作 ?????* ?????*?@param?redisTemplate ?????*?@return ?????*/ ????@Bean ????public?ListOperations<string>?listOperations(RedisTemplate<string>?redisTemplate)?{ ????????return?redisTemplate.opsForList(); ????} ? ????/** ?????*?對無序集合類型的數據操作 ?????* ?????*?@param?redisTemplate ?????*?@return ?????*/ ????@Bean ????public?SetOperations<string>?setOperations(RedisTemplate<string>?redisTemplate)?{ ????????return?redisTemplate.opsForSet(); ????} ? ????/** ?????*?對有序集合類型的數據操作 ?????* ?????*?@param?redisTemplate ?????*?@return ?????*/ ????@Bean ????public?ZSetOperations<string>?zSetOperations(RedisTemplate<string>?redisTemplate)?{ ????????return?redisTemplate.opsForZSet(); ????} }</string></string></string></string></string></string></string></string></string></string></string></string>
接著是Mapper持久層Dao,這里主要用注解寫比較方便,也可以使用mybatis的xml配置文件寫sql語句
package?com.lzh.springbootstudytest.mapper; ? import?com.lzh.springbootstudytest.bean.User; import?org.apache.ibatis.annotations.*; ? import?java.util.List; ? /** ?*?@author?lzh ?*?create?2019-09-18-22:32 ?*/ @Mapper public?interface?UserDao?{ ? ????@Select("select?*?from?user") ????List<user>?queryAll(); ? ????@Select("select?*?from?user?where?uid?=?#{id}") ????User?findUserById(int?id); ? ????@Update("UPDATE?USER?SET?username?=?CASE?WHEN?(#{userName}?!=?NULL)?AND?(#{userName}?!=?'')?THEN?#{userName},PASSWORD?=?CASE?WHEN?(#{passWord}?!=?NULL)?AND?(#{passWord}?!=?'')?THEN?#{passWord},salary?=?CASE?WHEN?(#{salary}?!=?0)?THEN?#{salary}?WHERE?uid?=?#{uid}") ????int?updateUser(@Param("user")?User?user); ? ????@Delete("delete?from?user?where?uid?=?#{id}") ????int?deleteUserById(int?id); ? }</user>
service層,這里主要是使用redis模板來寫
package?com.lzh.springbootstudytest.service; ? import?com.lzh.springbootstudytest.bean.User; import?com.lzh.springbootstudytest.mapper.UserDao; import?org.springframework.beans.factory.annotation.Autowired; import?org.springframework.data.redis.core.RedisTemplate; import?org.springframework.data.redis.core.ValueOperations; import?org.springframework.stereotype.Service; ? import?java.util.List; import?java.util.concurrent.TimeUnit; ? /** ?*?@author?lzh ?*?create?2019-09-18-22:33 ?*/ @Service public?class?UserService?{ ? ????@Autowired ????private?UserDao?userDao; ? ????@Autowired ????private?RedisTemplate?redisTemplate; ? ????public?List<user>?queryAll()?{ ????????return?userDao.queryAll(); ????} ? ????/** ?????*?獲取用戶策略:先從緩存中獲取用戶,沒有則取數據表中?數據,再將數據寫入緩存 ?????*/ ????public?User?findUserById(int?id)?{ ????????String?key?=?"user_"?+?id; ? ????????ValueOperations<string>?operations?=?redisTemplate.opsForValue(); ? ????????//判斷redis中是否有鍵為key的緩存 ????????boolean?hasKey?=?redisTemplate.hasKey(key); ? ????????if?(hasKey)?{ ????????????User?user?=?operations.get(key); ????????????System.out.println("從緩存中獲得數據:"+user.getUserName()); ????????????System.out.println("------------------------------------"); ????????????return?user; ????????}?else?{ ????????????User?user?=?userDao.findUserById(id); ????????????System.out.println("查詢數據庫獲得數據:"+user.getUserName()); ????????????System.out.println("------------------------------------"); ? ????????????//?寫入緩存 ????????????operations.set(key,?user,?5,?TimeUnit.HOURS); ????????????return?user; ????????} ????} ? ????/** ?????*?更新用戶策略:先更新數據表,成功之后,刪除原來的緩存,再更新緩存 ?????*/ ????public?int?updateUser(User?user)?{ ????????ValueOperations<string>?operations?=?redisTemplate.opsForValue(); ????????int?result?=?userDao.updateUser(user); ????????if?(result?!=?0)?{ ????????????String?key?=?"user_"?+?user.getUid(); ????????????boolean?haskey?=?redisTemplate.hasKey(key); ????????????if?(haskey)?{ ????????????????redisTemplate.delete(key); ????????????????System.out.println("刪除緩存中的key----------->?"?+?key); ????????????} ????????????//?再將更新后的數據加入緩存 ????????????User?userNew?=?userDao.findUserById(user.getUid()); ????????????if?(userNew?!=?null)?{ ????????????????operations.set(key,?userNew,?3,?TimeUnit.HOURS); ????????????} ????????} ????????return?result; ????} ? ????/** ?????*?刪除用戶策略:刪除數據表中數據,然后刪除緩存 ?????*/ ????public?int?deleteUserById(int?id)?{ ????????int?result?=?userDao.deleteUserById(id); ????????String?key?=?"user_"?+?id; ????????if?(result?!=?0)?{ ????????????boolean?hasKey?=?redisTemplate.hasKey(key); ????????????if?(hasKey)?{ ????????????????redisTemplate.delete(key); ????????????????System.out.println("刪除了緩存中的key:"?+?key); ????????????} ????????} ????????return?result; ????} ? } </string></string></user>
這里主要是使用RedisTemplate來對遠程redis操作,每次訪問controller暴露的接口,首先判斷redis緩存中是否存在該數據,若不存在就從數據庫中讀取數據,然后保存到redis緩存中,當下次訪問的時候,就直接從緩存中取出來。
這樣就不用每次都執行sql語句,能夠提高訪問速度。 但是在保存數據到緩存中,通過設置鍵和值和超時刪除,注意設置超時刪除緩存時間不要太長,否則會給服務器帶來壓力。
執行spring boot的啟動類,訪問http://localhost:8081/findUserById?id=1
再次訪問http://localhost:8081/findUserById?id=1就是從緩存中獲取保存的數據
更多redis知識請關注入redis門教程欄目。