您的位置:首页 > 数据库 > Redis

spring boot + mysql +mybatis +redis(二级缓存)实例

2017-12-14 15:01 1146 查看
配置了好几天才算配置好

个人感觉spring boot版本间兼容不好

一、创建maven项目并添加 pom 依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>1</groupId>
<artifactId>1</artifactId>
<version>1.0-SNAPSHOT</version>

<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<!--项目编码格式以及JDK版本指定-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<!-- Add typical dependencies for a web application -->

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<!--alibaba.fastjson-->
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.41</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->

//spring 包 很容易与spring boot 版本冲突 注意
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>


二、yml 配置文件

################################
######                     #####
######     应用通用配置     #####
######                     #####
################################

spring:
# 应用名称
application:
name: MavenDemoProject

# 多环境配置
profiles:
active: dev

# http请求编码配置
http:
encoding:
charset: UTF-8
force: true
enabled: true

# mysql数据库配置
datasource:
#    type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
#url,username,password动态配置
url: jdbc:mysql://localhost:3306/test?useUnicode:true&characterEncoding:utf-8
username: root
password: ****
dbcp2:
#最大空闲连接
max-idle: 100
#最小空闲连接
min-idle: 10
#最大连接数
max-total: 200
#最大等待时间
max-wait-millis: 5000
#检测周期 单位毫秒
time-between-eviction-runs-millis: 30000
#连接池足校生存时间
min-evictable-idle-time-millis: 1800000
#       test-on-borrow: true
#       validation-query: SELECT 1
#       test-while-idle: true
#       num-tests-per-eviction-run: 100

# redis缓存配置
redis:
#host,password,port,database动态配置
host: *******
password: *****
port: 6379
database: 0
timeout: 2000
pool:
# 连接池中的最大空闲连接
max-idle: 80
# 连接池中的最小空闲连接
min-idle: 1
# 连接池最大连接数(使用负值表示没有限制)
max-active: 80
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: 10

# mybatis配置
mybatis:
#config-location: classpath:/mybatis-config.xml
type-aliases-package: com.frank.dao.*
mapper-locations: classpath:/mapper/*.xml
#  configuration:
#    #延时加载
#    lazy-loading-enabled: true
#    map-underscore-to-camel-case: true
#    use-column-label: true


需要在mapper xml 文件中声明二级缓存 如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.weixin.dao.student.StudentMapper">
<!--开启二级缓存-->
<cache type="com.weixin.config.RedisConfig"/>
<select id="get" resultType="com.weixin.model.Student">

SELECT * FROM student

WHERE id = #{id}

</select>

<update id="update" parameterType="com.weixin.model.Student">

UPDATE student SET

name = #{name},

age = #{age}

WHERE id = #{id}

</update>

</mapper>


bean类型 需要实现Serializable接口

package com.weixin.model;

import java.io.Serializable;

public class Student implements Serializable {
private int id;
private String name;
private int age;

public int getId() {
return id;
}

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

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

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

public int getAge() {
return age;
}
}


三、Redis 配置类

package com.weixin.config;

import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class RedisConfig implements Cache {
private static final Logger logger = org.slf4j.LoggerFactory.getLogger(RedisConfig.class);

private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private  String id; // cache instance id
private RedisTemplate redisTemplate;
private static final long EXPIRE_TIME_IN_MINUTES = 30; // redis过期时间
private static final String DEFAULT_ID = "default_id";

public RedisConfig(String id) {
if (id == null) {
id = DEFAULT_ID;
}
this.id = id;
}

public void setId(String id ){

this.id = id;
}
@Override
public String getId() {
return id;
}

/**
* Put query result to redis
*
* @param key
* @param value
*/
@Override
@SuppressWarnings("unchecked")
public void putObject(Object key, Object value) {
try {
RedisTemplate redisTemplate = getRedisTemplate();
ValueOperations opsForValue = redisTemplate.opsForValue();
opsForValue.set(key, value, EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);
logger.debug("Put query result to redis");
} catch (Throwable t) {
logger.error("Redis put failed", t);
}
}

