经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Redis » 查看文章
Linux服务器使用Redis作为数据缓存,并用log4j2进行日志记录
来源:cnblogs  作者:HuskySir  时间:2023/9/20 9:28:18  对本文有异议

前言

个人网站使用Vue作为前端,SpringBoot作为后端,MySQL作为数据库,但前端每次请求都会从MySQL数据库中读取数据,而MySQL数据库的数据是存储于服务器磁盘中,所以响应速度有一定影响。之前了解过一点Redis数据库,该数据库数据存储于内存中(也可以持久化于磁盘中),数据读取速度就会比存储于磁盘中的MySQL快很多,故想把Redis数据库应用于该网站项目中。

一、安装Redis

Linux系统安装Redis比较简单,可以直接通过命令行安装,安装过程比较简单,在此就不赘述,下列出一些常用命令

  1. # 更新apt
  2. sudo apt update
  3. # 安装Redis
  4. sudo apt-get install redis-server
  5. # 设置密码(在配置文件redis.conf中,位置在 /etc/redis/redis.conf)
  6. requirepass ******
  7. # 启动Redis服务
  8. service redis-server start
  9. # 停止Redis服务
  10. service redis-server stop
  11. # 重启Redis服务
  12. service redis-server restart
  13. # 启动Redis客户端
  14. redis-cli
  15. # 测试Redis是否连接
  16. 127.0.0.1:6379> ping

注意:需要修改Redis配置文件中的保护模式“protected-mode"为修改为no,否则会出现无法连接的情况

  1. # 修改保护模式为no
  2. # protected-mode yes
  3. protected-mode no
  4. # 若不修改可能无法连接Redis,出现以下错误
  5. org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 127.0.0.1:6379
  6. at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1689)
  7. at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1597)
  8. ······
  9. ······
  10. ······
  11. Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to 127.0.0.1:6379
  12. at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:78)
  13. at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:56)
  14. ······
  15. ······
  16. ······
  17. Caused by: java.lang.IllegalStateException: RedisHandshakeHandler not registered
  18. at io.lettuce.core.AbstractRedisClient.lambda$initializeChannelAsync0$6(AbstractRedisClient.java:431)
  19. at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:590)
  20. ······
  21. ······
  22. ······

二、SpringBoot项目集成Redis

1、pom.xml添加依赖

  1. <!-- Redis -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-data-redis</artifactId>
  5. </dependency>

2、Redis数据库连接配置 application.yml

  1. # Redis
  2. redis:
  3. # 服务器地址
  4. host: 127.0.0.1
  5. # 服务器端口号
  6. port: 6379
  7. # 使用的数据库索引
  8. database: 0
  9. # 连接超时时间
  10. timeout: 10000
  11. # 设置密码
  12. password: ******
  13. lettuce:
  14. # 连接池
  15. pool:
  16. # 最大阻塞等待时间,负数表示没有限制
  17. max-wait: -1
  18. # 连接池中最大空闲
  19. max-idle: 5
  20. # 连接池中最小空闲
  21. min-idle: 0
  22. # 连接池最大连接数
  23. max-active: 20

