SpringBoot中的一些组件

Redis

引入data-redis-starter

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
   <exclusions>
       <!-- 排除lettuce依赖 -->
       <exclusion>
           <groupId>io.lettuce</groupId>
           <artifactId>lettuce-core</artifactId>
       </exclusion></exclusions>
</dependency>
<dependency>
   <!-- 使用jedis客户端 -->
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
</dependency>

lettuce客户端会产生堆外内存溢出:OutOfDirectMemoryError(堆外内存溢出)

  1. SpringBoot 2.0以后 默认使用lettuce作为操作redis的客户端,它使用netty进行网络通信。lettuce的bug导致netty堆外内存溢出 -Xmx100m netty。如果没有指定堆外内存,默认使用-Xmx100m

    可以通过-Dio.netty.maxDirectMemory进行设置(调大堆外内存)

    解决方案:不能只是调大堆外内存

    • 升级lettuce客户端

    • 切换使用jedis

  2. lettuce和jedis是操作redis的底层客户端,spring进行了再次封装redisTemplate;

  3. 所以不管底层用的是lettuce还是jedis我们直接使用redisTemplate即可操作redis;

 

简单配置redis的host、port等信息

spring:
redis:
  host: 192.168.101.100
  port: 6379

 

  1. 使用SpringBoot自动配置好的StringRedisTemplate来操作redis

 

Redisson

<!--    以后使用redisson作为所有分布式锁,分布式对象等功能框架    -->
<dependency>
   <groupId>org.redisson</groupId>
   <artifactId>redisson</artifactId>
   <version>3.12.0</version>
</dependency>

 

/**
* 配置Redisson操作客户端
*/
@Configuration
public class MyRedissonConfig {

   /**
    * 所有对Redisson的使用都是通过 RedissonClient对象
    **/
   @Bean(destroyMethod="shutdown")
   public RedissonClient redisson() throws IOException {
       // 1.创建配置
       //Redis url should start with redis:// or rediss:// (for SSL connection)
       Config config = new Config();
       // 使用单节点模式,指定redis服务器地址
       config.useSingleServer().setAddress("redis://192.168.101.100:6379");
       // 2.根据Config创建出RedissonClient实例
       return Redisson.create(config);
  }
}

 

 

