Springboot+mysql+mybatis+druid+redis实现数据库缓存实战

首先我们需要引入依赖


			org.springframework.boot
			spring-boot-starter-web
		
		
			org.mybatis.spring.boot
			mybatis-spring-boot-starter
			2.0.1
		

		
			mysql
			mysql-connector-java
			runtime
		
		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
		    org.springframework.boot
		    spring-boot-starter-data-redis
		    2.1.6.RELEASE
		
		
		    org.mybatis.spring.boot
		    mybatis-spring-boot-starter
		    2.0.0
		
		
		    com.alibaba
		    fastjson
		    1.2.57
		
		
		    com.fasterxml.jackson.core
		    jackson-databind
		    2.9.2
		
		
		    org.springframework.boot
		    spring-boot-devtools
		    true
		    
		
		    com.alibaba
		    druid-spring-boot-starter
		    1.1.16
		

将上述依赖引入后,我们需要编写配置文件

#服务启动的端口号(用Tomcat运行时无效)
server.port=8082
#项目的部署名称(用Tomcat运行时无效)
server.servlet.context-path=/SpringTemplate

#数据库相关配置
spring.datasource.driver-class-name =com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mytest?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=jack
spring.datasource.password=liuhong987
#如果不使用默认的数据库连接池 (com.zaxxer.hikari.HikariDataSource)
spring.datasource.type =com.alibaba.druid.pool.DruidDataSource
#配置druid连接池时用一下配置
spring.datasource.druid.initial-size=10
spring.datasource.druid.max-active=50
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-wait=60000

#mybatis 下划线转驼峰配置,两者都可以(在执行查询时将查询结果自动转换成对象)
#mybatis.configuration.mapUnderscoreToCamelCase=true
mybatis.configuration.map-underscore-to-camel-case=true
#xml文件存放位置
mybatis.mapper-locations=classpath:com/springboot/mapper/*.xml
#xml对应接口所在包名
mybatis.type-aliases-package=com.springboot.dao
#打印sql,方便调试
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

#Redis的主机名
spring.redis.host=127.0.0.1
# 使用的数据库(0-15),默认为0
spring.redis.database=0
#redis服务器密码
spring.redis.password=
#redis的端口号
spring.redis.port=6379 
spring.redis.ssl=false
#Redis连接超时
spring.redis.timeout=2000
spring.redis.jedis.pool.max-active=80
spring.redis.jedis.pool.max-idle=50
spring.redis.jedis.pool.max-wait=200ms
spring.redis.jedis.pool.min-idle=0

将上述步骤完成后,我们就需要开始编写Redis的配置类了

@Configuration
@EnableCaching
public class RedieConfig  extends CachingConfigurerSupport {
	@Bean(name="redisTemplate")
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
		RedisTemplate template = new RedisTemplate();
		template.setConnectionFactory(factory);
		setSerializer(template);
        return template;
    }
	@Bean(name="redisCacheManager")
    public CacheManager cacheManager(RedisConnectionFactory factory) {
		        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(factory);
		        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);//JSONObject
		        RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer);
		        RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
		        defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofSeconds(100));//设置过期时间
		        RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
		        ParserConfig.getGlobalInstance().addAccept("zmc.leon.mcd.entity.");
		        ParserConfig.getGlobalInstance().setAutoTypeSupport(true); 
		        return cacheManager;
    }
	
	/**
	 * 利用fastjson将转为json字符串
	 * @param template
	 */
	private void setSerializer(RedisTemplate template) {
        @SuppressWarnings({"rawtypes", "unchecked"})
        FastJsonRedisSerializer fastJsonRedisSerializer =new FastJsonRedisSerializer(Object.class);
        template.setValueSerializer(fastJsonRedisSerializer);
        template.setHashValueSerializer(fastJsonRedisSerializer);
        // key的序列化采用StringRedisSerializer
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
    }
	 /**
     * 自定义生成key的规则
     *
     * @return
     */
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object o, Method method, Object... objects) {
                //格式化缓存key字符串
                StringBuilder sb = new StringBuilder();
                //追加类名
                sb.append(o.getClass().getName()).append(".");
                //追加方法名
                sb.append(method.getName());
                //遍历参数并且追加
                for (Object obj : objects) {
                    sb.append(".");
                    sb.append(obj.toString());
                }
                System.out.println("调用Redis缓存Key : " + sb.toString());
                return sb.toString();
            }
        };
    }
} 
  

注意我们这里使用的是redis的String类型作为缓存,使用fastjson将缓存数据转为json字符串进行缓存。

还要注意一个问题,我们这里必须自定义fastjson的的序列化类。否则会出现异常,下面是自定义的fastjson序列化的类。

在redis的配置类中一定要引入自定义的FastJsonRedisSerializer类,而不是自带的序列化类

public class FastJsonRedisSerializer implements RedisSerializer {
    private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    private Class clazz;
    public FastJsonRedisSerializer(Class clazz) {
        super();
        this.clazz = clazz;
    }
 
    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (null == t) {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }
 
    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (null == bytes || bytes.length <= 0) {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);
        return (T) JSON.parseObject(str, clazz);
    }
}