3、Redis配置类RedisConfig

  1. package cn.huskysir.Config;
  2. import com.fasterxml.jackson.annotation.JsonAutoDetect;
  3. import com.fasterxml.jackson.annotation.PropertyAccessor;
  4. import com.fasterxml.jackson.databind.ObjectMapper;
  5. import org.springframework.cache.annotation.CachingConfigurerSupport;
  6. import org.springframework.cache.annotation.EnableCaching;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.data.redis.connection.RedisConnectionFactory;
  10. import org.springframework.data.redis.core.*;
  11. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
  12. import org.springframework.data.redis.serializer.StringRedisSerializer;
  13. @Configuration
  14. @EnableCaching //开启注解
  15. public class RedisConfig extends CachingConfigurerSupport {
  16. /**
  17. * retemplate相关配置
  18. */
  19. @Bean
  20. public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
  21. RedisTemplate<String, Object> template = new RedisTemplate<>();
  22. // 配置连接工厂
  23. template.setConnectionFactory(factory);
  24. //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
  25. Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
  26. ObjectMapper om = new ObjectMapper();
  27. // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
  28. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  29. // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
  30. om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  31. jacksonSeial.setObjectMapper(om);
  32. // 值采用json序列化
  33. template.setValueSerializer(jacksonSeial);
  34. //使用StringRedisSerializer来序列化和反序列化redis的key值
  35. template.setKeySerializer(new StringRedisSerializer());
  36. // 设置hash key 和value序列化模式
  37. template.setHashKeySerializer(new StringRedisSerializer());
  38. template.setHashValueSerializer(jacksonSeial);
  39. template.afterPropertiesSet();
  40. return template;
  41. }
  42. /**
  43. * 对hash类型的数据操作
  44. */
  45. @Bean
  46. public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
  47. return redisTemplate.opsForHash();
  48. }
  49. /**
  50. * 对redis字符串类型数据操作
  51. */
  52. @Bean
  53. public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
  54. return redisTemplate.opsForValue();
  55. }
  56. /**
  57. * 对链表类型的数据操作
  58. */
  59. @Bean
  60. public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
  61. return redisTemplate.opsForList();
  62. }
  63. /**
  64. * 对无序集合类型的数据操作
  65. */
  66. @Bean
  67. public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
  68. return redisTemplate.opsForSet();
  69. }
  70. /**
  71. * 对有序集合类型的数据操作
  72. */
  73. @Bean
  74. public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
  75. return redisTemplate.opsForZSet();
  76. }
  77. }

