1、什么是缓存?

- 缓存是指把经常需要读写的数据,保存到一个高速的缓冲区中,这个行为叫缓存

- 也可以是指被保存在高速缓冲区的数据,也叫缓存

2、Mybatis缓存

Mybatis中分为一级缓存和二级缓存

- 一级缓存,数据缓存在这个SqlSession的作用范围内

- 二级缓存,数据缓存在这个SqlSesssionFactory的作用范围内

一级缓存:

一级缓存是默认开启的,那么如何证实是开启的呢?

同一个SQL语句只会执行一次,并留下缓存,

如果在这个SqlSession存在的期间,再次调用,那么Mybatis将不会执行SQL

而是直接调用缓存执行

案例:

映射接口

  1. User getUserById(Integer id);

映射器

  1. <select id="getUserById" resultType="user" parameterType="int">
  2. SELECT *
  3. FROM t_user
  4. WHERE id = #{id}
  5. </select>

测试类

  1. @Test
  2. public void getUserById(){
  3. SqlSession sqlSession = MybatisUtil.getSqlSession(true);
  4. UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
  5.  
  6. User user1 = userMapper.getUserById(1);
  7. System.out.println(user1);
  8.  
  9. User user2 = userMapper.getUserById(1);
  10. System.out.println(user2);
  11.  
  12. User user3 = userMapper.getUserById(1);
  13. System.out.println(user3);
  14.  
  15. User user4 = userMapper.getUserById(1);
  16. System.out.println(user4);
  17.  
  18. sqlSession.close();
  19. }