SpringCache

  1. 引入依赖 spring-boot-starter-cache、spring-boot-starter-data-redis

    <!-- 再加上上文的Redis依赖 -->
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>

     

  2. 配置类

    @EnableConfigurationProperties(CacheProperties.class) // 开启属性配置的绑定功能
    @Configuration
    @EnableCaching // 开启缓存功能
    public class MyCacheConfig {

       @Bean
       RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){
           RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
           // key的序列化
           config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
           // value的序列化
           config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
           CacheProperties.Redis redisProperties = cacheProperties.getRedis();
           // 将配置文件中的所有配置都生效
           if (redisProperties.getTimeToLive() != null) {
               config = config.entryTtl(redisProperties.getTimeToLive());
          }
           if (redisProperties.getKeyPrefix() != null) {
               config = config.prefixKeysWith(redisProperties.getKeyPrefix());
          }
           if (!redisProperties.isCacheNullValues()) {
               config = config.disableCachingNullValues();
          }
           if (!redisProperties.isUseKeyPrefix()) {
               config = config.disableKeyPrefix();
          }
           return config;
      }
    }
  3. 配置文件

    # 配置使用redis作为缓存
    spring.cache.type=redis
    # 过期时间:毫秒
    spring.cache.redis.time-to-live=3600000
    # 缓存前缀,如果指定了前缀就用我们指定的前缀,若没有就默认使用缓存的名字作为前缀 缓存的名字:@Cacheable(value = {"category"})
    #spring.cache.redis.key-prefix=CACHE_
    # 是否使用缓存前缀
    spring.cache.redis.use-key-prefix=true
    # 是否缓存空值,防止缓存穿透
    spring.cache.redis.cache-null-values=true
  4. 使用缓存

    • @Cacheable: Triggers cache population. 触发将数据保存到缓存的操作

      @Cacheable可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。@Cacheable可以指定三个属性,value、key和condition。

    • @CacheEvict: Triggers cache eviction. 触发将数据从缓存删除

      @CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称);key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key;condition表示清除操作发生的条件。

    • @CachePut: Updates the cache without interfering with the method execution.以不影响方法执行的方式更新缓存

      在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

    • @Caching: Regroups multiple cache operations to be applied on a method. 组合多个缓存操作

      @Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。

    • @CacheConfig: Shares some common cache-related settings at class-level. 在类级别共享缓存的相同配置

      @CacheConfig用在类上,将公共缓存内容写在该注解中,方法中这些属性即可不用再写了

       

    • 开启缓存功能 @EnableCaching

    • 只需要使用注解就能完成缓存操作

  5. 代码

    @Cacheable(value = {"category"},key = "#root.method.name",sync = true) //sync = true 很重要(加锁,解决击穿)
    @Override
    public List<CategoryEntity> getLevel1Categorys() {
       System.out.println("getLevel1Categorys....");
       List<CategoryEntity> categoryEntities = baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));
       return categoryEntities;
    }

    @Cacheable(value = "category",key = "#root.methodName")
    @Override
    public Map<String, List<Catelog2Vo>> getCatalogJson() {
       dosomething();
    }

    @CacheEvict(value = "category",allEntries = true) // 指定删除某个分区下的所有数据
    @Transactional
    @Override
    public void updateCascade(CategoryEntity category) {
       this.updateById(category); //先更新自己
       categoryBrandRelationService.updateCategory(category.getCatId(), category.getName());
       // 同时修改缓存中的数据【双写模式】
       // 删除缓存中的数据,等待下一次主动查询进行更新【失效模式】
    }

    @Caching(cacheable = @Cacheable("users"), evict = { @CacheEvict("cache2"),
    @CacheEvict(value = "cache3", allEntries = true) })
    public User find(Integer id) {
    return null;
    }
    @CacheConfig(value="emp")
    public class EmployeeService{
    @Cacheable(key="#user.id")
    public User find(User user) {
      return null;
      }
      @Cacheable(key = "#root.args[0]")
      public User getUserById(Integer id){
      User user=userMapper.getUserById(id);
    return user;
      }
    }

    @Cacheable({"category"})

    代表当前方法的结果需要缓存。如果缓存中有,方法不用调用,如果缓存中没有,会调用方法,最后将方法中的结果放入缓存。 每一个需要缓存的数据我们都来指定要放到哪个名字的缓存,这里是放在“category”分区【缓存的分区(按照业务类型分)】

    image-20240321225817197

默认行为 1)如果缓存中有,方法不调用 2)key默认自动生成:缓存的名字 category::SimpleKey [] (自动生成的key) 3)缓存的value的值,默认使用jdk序列化机制,将序列化后的数据存到redis 4)默认ttl时间:-1 永不过期

 

自定义

1)value是我们设置的缓存中的分区名字。 2)指定生成的缓存使用的key : key属性指定,接收一个spEL spEL详细语法参照文档 3)指定缓存的数据的存活时间 配置文件中修改ttl 4)将数据存为json数据

 

mybatisplus

  1. 依赖

    <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.2.0</version>
    </dependency>
  2. 配置

    spring:
    datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.101.100:3306/gulimall_pms?useUnicode=true&characterEncoding=UTF8
    mybatis-plus:
    mapper-locations: classpath:/mapper/**/*.xml
    #设置实体类的自增主键
    global-config:
    db-config:
    id-type: auto
    #逻辑删除
    logic-delete-value: 1
    logic-not-delete-value: 2
  3. @MapperScan注解

    实体类字段上加上逻辑删除注解@TableLogic

  4.  
posted @ 2024-03-21 23:39  小陈_winwah  阅读(9)  评论(0编辑  收藏  举报