4、Redis工具类RedisUtil

  1. package cn.huskysir.Utils;
  2. import org.springframework.data.redis.core.RedisTemplate;
  3. import org.springframework.stereotype.Component;
  4. import org.springframework.util.CollectionUtils;
  5. import javax.annotation.Resource;
  6. import java.util.Collection;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.Set;
  10. import java.util.concurrent.TimeUnit;
  11. @Component
  12. public class RedisUtil {
  13. @Resource
  14. private RedisTemplate<String, Object> redisTemplate;
  15. public RedisUtil(RedisTemplate<String, Object> redisTemplate) {
  16. this.redisTemplate = redisTemplate;
  17. }
  18. /**
  19. * 指定缓存失效时间
  20. *
  21. * @param key 键
  22. * @param time 时间(秒)
  23. * @return
  24. */
  25. public boolean expire(String key, long time) {
  26. try {
  27. if (time > 0) {
  28. redisTemplate.expire(key, time, TimeUnit.SECONDS);
  29. }
  30. return true;
  31. } catch (Exception e) {
  32. e.printStackTrace();
  33. return false;
  34. }
  35. }
  36. /**
  37. * 根据key 获取过期时间
  38. *
  39. * @param key 键 不能为null
  40. * @return 时间(秒) 返回0代表为永久有效
  41. */
  42. public long getExpire(String key) {
  43. return redisTemplate.getExpire(key, TimeUnit.SECONDS);
  44. }
  45. /**
  46. * 判断key是否存在
  47. *
  48. * @param key 键
  49. * @return true 存在 false不存在
  50. */
  51. public boolean hasKey(String key) {
  52. try {
  53. return redisTemplate.hasKey(key);
  54. } catch (Exception e) {
  55. e.printStackTrace();
  56. return false;
  57. }
  58. }
  59. /**
  60. * 删除缓存
  61. *
  62. * @param key 可以传一个值 或多个
  63. */
  64. @SuppressWarnings("unchecked")
  65. public void del(String... key) {
  66. if (key != null && key.length > 0) {
  67. if (key.length == 1) {
  68. redisTemplate.delete(key[0]);
  69. } else {
  70. redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
  71. }
  72. }
  73. }
  74. //============================String=============================
  75. /**
  76. * 普通缓存获取
  77. *
  78. * @param key 键
  79. * @return 值
  80. */
  81. public Object get(String key) {
  82. return key == null ? null : redisTemplate.opsForValue().get(key);
  83. }
  84. /**
  85. * 普通缓存放入
  86. *
  87. * @param key 键
  88. * @param value 值
  89. * @return true成功 false失败
  90. */
  91. public boolean set(String key, Object value) {
  92. try {
  93. redisTemplate.opsForValue().set(key, value);
  94. return true;
  95. } catch (Exception e) {
  96. e.printStackTrace();
  97. return false;
  98. }
  99. }
  100. /**
  101. * 普通缓存放入并设置时间
  102. *
  103. * @param key 键
  104. * @param value 值
  105. * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
  106. * @return true成功 false 失败
  107. */
  108. public boolean set(String key, Object value, long time) {
  109. try {
  110. if (time > 0) {
  111. redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
  112. } else {
  113. set(key, value);
  114. }
  115. return true;
  116. } catch (Exception e) {
  117. e.printStackTrace();
  118. return false;
  119. }
  120. }
  121. /**
  122. * 递增
  123. *
  124. * @param key 键
  125. * @param delta 要增加几(大于0)
  126. * @return
  127. */
  128. public long incr(String key, long delta) {
  129. if (delta < 0) {
  130. throw new RuntimeException("递增因子必须大于0");
  131. }
  132. return redisTemplate.opsForValue().increment(key, delta);
  133. }
  134. /**
  135. * 递减
  136. *
  137. * @param key 键
  138. * @param delta 要减少几(小于0)
  139. * @return
  140. */
  141. public long decr(String key, long delta) {
  142. if (delta < 0) {
  143. throw new RuntimeException("递减因子必须大于0");
  144. }
  145. return redisTemplate.opsForValue().increment(key, -delta);
  146. }
  147. //================================Map=================================
  148. /**
  149. * HashGet
  150. *
  151. * @param key 键 不能为null
  152. * @param item 项 不能为null
  153. * @return 值
  154. */
  155. public Object hget(String key, String item) {
  156. return redisTemplate.opsForHash().get(key, item);
  157. }
  158. /**
  159. * 获取hashKey对应的所有键值
  160. *
  161. * @param key 键
  162. * @return 对应的多个键值
  163. */
  164. public Map<Object, Object> hmget(String key) {
  165. return redisTemplate.opsForHash().entries(key);
  166. }
  167. /**
  168. * HashSet
  169. *
  170. * @param key 键
  171. * @param map 对应多个键值
  172. * @return true 成功 false 失败
  173. */
  174. public boolean hmset(String key, Map<String, Object> map) {
  175. try {
  176. redisTemplate.opsForHash().putAll(key, map);
  177. return true;
  178. } catch (Exception e) {
  179. e.printStackTrace();
  180. return false;
  181. }
  182. }
  183. /**
  184. * HashSet 并设置时间
  185. *
  186. * @param key 键
  187. * @param map 对应多个键值
  188. * @param time 时间(秒)
  189. * @return true成功 false失败
  190. */
  191. public boolean hmset(String key, Map<String, Object> map, long time) {
  192. try {
  193. redisTemplate.opsForHash().putAll(key, map);
  194. if (time > 0) {
  195. expire(key, time);
  196. }
  197. return true;
  198. } catch (Exception e) {
  199. e.printStackTrace();
  200. return false;
  201. }
  202. }
  203. /**
  204. * 向一张hash表中放入数据,如果不存在将创建
  205. *
  206. * @param key 键
  207. * @param item 项
  208. * @param value 值
  209. * @return true 成功 false失败
  210. */
  211. public boolean hset(String key, String item, Object value) {
  212. try {
  213. redisTemplate.opsForHash().put(key, item, value);
  214. return true;
  215. } catch (Exception e) {
  216. e.printStackTrace();
  217. return false;
  218. }
  219. }
  220. /**
  221. * 向一张hash表中放入数据,如果不存在将创建
  222. *
  223. * @param key 键
  224. * @param item 项
  225. * @param value 值
  226. * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
  227. * @return true 成功 false失败
  228. */
  229. public boolean hset(String key, String item, Object value, long time) {
  230. try {
  231. redisTemplate.opsForHash().put(key, item, value);
  232. if (time > 0) {
  233. expire(key, time);
  234. }
  235. return true;
  236. } catch (Exception e) {
  237. e.printStackTrace();
  238. return false;
  239. }
  240. }
  241. /**
  242. * 删除hash表中的值
  243. *
  244. * @param key 键 不能为null
  245. * @param item 项 可以使多个 不能为null
  246. */
  247. public void hdel(String key, Object... item) {
  248. redisTemplate.opsForHash().delete(key, item);
  249. }
  250. /**
  251. * 判断hash表中是否有该项的值
  252. *
  253. * @param key 键 不能为null
  254. * @param item 项 不能为null
  255. * @return true 存在 false不存在
  256. */
  257. public boolean hHasKey(String key, String item) {
  258. return redisTemplate.opsForHash().hasKey(key, item);
  259. }
  260. /**
  261. * hash递增 如果不存在,就会创建一个 并把新增后的值返回
  262. *
  263. * @param key 键
  264. * @param item 项
  265. * @param by 要增加几(大于0)
  266. * @return
  267. */
  268. public double hincr(String key, String item, double by) {
  269. return redisTemplate.opsForHash().increment(key, item, by);
  270. }
  271. /**
  272. * hash递减
  273. *
  274. * @param key 键
  275. * @param item 项
  276. * @param by 要减少记(小于0)
  277. * @return
  278. */
  279. public double hdecr(String key, String item, double by) {
  280. return redisTemplate.opsForHash().increment(key, item, -by);
  281. }
  282. //============================set=============================
  283. /**
  284. * 根据key获取Set中的所有值
  285. *
  286. * @param key 键
  287. * @return
  288. */
  289. public Set<Object> sGet(String key) {
  290. try {
  291. return redisTemplate.opsForSet().members(key);
  292. } catch (Exception e) {
  293. e.printStackTrace();
  294. return null;
  295. }
  296. }
  297. /**
  298. * 根据value从一个set中查询,是否存在
  299. *
  300. * @param key 键
  301. * @param value 值
  302. * @return true 存在 false不存在
  303. */
  304. public boolean sHasKey(String key, Object value) {
  305. try {
  306. return redisTemplate.opsForSet().isMember(key, value);
  307. } catch (Exception e) {
  308. e.printStackTrace();
  309. return false;
  310. }
  311. }
  312. /**
  313. * 将数据放入set缓存
  314. *
  315. * @param key 键
  316. * @param values 值 可以是多个
  317. * @return 成功个数
  318. */
  319. public long sSet(String key, Object... values) {
  320. try {
  321. return redisTemplate.opsForSet().add(key, values);
  322. } catch (Exception e) {
  323. e.printStackTrace();
  324. return 0;
  325. }
  326. }
  327. /**
  328. * 将set数据放入缓存
  329. *
  330. * @param key 键
  331. * @param time 时间(秒)
  332. * @param values 值 可以是多个
  333. * @return 成功个数
  334. */
  335. public long sSetAndTime(String key, long time, Object... values) {
  336. try {
  337. Long count = redisTemplate.opsForSet().add(key, values);
  338. if (time > 0) {
  339. expire(key, time);
  340. }
  341. return count;
  342. } catch (Exception e) {
  343. e.printStackTrace();
  344. return 0;
  345. }
  346. }
  347. /**
  348. * 获取set缓存的长度
  349. *
  350. * @param key 键
  351. * @return
  352. */
  353. public long sGetSetSize(String key) {
  354. try {
  355. return redisTemplate.opsForSet().size(key);
  356. } catch (Exception e) {
  357. e.printStackTrace();
  358. return 0;
  359. }
  360. }
  361. /**
  362. * 移除值为value的
  363. *
  364. * @param key 键
  365. * @param values 值 可以是多个
  366. * @return 移除的个数
  367. */
  368. public long setRemove(String key, Object... values) {
  369. try {
  370. Long count = redisTemplate.opsForSet().remove(key, values);
  371. return count;
  372. } catch (Exception e) {
  373. e.printStackTrace();
  374. return 0;
  375. }
  376. }
  377. //===============================list=================================
  378. /**
  379. * 获取list缓存的内容
  380. *
  381. * @param key 键
  382. * @param start 开始
  383. * @param end 结束 0 到 -1代表所有值
  384. * @return
  385. */
  386. public List<Object> lGet(String key, long start, long end) {
  387. try {
  388. return redisTemplate.opsForList().range(key, start, end);
  389. } catch (Exception e) {
  390. e.printStackTrace();
  391. return null;
  392. }
  393. }
  394. /**
  395. * 获取list缓存的长度
  396. *
  397. * @param key 键
  398. * @return
  399. */
  400. public long lGetListSize(String key) {
  401. try {
  402. return redisTemplate.opsForList().size(key);
  403. } catch (Exception e) {
  404. e.printStackTrace();
  405. return 0;
  406. }
  407. }
  408. /**
  409. * 通过索引 获取list中的值
  410. *
  411. * @param key 键
  412. * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
  413. * @return
  414. */
  415. public Object lGetIndex(String key, long index) {
  416. try {
  417. return redisTemplate.opsForList().index(key, index);
  418. } catch (Exception e) {
  419. e.printStackTrace();
  420. return null;
  421. }
  422. }
  423. /**
  424. * 将list放入缓存
  425. *
  426. * @param key 键
  427. * @param value 值
  428. * @return
  429. */
  430. public boolean lSet(String key, Object value) {
  431. try {
  432. redisTemplate.opsForList().rightPush(key, value);
  433. return true;
  434. } catch (Exception e) {
  435. e.printStackTrace();
  436. return false;
  437. }
  438. }
  439. /**
  440. * 将list放入缓存
  441. *
  442. * @param key 键
  443. * @param value 值
  444. * @param time 时间(秒)
  445. * @return
  446. */
  447. public boolean lSet(String key, Object value, long time) {
  448. try {
  449. redisTemplate.opsForList().rightPush(key, value);
  450. if (time > 0) {
  451. expire(key, time);
  452. }
  453. return true;
  454. } catch (Exception e) {
  455. e.printStackTrace();
  456. return false;
  457. }
  458. }
  459. /**
  460. * 将list放入缓存
  461. *
  462. * @param key 键
  463. * @param value 值
  464. * @return
  465. */
  466. public boolean lSet(String key, List<Object> value) {
  467. try {
  468. redisTemplate.opsForList().rightPushAll(key, value);
  469. return true;
  470. } catch (Exception e) {
  471. e.printStackTrace();
  472. return false;
  473. }
  474. }
  475. /**
  476. * 将list放入缓存
  477. *
  478. * @param key 键
  479. * @param value 值
  480. * @param time 时间(秒)
  481. * @return
  482. */
  483. public boolean lSet(String key, List<Object> value, long time) {
  484. try {
  485. redisTemplate.opsForList().rightPushAll(key, value);
  486. if (time > 0) {
  487. expire(key, time);
  488. }
  489. return true;
  490. } catch (Exception e) {
  491. e.printStackTrace();
  492. return false;
  493. }
  494. }
  495. /**
  496. * 根据索引修改list中的某条数据
  497. *
  498. * @param key 键
  499. * @param index 索引
  500. * @param value 值
  501. * @return
  502. */
  503. public boolean lUpdateIndex(String key, long index, Object value) {
  504. try {
  505. redisTemplate.opsForList().set(key, index, value);
  506. return true;
  507. } catch (Exception e) {
  508. e.printStackTrace();
  509. return false;
  510. }
  511. }
  512. /**
  513. * 移除N个值为value
  514. *
  515. * @param key 键
  516. * @param count 移除多少个
  517. * @param value 值
  518. * @return 移除的个数
  519. */
  520. public long lRemove(String key, long count, Object value) {
  521. try {
  522. Long remove = redisTemplate.opsForList().remove(key, count, value);
  523. return remove;
  524. } catch (Exception e) {
  525. e.printStackTrace();
  526. return 0;
  527. }
  528. }
  529. }