/**
* Get cached query result from redis
*
* @param key
* @return
*/
@Override
public Object getObject(Object key) {
try {
RedisTemplate redisTemplate = getRedisTemplate();
ValueOperations opsForValue = redisTemplate.opsForValue();
logger.debug("Get cached query result from redis");
return opsForValue.get(key);
} catch (Throwable t) {
logger.error("Redis get failed, fail over to db", t);
return null;
}
}

/**
* Remove cached query result from redis
*
* @param key
* @return
*/
@Override
@SuppressWarnings("unchecked")
public Object removeObject(Object key) {
try {
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.delete(key);
logger.debug("Remove cached query result from redis");
} catch (Throwable t) {
logger.error("Redis remove failed", t);
}
return null;
}

/**
* Clears this cache instance
*/
@Override
public void clear() {
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.execute((RedisCallback) connection -> {
connection.flushDb();
return null;
});
logger.debug("Clear all the cached query result from redis");
}

/**
* This method is not used
*
* @return
*/
@Override
public int getSize() {
return 0;
}

@Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
}

private RedisTemplate getRedisTemplate() {
if (redisTemplate == null) {
redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
}
//spring-data-redis的RedisTemplate<K, V>模板类在操作redis时默认使用JdkSerializationRedisSerializer来进行序列化
//一下修改为String类型序列化 解决redis库中 K V 出现 xAC\xED\x00\x05t\x00\x04 问题
RedisSerializer stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
//        redisTemplate.setValueSerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
//        redisTemplate.setHashValueSerializer(stringSerializer);

return redisTemplate;
}
}


ApplicationContextHolder 类

package com.weixin.config;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
applicationContext = ctx;
}

/**
* Get application context from everywhere
*
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}

/**
* Get bean by class
*
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}

/**
* Get bean by class name
*
* @param name
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
}


上面需要用到spring-context jar 包,需要注意版本,版本不同可能冲突

注意:

RedisSerializer stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
//        redisTemplate.setValueSerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
//        redisTemplate.setHashValueSerializer(stringSerializer);


上面表示redis中的key值设置为String类型,这样能更清楚的找到key值,但是如果开启二级缓存的话,执行sql语句时查找的对象不会进行redis存储,因为查找到对象key为Object值,控制台会报错,如图



可以改成 key.toString() 进行存储,但是出现文件分级,如图:



所以说还要按照实际情况进行设置

四、controller层进行使用

package com.weixin.controller;

import com.alibaba.fastjson.JSONObject;
import com.weixin.config.RedisConfig;
import com.weixin.model.Student;
import com.weixin.service.student.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class SpringBootTest {

@Autowired
private StudentService studentService;

@RequestMapping("/one")
public JSONObject test() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", "success");
//id 没有实际价值 只是为了更好确认
RedisConfig redisConfig = new RedisConfig("100");
redisConfig.putObject("1000","hello i m frank!");

return jsonObject;
}

/**
* 根据id获取对象
*
* @param id
* @return
*/
@GetMapping("/{id}")
public JSONObject get(@PathVariable("id") int id) {

Student student = studentService.get(id);
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", student.getId());
jsonObject.put("age", student.getAge());
jsonObject.put("name", student.getName());
RedisConfig redisConfig = new RedisConfig("100");
redisConfig.putObject("frank",jsonObject);
return jsonObject;

}

/**
* 更新对象
*
* @return
*/
@RequestMapping("/update")
public String put() {

Student student = new Student();
student.setId(1);
student.setAge(22);
student.setName("new frank");
studentService.update(student);

return "success";

}

@RequestMapping("/getRedis")

public JSONObject get() {

RedisConfig redisConfig = new RedisConfig("100");

return  (JSONObject) redisConfig.getObject("frank");

}
}


五、运行查看



查看redis



添加JSON value 值



显示情况



如果想显示String的话 可以在RedisConfig中 setValueSerializer 进行设置

获取value值



五、项目总体结构



项目下载

http://download.csdn.net/download/jasonhector/10158450
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息