测试结果:

  1. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
  2. [org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 336371513.
  3. [cn.dai.mapper.UserMapper.getUserById]-==> Preparing: SELECT * FROM t_user WHERE id = ?
  4. [cn.dai.mapper.UserMapper.getUserById]-==> Parameters: 1(Integer)
  5. [cn.dai.mapper.UserMapper.getUserById]-<== Total: 1
  6. User(id=1, last_name=阿伟, gender=0)
  7. User(id=1, last_name=阿伟, gender=0)
  8. User(id=1, last_name=阿伟, gender=0)
  9. User(id=1, last_name=阿伟, gender=0)
  10. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@140c9f39]
  11. [org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 336371513 to pool.
  12.  
  13. Process finished with exit code 0

这里可以看到SQL语句只执行了一次

4次查询只执行了一次,这证明了缓存的存在

也就是说,实际上缓存存放的数据是首次查询出来的一个结果

如果我们反复调用相同的结果,Mybatis就会从缓存中返回数据给我们

但是在查询不同情况下的值的时候,Mybatis还是无法调用缓存来完成

例如我们这样查询不同的数据出来:

  1. @Test
  2. public void getUserById(){
  3. SqlSession sqlSession = MybatisUtil.getSqlSession(true);
  4. UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
  5.  
  6. User user1 = userMapper.getUserById(1);
  7. System.out.println(user1);
  8.  
  9. User user2 = userMapper.getUserById(2);
  10. System.out.println(user2);
  11.  
  12. User user3 = userMapper.getUserById(3);
  13. System.out.println(user3);
  14.  
  15. User user4 = userMapper.getUserById(4);
  16. System.out.println(user4);
  17.  
  18. sqlSession.close();
  19. }

结果就是不会触发缓存,因为每次查询的都不一样

  1. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
  2. [org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 336371513.
  3. [cn.dai.mapper.UserMapper.getUserById]-==> Preparing: SELECT * FROM t_user WHERE id = ?
  4. [cn.dai.mapper.UserMapper.getUserById]-==> Parameters: 1(Integer)
  5. [cn.dai.mapper.UserMapper.getUserById]-<== Total: 1
  6. User(id=1, last_name=阿伟, gender=0)
  7. [cn.dai.mapper.UserMapper.getUserById]-==> Preparing: SELECT * FROM t_user WHERE id = ?
  8. [cn.dai.mapper.UserMapper.getUserById]-==> Parameters: 2(Integer)
  9. [cn.dai.mapper.UserMapper.getUserById]-<== Total: 1
  10. User(id=2, last_name=阿伟, gender=1)
  11. [cn.dai.mapper.UserMapper.getUserById]-==> Preparing: SELECT * FROM t_user WHERE id = ?
  12. [cn.dai.mapper.UserMapper.getUserById]-==> Parameters: 3(Integer)
  13. [cn.dai.mapper.UserMapper.getUserById]-<== Total: 1
  14. User(id=3, last_name=杰哥, gender=0)
  15. [cn.dai.mapper.UserMapper.getUserById]-==> Preparing: SELECT * FROM t_user WHERE id = ?
  16. [cn.dai.mapper.UserMapper.getUserById]-==> Parameters: 4(Integer)
  17. [cn.dai.mapper.UserMapper.getUserById]-<== Total: 1
  18. User(id=4, last_name=阿强, gender=0)
  19. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@140c9f39]
  20. [org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 336371513 to pool.
  21.  
  22. Process finished with exit code 0

原理示意:

一级缓存失败的四种情况:

- 不在同一个SqlSession对象中【同一个SQL语句】

- 执行的语句的参数不一样,缓存中也不存在数据【就是上面的演示】

- 执行增、删、改、会清除缓存

- 自行手动清除

手动清除是指SqlSession调用清除缓存方法

  1. sqlSession.clearCache();

为什么增、删、改、也会清除缓存?

是因为底层在SQL执行完默认就调用了这个方法清除了

二级缓存:

首先,二级缓存默认是不开启的,我们需要在Mybatis的核心配置文件中

配置关于二级缓存的SETTINGS选项,和在映射器的配置文件中加入cache标签

并且,需要被二级缓存的对象,必须要实现序列化接口

示意图:

开启二级缓存的配置操作:

1、核心配置中添加二级缓存配置

2、映射器加入cache标签

3、被缓存的对象所属类必须实现序列化接口

二级缓存开启配置

  1. <setting name="cacheEnabled" value="true"/>

映射器配置cache标签

  1. <cache/>

测试类

  1. public void cacheTest(){
  2. SqlSession sqlSession = MybatisUtil.getSqlSession(true);
  3. UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  4.  
  5. User userById = mapper.getUserById(1);
  6. System.out.println(userById);
  7.  
  8. sqlSession.close();
  9. }
  10.  
  11. @Test
  12. public void sync(){
  13. cacheTest();
  14. cacheTest();
  15. }

如果不实现序列化接口,二级缓存在调用时,就会出现未序列化异常

  1. [cn.dai.mapper.UserMapper]-Cache Hit Ratio [cn.dai.mapper.UserMapper]: 0.0
  2. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
  3. [org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 1025309396.
  4. [cn.dai.mapper.UserMapper.getUserById]-==> Preparing: SELECT * FROM t_user WHERE id = ?
  5. [cn.dai.mapper.UserMapper.getUserById]-==> Parameters: 1(Integer)
  6. [cn.dai.mapper.UserMapper.getUserById]-<== Total: 1
  7. User(id=1, last_name=阿伟, gender=0)
  8. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3d1cfad4]
  9. [org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 1025309396 to pool.
  10.  
  11. org.apache.ibatis.cache.CacheException: Error serializing object. Cause: java.io.NotSerializableException: cn.dai.pojo.User
  12.  
  13. at org.apache.ibatis.cache.decorators.SerializedCache.serialize(SerializedCache.java:94)
  14. at org.apache.ibatis.cache.decorators.SerializedCache.putObject(SerializedCache.java:55)
  15. at org.apache.ibatis.cache.decorators.LoggingCache.putObject(LoggingCache.java:49)
  16. at org.apache.ibatis.cache.decorators.SynchronizedCache.putObject(SynchronizedCache.java:43)
  17. at org.apache.ibatis.cache.decorators.TransactionalCache.flushPendingEntries(TransactionalCache.java:116)
  18. at org.apache.ibatis.cache.decorators.TransactionalCache.commit(TransactionalCache.java:99)
  19. at org.apache.ibatis.cache.TransactionalCacheManager.commit(TransactionalCacheManager.java:44)
  20. at org.apache.ibatis.executor.CachingExecutor.close(CachingExecutor.java:61)
  21. at org.apache.ibatis.session.defaults.DefaultSqlSession.close(DefaultSqlSession.java:263)
  22. at BuildTest.cacheTest(BuildTest.java:59)
  23. at BuildTest.sync(BuildTest.java:64)
  24. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  25. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  26. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  27. at java.lang.reflect.Method.invoke(Method.java:498)
  28. at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
  29. at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
  30. at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
  31. at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
  32. at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
  33. at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
  34. at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
  35. at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
  36. at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
  37. at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
  38. at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
  39. at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
  40. at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
  41. at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
  42. at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
  43. at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
  44. at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
  45. at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
  46. at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
  47. at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
  48. at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
  49. Caused by: java.io.NotSerializableException: cn.dai.pojo.User
  50. at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
  51. at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
  52. at java.util.ArrayList.writeObject(ArrayList.java:766)
  53. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  54. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  55. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  56. at java.lang.reflect.Method.invoke(Method.java:498)
  57. at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1140)
  58. at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
  59. at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
  60. at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
  61. at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
  62. at org.apache.ibatis.cache.decorators.SerializedCache.serialize(SerializedCache.java:90)
  63. ... 35 more
  64.  
  65. Process finished with exit code -1

所以需要我们自己来把实体类序列化

再次测试:

  1. [cn.dai.mapper.UserMapper]-Cache Hit Ratio [cn.dai.mapper.UserMapper]: 0.0
  2. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
  3. [org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 1025309396.
  4. [cn.dai.mapper.UserMapper.getUserById]-==> Preparing: SELECT * FROM t_user WHERE id = ?
  5. [cn.dai.mapper.UserMapper.getUserById]-==> Parameters: 1(Integer)
  6. [cn.dai.mapper.UserMapper.getUserById]-<== Total: 1
  7. User(id=1, last_name=阿伟, gender=0)
  8. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3d1cfad4]
  9. [org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 1025309396 to pool.
  10. [cn.dai.mapper.UserMapper]-Cache Hit Ratio [cn.dai.mapper.UserMapper]: 0.5
  11. User(id=1, last_name=阿伟, gender=0)
  12.  
  13. Process finished with exit code 0

可以看到二次调用时不再调用SQL查询,而是使用了二级缓存保留的数据返回结果

一些说明:

useCache属性,这个属性是放在SQL查询标签中的<SELECT>

默认TRUE(就是不写也表示开启的),表示使用二级缓存,前提是二级缓存是开启的

在上面的全局测试中已经演示了结果

如果更改为False就是取消这个SQL的二级缓存

测试结果就是第二次查询就需要再次调用SQL了

  1. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
  2. [org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 1504642150.
  3. [cn.dai.mapper.UserMapper.getUserById]-==> Preparing: SELECT * FROM t_user WHERE id = ?
  4. [cn.dai.mapper.UserMapper.getUserById]-==> Parameters: 1(Integer)
  5. [cn.dai.mapper.UserMapper.getUserById]-<== Total: 1
  6. User(id=1, last_name=阿伟, gender=0)
  7. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@59af0466]
  8. [org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 1504642150 to pool.
  9. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
  10. [org.apache.ibatis.datasource.pooled.PooledDataSource]-Checked out connection 1504642150 from pool.
  11. [cn.dai.mapper.UserMapper.getUserById]-==> Preparing: SELECT * FROM t_user WHERE id = ?
  12. [cn.dai.mapper.UserMapper.getUserById]-==> Parameters: 1(Integer)
  13. [cn.dai.mapper.UserMapper.getUserById]-<== Total: 1
  14. User(id=1, last_name=阿伟, gender=0)
  15. [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@59af0466]
  16. [org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 1504642150 to pool.
  17.  
  18. Process finished with exit code 0

flushCache属性,这个属性是放在增、删、改、SQL语句中,

表示自动清除缓存,默认值TRUE,另外不要手贱改FALSE

如果不清除缓存,二次调用就从缓存的数据进行返回

为什么这么说?

- 先查询一个结果

  【主键:01,名字:阿伟,性别:男】

- 不清除缓存进行修改记录,变更为

  【主键:01,名字:杰哥,性别:男】

- 当二次查询时,Mybatis不会再调用SQL重新查询,

  直接跑到缓存中返回数据,这个查询返回的结果就是

  【主键:01,名字:阿伟,性别:男】

  但实际上数据库已经更改,这样查询返回的结果是不对的

  所以不要修改flushCache属性为False!!!

3、Cache标签:

当你在映射器中标注了此标签,Mybatis会默认开启这些功能:

  • 映射语句文件中的所有 select 语句的结果将会被缓存。
  • 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
  • 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
  • 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
  • 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。【就是能放多少个缓存】
  • 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

1、最近最少使用算法

  【Least Recently Used 】LRU算法来清除不需要的缓存。

  移除符合这个描述的对象,优化内存空间

除此之外还有其他算法,这个属性值由eviction配置

2、先进先出算法

  FIFO,First In First Out 先进先出

  按对象进入缓存的顺序来移除

3、软引用算法

  SOFT,移除基于GC回收状态和软引用规则的对象

4、弱引用算法

  WEAK,弱引用,更积极的移除基于GC回收状态和弱引用规则的对象

当然,默认使用的是LRU最少使用原则清除

  1. LRU
  2. FIFO
  3. SOFT
  4. WEAK

二、可读可写的说明:

  1. readOnly="true"

可读是共享对象的,所有的SqlSession如果需要调用这个二级缓存

指针就会直接引用缓存返回对象

可读是非共享的,所有SqlSession如果调用二级缓存,

那么Mybatis会分别new一个对象,并把缓存对象的属性值赋值给这些new出来的对象

指针则引用这些对象进写入修改

三、自定义二级缓存

可以通过实现你自己的缓存,或为其他第三方缓存方案创建适配器,来完全覆盖缓存行为。

  1. <cache type="com.domain.something.MyCustomCache"/>

我们可以查看Mybatis的缓存实现类是怎么写的

  1. package org.apache.ibatis.cache.impl;
  2.  
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import org.apache.ibatis.cache.Cache;
  6. import org.apache.ibatis.cache.CacheException;
  7.  
  8. public class PerpetualCache implements Cache {
  9. private final String id;
  10. private final Map<Object, Object> cache = new HashMap();
  11.  
  12. public PerpetualCache(String id) {
  13. this.id = id;
  14. }
  15.  
  16. public String getId() {
  17. return this.id;
  18. }
  19.  
  20. public int getSize() {
  21. return this.cache.size();
  22. }
  23.  
  24. public void putObject(Object key, Object value) {
  25. this.cache.put(key, value);
  26. }
  27.  
  28. public Object getObject(Object key) {
  29. return this.cache.get(key);
  30. }
  31.  
  32. public Object removeObject(Object key) {
  33. return this.cache.remove(key);
  34. }
  35.  
  36. public void clear() {
  37. this.cache.clear();
  38. }
  39.  
  40. public boolean equals(Object o) {
  41. if (this.getId() == null) {
  42. throw new CacheException("Cache instances require an ID.");
  43. } else if (this == o) {
  44. return true;
  45. } else if (!(o instanceof Cache)) {
  46. return false;
  47. } else {
  48. Cache otherCache = (Cache)o;
  49. return this.getId().equals(otherCache.getId());
  50. }
  51. }
  52.  
  53. public int hashCode() {
  54. if (this.getId() == null) {
  55. throw new CacheException("Cache instances require an ID.");
  56. } else {
  57. return this.getId().hashCode();
  58. }
  59. }
  60. }

四、缓存的执行顺序

1、当我们执行一个查询语句的时候,mybatis会先去二级缓存中查询数据,如果二级缓存中没有,就到一级缓存中查找

2、如果一级缓存也没有,调用SQL执行

3、执行返回,并且结果保存进一级缓存

4、SqlSession关闭,一级缓存保存到二级缓存中

【Mybatis】14 缓存的更多相关文章

  1. 八 mybatis查询缓存(一级缓存,二级缓存)和ehcache整合

    1       查询缓存 1.1     什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存.

  2. MyBatis一级缓存引起的无穷递归

    MyBatis一级缓存引起的无穷递归 引言: 最近在项目中参与了一个领取优惠劵的活动,当多个用户领取同一张优惠劵的时候,使用了数据库锁控制并发,起初的设想是:如果多个人同时领一张劵,第一个到达的人领取 ...

  3. 【MyBatis源码解析】MyBatis一二级缓存

    MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级),尤其是对于一些相 ...

  4. mybatis学习--缓存(一级和二级缓存)

    声明:学习摘要! MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级) ...

  5. 三)mybatis 二级缓存,整合ehcache

    mybatis-config.xml <setting name="cacheEnabled" value="true" /> PersonMapp ...

  6. MyBatis 示例-缓存

    MyBatis 提供两种类型的缓存,一种是一级缓存,另一种是二级缓存,本章通过例子的形式描述 MyBatis 缓存的使用. 测试类:com.yjw.demo.CacheTest 一级缓存 MyBati ...

  7. MyBatis框架——缓存机制

    使⽤缓存机制的作⽤也是减少 Java 应⽤程序与数据库的交互次数,从⽽提升程序的运⾏效率. ⽐如第 ⼀次查询出某个对象之后,MyBatis 会⾃动将其存⼊缓存,当下⼀次查询同⼀个对象时,就可以直接从 ...

  8. [.net 面向对象程序设计进阶] (14) 缓存(Cache) (一) 认识缓存技术

    [.net 面向对象程序设计进阶] (14) 缓存(Cache)(一) 认识缓存技术 本节导读: 缓存(Cache)是一种用空间换时间的技术,在.NET程序设计中合理利用,可以极大的提高程序的运行效率 ...

  9. 通过源码分析MyBatis的缓存

    前方高能! 本文内容有点多,通过实际测试例子+源码分析的方式解剖MyBatis缓存的概念,对这方面有兴趣的小伙伴请继续看下去~ MyBatis缓存介绍 首先看一段wiki上关于MyBatis缓存的介绍 ...

  10. MyBatis 一级缓存与二级缓存

    MyBatis一级缓存 MyBatis一级缓存默认开启,一级缓存为Session级别的缓存,在执行以下操作时一级缓存会清空 1.执行session.clearCache(); 2.执行CUD操作 3. ...

随机推荐

  1. RabbbitMQ RabbitListener使用IP动态队列 Attribute value must be constant

    在RabbitMQ消息队列使用 @RabbitListener 接收消息,队列名称使用常量命名,但是如果使用动态队列名称,比如根据系统 ip 命名队列名称. 获取服务器 IP /** * 获取服务器i ...

  2. idea mapper xml 文件报红

    在使用 idea 打开 mapper 文件,出现一下报红错误: 可以看到数据表和字段都是红色的. 解决方案 打开设置,window版本是打开Settings: 找到 Languages & F ...

  3. C#.NET HTTPS 双向证书 请求被中止: 未能创建 SSL/TLS 安全通道。

    请求被中止: 未能创建 SSL/TLS 安全通道. 用mmc 给私钥证书添加Everyone 的权限.

  4. 使用Git命令从本地上传到码云

    Gitee创建仓库内没有内容 本地: 初始化Git仓库:git init 提交文件到暂存区:git add . //. 表示提交所有文件 提交文件到工作区:git commit -m "此次 ...

  5. python重拾基础第一天

    本节内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc是个什么鬼? 数据类型初识 数据运算 表达式if ...else语 ...

  6. P2467 [SDOI2010] 地精部落 学习笔记

    DP 显然我固定第一个是峰,然后再乘以2就是答案,因为一个合法的反转之后也是合法的而且谷峰颠倒了 发现如果设\(dp[i][j]\)表示前\(i\)个山脉,第\(i\)个山脉是高度\(j\)的答案,然 ...

  7. Android日志系统(logging system)

    Android日志系统(logging system) 背景 不管是做Android应用还是做Android中间层和底层,在做一些调试工作的时候,使用adb logcat非常关键.特意学习了一下安卓的 ...

  8. (Java)常用类库

    Spring 常用工具类 Spring作为常用的开发框架,在Spring框架应用中,排在ApacheCommon.Guava.Huool等通用库后,第二优先级可以考虑使用Spring-core-xxx ...

  9. debian12 笔记

    前言 最近在win10通过wsl安装了debian linux子系统(wsl2安装报错了..所以改成了wsl),没想到安装的还是最新的debian12 (Bookworm).的确和ubuntu有些不一 ...

  10. weui weui-switch 开关取值,设置默认状态

    html <div class="weui-cell__ft"> <input class="weui-switch" type=" ...