三、SpringBoot项目集成log4j2

SpringBoot项目在运行的时候可能会产生一些运行信息,如果能将这些信息记录下来,那么对于该项目的运行状态以及错误排查会起到一个非常好的帮助,所以采用log4j2进行日志记录

1、pom.xml添加依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. <exclusions>
  5. <!-- 排除自带的logback依赖 -->
  6. <exclusion>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-logging</artifactId>
  9. </exclusion>
  10. </exclusions>
  11. </dependency>
  12. <!-- log4j2 -->
  13. <dependency>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-starter-log4j2</artifactId>
  16. </dependency>

2、log4j2.xml配置文件,放置于resources文件夹下

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Configuration status="fatal">
  3. <Properties>
  4. <Property name="baseDir" value="/home/leilee/Projects/back/logs"/>
  5. </Properties>
  6. <Appenders>
  7. <Console name="Console" target="SYSTEM_OUT">
  8. <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
  9. <ThresholdFilter level="info" onMatch="ACCEPT"
  10. onMismatch="DENY"/>
  11. <PatternLayout
  12. pattern="[%d{MM:dd HH:mm:ss.SSS}] [%level] [%logger{36}] - %msg%n"/>
  13. </Console>
  14. <!--debug级别日志文件输出-->
  15. <RollingFile name="debug_appender" fileName="${baseDir}/debug.log"
  16. filePattern="${baseDir}/debug_%i.log.%d{yyyy-MM-dd}">
  17. <!-- 过滤器 -->
  18. <Filters>
  19. <!-- 限制日志级别在debug及以上在info以下 -->
  20. <ThresholdFilter level="debug"/>
  21. <ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/>
  22. </Filters>
  23. <!-- 日志格式 -->
  24. <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
  25. <!-- 策略 -->
  26. <Policies>
  27. <!-- 每隔一天转存 -->
  28. <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
  29. <!-- 文件大小 -->
  30. <SizeBasedTriggeringPolicy size="100 MB"/>
  31. </Policies>
  32. </RollingFile>
  33. <!-- info级别日志文件输出 -->
  34. <RollingFile name="info_appender" fileName="${baseDir}/info.log"
  35. filePattern="${baseDir}/info_%i.log.%d{yyyy-MM-dd}">
  36. <!-- 过滤器 -->
  37. <Filters>
  38. <!-- 限制日志级别在info及以上在error以下 -->
  39. <ThresholdFilter level="info"/>
  40. <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
  41. </Filters>
  42. <!-- 日志格式 -->
  43. <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
  44. <!-- 策略 -->
  45. <Policies>
  46. <!-- 每隔一天转存 -->
  47. <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
  48. <!-- 文件大小 -->
  49. <SizeBasedTriggeringPolicy size="100 MB"/>
  50. </Policies>
  51. </RollingFile>
  52. <!-- error级别日志文件输出 -->
  53. <RollingFile name="error_appender" fileName="${baseDir}/error.log"
  54. filePattern="${baseDir}/error_%i.log.%d{yyyy-MM-dd}">
  55. <!-- 过滤器 -->
  56. <Filters>
  57. <!-- 限制日志级别在error及以上 -->
  58. <ThresholdFilter level="error"/>
  59. </Filters>
  60. <!-- 日志格式 -->
  61. <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
  62. <Policies>
  63. <!-- 每隔一天转存 -->
  64. <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
  65. <!-- 文件大小 -->
  66. <SizeBasedTriggeringPolicy size="100 MB"/>
  67. </Policies>
  68. </RollingFile>
  69. </Appenders>
  70. <Loggers>
  71. <Root level="debug">
  72. <AppenderRef ref="Console"/>
  73. <AppenderRef ref="debug_appender"/>
  74. <AppenderRef ref="info_appender"/>
  75. <AppenderRef ref="error_appender"/>
  76. </Root>
  77. </Loggers>
  78. </Configuration>

