1.12 缓存处理

1.12.1 缓存配置

SpringBoot2.0 的缓存可以使用注解方式实现。

  • (1) 修改pom文件添加依赖
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
  • (2) 修改application-dev.properties配置文件
    添加配置“spring.cache.type=redis”
  • (3) 添加@EnableCaching开启缓存注解
@EnableCaching
@ServletComponentScan
@SpringBootApplication(scanBasePackages = {"com.zone7.demo.helloworld"})
public class HelloworldApplication {

 public static void main(String[] args) {
  SpringApplication.run(HelloworldApplication.class, args);
 }

}

1.12.2 注解说明

在需要使用缓存的方法上面添加以下注解:
- @Cacheable 将方法的运行结果进行缓存;第二次再要相同的数据,直接从缓存中获取,不再调用方法;
- @CacheEvict 移除缓存
- @CachePut 修改了数据库的某个数据,同时更新缓存

以下对这三个注解的属性展开介绍:

  • (1) @Cacheable
    Cacheable中的几个属性:
  • 1)cacheNames/value:指定缓存组件的名字, 数组的方式,可以指定多个缓存组件名称。
  • 2)key: 缓存数据使用的key,默认使用方法参数的值作为key。也可以自己指定,通过编写SpEL指定key的值;如:#root.methodName 、#id等。
  • 3)keyGenerator: key的生成器,可以自己编写key的生成器组件。注意:在使用时key和keyGenerator二选一。
  • 4)cacheManager: 指定缓存管理器。
  • 5)condition: 指定符合条件的情况下才缓存;如: condition = “#id>0” "#a0>1"才进行缓存。
  • 6)unless: 否定缓存; 当unless指定的条件为true,方法的返回值就不会缓存;如:可以获取到结果进行判断unless = "#result == null " 当方法结果为null时,不缓存。
  • 7)sync: 是否使用异步模式
  • (2) @CacheEvit
  • @CacheEvit:缓存清除
  • @CacheEvit和@Cacheable的相同属性就不再赘述。
  • 1)allEntries = true 每次删除,将指定缓存中的所有数据全都删除。
  • 2)beforeInvocation=false ,缓存的清除是否是在方法之前执行,默认false, 即在方法之后清除,当方法执行出现异常时,缓存不会清除。
  • 3)beforeInvocation=true ,方法之前清除,无论方法执行是否出现异常,缓存都会清除。
  • (3) @CachePut
    运行时机:先调用目标方法,将目标方法的结果缓存起来,属性与@Cacheable相同。
    此外还有@CacheConfig:可以标注在类上,抽取出相同的属性,简化代码。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CacheConfig {
    String[] cacheNames() default {};
    String keyGenerator() default ""; 
    String cacheManager() default ""; 
    String cacheResolver() default "";
}

1.12.3 缓存使用

我们在服务层实现类中增加缓存注解

package com.zone7.demo.helloworld.sys.service.impl;

import com.zone7.demo.helloworld.commons.exception.AddOPException;
import com.zone7.demo.helloworld.commons.exception.DeleteOPException;
import com.zone7.demo.helloworld.commons.exception.UpdateOPException;
import com.zone7.demo.helloworld.sys.dao.SysUserMapper;
import com.zone7.demo.helloworld.sys.pojo.SysUser;
import com.zone7.demo.helloworld.sys.service.SysUserService;
import com.zone7.demo.helloworld.sys.vo.SysUserVo;
import com.zone7.demo.helloworld.utils.MD5Util;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * SysUserServiceImpl
 *
 * @author: zone7
 * @time: 2019.02.17
 */
@Service
@CacheConfig(cacheNames = "users")
public class SysUserServiceImpl implements SysUserService {

    @Value("${system.default.password}")
    private String defaultPassword;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;



    @Override
    @Transactional(rollbackFor = AddOPException.class)
    @CachePut
    public SysUserVo save(SysUserVo userVo) {
        try {


            String password = defaultPassword;
            String md5Password = MD5Util.encode(password);
            SysUser sysUser =  SysUser.builder()
                    .name(userVo.getName()).password(md5Password)
                    .phone(userVo.getPhone())
                    .department(userVo.getDepartment())
                    .build();


            // 存储用户信息
            sysUserMapper.insertSelective(sysUser);

            SysUserVo vo=new SysUserVo();
            BeanUtils.copyProperties(sysUser,vo);

            return vo;

        } catch (Exception e) {

            throw new AddOPException("新增用户操作出错,错误原因: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = UpdateOPException.class)
    @CachePut
    public void update(SysUserVo userVo) {
        try {

            SysUser after = SysUser.builder()
                    .id(userVo.getId())
                    .name(userVo.getName())
                    .phone(userVo.getPhone())
                    .department(userVo.getDepartment()).build();

            sysUserMapper.updateByPrimaryKeySelective(after);

        } catch (Exception e) {

            throw new UpdateOPException("更新用户操作出错,错误原因: " + e.getMessage());
        }
    }

    @Override
    @Cacheable
    public SysUserVo findById(Integer id) {
          SysUser user = sysUserMapper.selectByPrimaryKey(id);
          SysUserVo vo=new SysUserVo();
          BeanUtils.copyProperties(user,vo);
          return vo;
    }


    @Override
    public List<SysUserVo> findByName( String name) {
        List<SysUser> users = sysUserMapper.findByName(name);

        List<SysUserVo> userList = new ArrayList<SysUserVo>();
        users.forEach(sysUser -> {
            // 查询角色信息
            SysUserVo vo=new SysUserVo();
            BeanUtils.copyProperties(sysUser,vo);
            userList.add(vo);
        });
        return userList;
    }

    @Override
    @Transactional(rollbackFor = DeleteOPException.class)
    @CacheEvict
    public void delete(Integer id) {
        try {
            sysUserMapper.deleteByPrimaryKey(id);

        } catch (Exception e) {
            e.printStackTrace();
            throw new DeleteOPException("删除用户操作出错,错误原因: " + e.getMessage());
        }
    }

}

通过Postman测试执行两次findById操作只有第一次进入方法内部执行,后续的执行都直接返回缓存中的数据。

springboot 清除缓存 springboot项目缓存清理_redis