到这里, 我们已经基本构建完的Redis的环境,下面我们就要结合mybatis来使用它作为数据库缓存

首先我们来看一下建一个简单表测试下,下面是SQL语句

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` bigint(32) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `sex` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 10009 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

下面我么使用自动生成代码工具generator来生成xml,实体类文件、以及接口文件

实体类文件

package com.springboot.domain;

public class User {
    private Long id;

    private String username;

    private String sex;

    private Integer age;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username == null ? null : username.trim();
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex == null ? null : sex.trim();
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

XML文件




  
    
    
    
    
  
  
    id, username, sex, age
  
  
  
  
  
  
    delete from user
    where id = #{id,jdbcType=BIGINT}
  
  
  
    SELECT LAST_INSERT_ID()
  
    insert into user (id, username, sex, 
      age)
    values (#{id,jdbcType=BIGINT}, #{username,jdbcType=VARCHAR}, #{sex,jdbcType=VARCHAR}, 
      #{age,jdbcType=INTEGER})
  
  
  
    insert into user
    
      
        id,
      
      
        username,
      
      
        sex,
      
      
        age,
      
    
    
      
        #{id,jdbcType=BIGINT},
      
      
        #{username,jdbcType=VARCHAR},
      
      
        #{sex,jdbcType=VARCHAR},
      
      
        #{age,jdbcType=INTEGER},
      
    
  
  
    update user
    
      
        username = #{username,jdbcType=VARCHAR},
      
      
        sex = #{sex,jdbcType=VARCHAR},
      
      
        age = #{age,jdbcType=INTEGER},
      
    
    where id = #{id,jdbcType=BIGINT}
  
  
    update user
    set username = #{username,jdbcType=VARCHAR},
      sex = #{sex,jdbcType=VARCHAR},
      age = #{age,jdbcType=INTEGER}
    where id = #{id,jdbcType=BIGINT}
  

接口类文件

public interface UserMapper {
    int deleteByPrimaryKey(Long id);
    int insert(User record);
    int insertSelective(User record);
    List selectList();
    User selectByPrimaryKey(Long id);

    int updateByPrimaryKeySelective(User record);

    int updateByPrimaryKey(User record);
}

service层文件

@Service
@CacheConfig(cacheNames = "user")
public class UserService {
	@Autowired
	private UserMapper userMapper;
    @Cacheable(key="#id")
	public User findById(String id) {
		// TODO Auto-generated method stub
		return userMapper.selectByPrimaryKey(Long.parseLong(id));
	}
    @Cacheable(key ="'userList'+#accountId")
	public Object selectList(String accountId) {
		// TODO Auto-generated method stub
		return userMapper.selectList();
	}
	@CachePut(key = "#user.id")
	public Object saveUser(User user) {
		// TODO Auto-generated method stub
		return userMapper.insert(user);
	}
	@CachePut(key = "#user.id")
	public Object updateUser(User user) {
		// TODO Auto-generated method stub
		return userMapper.updateByPrimaryKey(user);
	}
	@CacheEvict(key ="#id")
	public Object deleteById(String id) {
		// TODO Auto-generated method stub
		return userMapper.deleteByPrimaryKey(Long.parseLong(id));
	}
}

我们使用redis作为缓存是在service层加注解实现的

@CacheConfig(cacheNames = "user")  这个是我定义缓存的名字,原则上是必须的

@Cacheable(key ="'userList'+#accountId")  这个是在在查询时使用的缓存注解,一定要定义key值,唯一的。

@CachePut(key = "#user.id")  在实现增加和修改功能时使用该缓存注解

 @CachePut(key = "#user.id") 在实现删除功能时,使用该缓存注解

下面我们继续实现controller层

@RestController
@RequestMapping("/user/v1/")
public class UserController {
	@Autowired
	private UserService userService;
	
	@RequestMapping("findById")
	public Object  findById(String id) {
		 return  userService.findById(id);	
	}
	@RequestMapping("list")
	public Object  selectList(String accountId) {
		 return  userService.selectList(accountId);	
	}
	
	@RequestMapping("deleteById")
	public Object  deleteById(String id) {
		 return  userService.deleteById(id);	
	}
	
	@RequestMapping("save")
	public Object  saveUser(@RequestBody User user) {
		 return  userService.saveUser(user);	
	}
	
	@RequestMapping("update")
	public Object  updateUser(@RequestBody User user) {
		 return  userService.updateUser(user);	
	}
}

接下来启动类也是非常关键的

@SpringBootApplication
@MapperScan("com.springboot.dao")
//@EnableCaching   //当redis的配置类里面未开启缓存功能,则此处必须开启此注解。
public class ApplicationBoot {
	public static void main(String[] args) {
		SpringApplication.run(ApplicationBoot.class, args);
		
	}

}

以上过程利用redis实现的数据库简单的数据缓存功能。

你可能感兴趣的:(数据库相关,Redis,redis实现缓存)