注意:第四行中value的值即输出的log文件的存放路径

3、自定义log信息

如果自己想存入一些自定义的信息,那么采用@Log4j2对类进行注解,然后在类中使用log的方法即可,以该网站的数据库读取过程为例

  1. package cn.huskysir.Service.Impl;
  2. import cn.huskysir.Dao.DynastyMapper;
  3. import cn.huskysir.Dao.EmperorMapper;
  4. import cn.huskysir.Entity.MySQL.Dynasty;
  5. import cn.huskysir.Entity.MySQL.Emperor;
  6. import cn.huskysir.Service.EmperorService;
  7. import cn.huskysir.Utils.RedisUtil;
  8. import cn.huskysir.Vo.EmperorVo;
  9. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  10. import lombok.extern.log4j.Log4j2;
  11. import org.springframework.beans.BeanUtils;
  12. import org.springframework.stereotype.Service;
  13. import javax.annotation.Resource;
  14. import java.util.Date;
  15. import java.util.LinkedList;
  16. import java.util.List;
  17. /**
  18. * Emperor Service层(实现类)
  19. */
  20. @Log4j2
  21. @Service
  22. public class EmperorServiceImpl implements EmperorService {
  23. @Resource
  24. EmperorMapper emperorMapper;
  25. @Resource
  26. DynastyMapper dynastyMapper;
  27. @Resource
  28. RedisUtil redisUtil;
  29. /**
  30. * 获得所有EmperorVo对象列表
  31. *
  32. * @return
  33. */
  34. @Override
  35. public List<EmperorVo> getAllEmperorVoList() {
  36. // 判断Redis是否存在该结果
  37. String key = "getAllEmperorVoList";
  38. if (redisUtil.hasKey(key)) {
  39. List<EmperorVo> emperorVoList = (List<EmperorVo>) redisUtil.get(key);
  40. System.out.println("由Redis得到" + key + "结果");
  41. // 日志记录
  42. log.info(new Date() + " 由Redis得到" + key + "数据");
  43. return emperorVoList;
  44. }
  45. List<Emperor> emperorList = emperorMapper.selectList(null);
  46. List<EmperorVo> emperorVoList = new LinkedList<>();
  47. for (Emperor emperor : emperorList) {
  48. EmperorVo emperorVo = new EmperorVo();
  49. BeanUtils.copyProperties(emperor, emperorVo);
  50. Dynasty dynasty = dynastyMapper.selectById(emperor.getDynastyId());
  51. emperorVo.setDynastyName(dynasty.getName());
  52. emperorVo.calculateTime();
  53. emperorVoList.add(emperorVo);
  54. }
  55. System.out.println("由MySQL得到" + key + "结果");
  56. // 日志记录
  57. log.info(new Date() + " 由MySQL得到" + key + "数据");
  58. if (redisUtil.set(key, emperorVoList, 600)) {
  59. System.out.println("Redis已存入" + key + "数据");
  60. // 日志记录
  61. log.info(new Date() + " Redis已存入" + key + "数据");
  62. }
  63. return emperorVoList;
  64. }
  65. /**
  66. * 根据id获得EmperorVo对象
  67. *
  68. * @param id
  69. * @return
  70. */
  71. @Override
  72. public EmperorVo getEmperorVoById(Integer id) {
  73. // 判断Redis是否存在该结果
  74. String key = "getEmperorVoById_" + String.valueOf(id);
  75. if (redisUtil.hasKey(key)) {
  76. EmperorVo emperorVo = (EmperorVo) redisUtil.get(key);
  77. System.out.println("由Redis得到" + key + "结果");
  78. // 日志记录
  79. log.info(new Date() + " 由Redis得到" + key + "数据");
  80. return emperorVo;
  81. }
  82. Emperor emperor = emperorMapper.selectById(id);
  83. EmperorVo emperorVo = new EmperorVo();
  84. BeanUtils.copyProperties(emperor, emperorVo);
  85. Dynasty dynasty = dynastyMapper.selectById(emperor.getDynastyId());
  86. emperorVo.setDynastyName(dynasty.getName());
  87. emperorVo.calculateTime();
  88. System.out.println("由MySQL得到" + key + "结果");
  89. // 日志记录
  90. log.info(new Date() + " 由MySQL得到" + key + "数据");
  91. if (redisUtil.set(key, emperorVo, 600)) {
  92. System.out.println("Redis已存入" + key + "数据");
  93. // 日志记录
  94. log.info(new Date() + " Redis已存入" + key + "数据");
  95. }
  96. return emperorVo;
  97. }
  98. /**
  99. * 根据dynastyId获得所有EmperorVo对象列表
  100. *
  101. * @param dynastyId
  102. * @return
  103. */
  104. @Override
  105. public List<EmperorVo> getEmperorListByDynastyId(Integer dynastyId) {
  106. // 判断Redis是否存在该结果
  107. String key = "getEmperorListByDynastyId_" + String.valueOf(dynastyId);
  108. if (redisUtil.hasKey(key)) {
  109. List<EmperorVo> emperorVoList = (List<EmperorVo>) redisUtil.get(key);
  110. System.out.println("由Redis得到" + key + "结果");
  111. // 日志记录
  112. log.info(new Date() + " 由Redis得到" + key + "数据");
  113. return emperorVoList;
  114. }
  115. QueryWrapper<Emperor> queryWrapper = new QueryWrapper<>();
  116. queryWrapper.eq("dynasty_id", dynastyId);
  117. List<Emperor> emperorList = emperorMapper.selectList(queryWrapper);
  118. List<EmperorVo> emperorVoList = new LinkedList<>();
  119. String nastyName = dynastyMapper.selectById(dynastyId).getName();
  120. for (Emperor emperor : emperorList) {
  121. EmperorVo emperorVo = new EmperorVo();
  122. BeanUtils.copyProperties(emperor, emperorVo);
  123. emperorVo.setDynastyName(nastyName);
  124. emperorVo.calculateTime();
  125. emperorVoList.add(emperorVo);
  126. }
  127. System.out.println("由MySQL得到" + key + "结果");
  128. // 日志记录
  129. log.info(new Date() + " 由MySQL得到" + key + "数据");
  130. if (redisUtil.set(key, emperorVoList, 600)) {
  131. System.out.println("Redis已存入" + key + "数据");
  132. // 日志记录
  133. log.info(new Date() + " Redis已存入" + key + "数据");
  134. }
  135. return emperorVoList;
  136. }
  137. }

以“getEmperorListByDynastyId(Integer dynastyId)”方法为例,该方法是根据dynastyId获得List对象,首先会根据方法名及dynastyIdRedis数据库中查找,若存在则直接返回,否则从MySQL数据库中读取,并将结果存入Redis数据库中然后返回。使用log.info()记录数据库读取过程,该记录会存储于info.log文件中

该网站后台的info.log日志记录如下

  1. [00:54:31:770] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:141) - Wed Sep 20 00:54:31 CST 2023 MySQL得到getEmperorListByDynastyId_1数据
  2. [00:54:31:773] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:145) - Wed Sep 20 00:54:31 CST 2023 Redis已存入getEmperorListByDynastyId_1数据
  3. [00:54:35:853] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:141) - Wed Sep 20 00:54:35 CST 2023 MySQL得到getEmperorListByDynastyId_2数据
  4. [00:54:35:863] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:145) - Wed Sep 20 00:54:35 CST 2023 Redis已存入getEmperorListByDynastyId_2数据
  5. [00:54:37:363] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:123) - Wed Sep 20 00:54:37 CST 2023 Redis得到getEmperorListByDynastyId_1数据
  6. [00:54:38:043] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:123) - Wed Sep 20 00:54:38 CST 2023 Redis得到getEmperorListByDynastyId_2数据
  7. [00:54:39:214] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:123) - Wed Sep 20 00:54:39 CST 2023 Redis得到getEmperorListByDynastyId_1数据
  8. [00:54:39:936] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:123) - Wed Sep 20 00:54:39 CST 2023 Redis得到getEmperorListByDynastyId_2数据

四、总结

关于SpringBoot项目配置Redis与log4j2是查询官方文档以及他人博客得到的,本文中的Redis配置类、Redis工具类以及log4j2.xml配置文件来自网络,查证源自何处比较麻烦,所以在此感谢所有人的分享!

原文链接:https://www.cnblogs.com/huskysir/p/17716281.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号