Spring+Mybatis+redis整合(用依赖注入的方式手动修改缓存)

现在开始Spring+mybatis+redis的整合,一开始我想的是Spring+SpringMVC+Mybatis+redis进行整合,但是慢慢整合着就就感觉前面的会了,后面的肯定也就会了,也就不整合后面的了,如果感觉还是很模糊的话,你可以根据下面的慢慢的来整合你肯定会这么觉的

这篇redis不是用注解的方式操作缓存的,用依赖注入的方式,让redis相当于一个数据库(它原本就是一个key-value库),不像用注解的方式完全不用自己管理只需有几个工具类,这里需要自己手动写redis的set,get…,添加生命周期对象转成json字符串也是自己手动解决,当然如果redisDao完善了(命令全了,以后也可以相当于个工具包了)
注解方式请看这:https://blog.csdn.net/weixin_43113679/article/details/90680254

先看看我的目录结构

在这里插入图片描述

首先spring-server.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/tx 
						http://www.springframework.org/schema/tx/spring-tx.xsd
						http://www.springframework.org/schema/context 
						http://www.springframework.org/schema/context/spring-context-4.0.xsd
	">
	<!-- 包扫描 -->
	<context:component-scan base-package="cn.qlq.service"/>
	<!-- 下面这俩import,因为是测试,没办法从web.xml里读取,所以只能写这个,等再加上springmvc时就可以直接让web.xml读取全部的xml了,就不用下面这两个import了 -->
	<import resource="spring-dao.xml"/>
	<import resource="spring-redis.xml"/>
	<!--配置事务管理器 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
		
	</bean>
	<!-- 配置注解的事务驱动 -->
	<tx:annotation-driven transaction-manager="txManager"/>	
	
</beans>

spring-dao.xml和它的配置文件conn.properties

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/context 
						http://www.springframework.org/schema/context/spring-context-4.0.xsd
						http://www.springframework.org/schema/tx
						http://www.springframework.org/schema/tx/spring-tx.xsd
						http://www.springframework.org/schema/aop
						http://www.springframework.org/schema/aop/spring-aop.xsd
	">
	
	<!-- property-placeholder用于加载一个属性文件 -->
	<!-- ignore-unresolvable="true"  必须加上,要不肯定出错,错误应该是没有找到配置文件,如果不加上,它就会只读一个,剩下的不会读按顺序 -->
	<context:property-placeholder location="classpath:conn.properties" ignore-unresolvable="true"/>
	
	<!-- c3p0数据库连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" 
		p:driverClass="${jdbc.driver}" p:jdbcUrl="${jdbc.url}"
		p:user="${jdbc.username}" p:password="${jdbc.password}"
		p:maxPoolSize="100" p:minPoolSize="20"
		p:initialPoolSize="20" p:maxIdleTime="200" >
		</bean>

	
	<!-- sqlSessionFactory工厂bean -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	     <!-- 数据库连接池,ref和上面的数据库连接池的id对应 -->
	     <property name="dataSource" ref="dataSource" />
	     <!-- 加载mybatis的全局配置文件 -->
	     <property name="configLocation" value="classpath:sqlMapConfig.xml" />
	</bean>											
	
	<!-- 配置MyBatis的高级mapper代理方式 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- 扫描包路径,如果需要扫描多个包,中间使用半角逗号隔开 -->
		<property name="basePackage" value="cn.qlq.mapper"></property>
		
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
	
	</bean>
 

</beans>

conn.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/qbb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
jdbc.username=root
jdbc.password=

sqlMapConfig

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
					"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- MyBatis的全局参数设置,基本用来进行MyBatis的优化处理 -->
	<settings>
	  <!-- 开启二级缓存 -->
 
      <setting name="cacheEnabled" value="true"/>
   
    
		<!-- 下面的是延迟加载 -->
		<setting name="lazyLoadingEnabled" value="true"/>
		<!-- 是否开启延迟加载 -->
		<setting name="aggressiveLazyLoading" value="false"/>
		<!-- 缓冲加载 -->
		<setting name="cacheEnabled" value="true"/>
	</settings>
	
	<typeAliases>
		<!--肯定要有这个的啦,要不怎么从mybatis中返回自己想要的对象呢-->
		<package name="cn.qlq.bean"/>
	</typeAliases>
	
</configuration>

spring-redis.xml和它的配置文件redis.properties

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/context 
						http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 
	<!-- 连接池配置 -->
	<context:component-scan base-package="cn.qlq.Redis"/>
	<!--ignore-unresolvable必须写上true,要不配置文件就读不上了,当然,也可以全读,我这为了区分,分开读的-->
	<context:property-placeholder location="classpath:redis.properties" ignore-unresolvable="true"/>
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
	<!--下面这些可以用配置文件里也可以自己定义,在你,value格式和下一个bean一样-->
		<!-- 最大连接数 -->
		<property name="maxTotal" value="30" />
		<!-- 最大空闲连接数 -->
		<property name="maxIdle" value="10" />
		<!-- 每次释放连接的最大数目 -->
		<property name="numTestsPerEvictionRun" value="1024" />
		<!-- 释放连接的扫描间隔(毫秒) -->
		<property name="timeBetweenEvictionRunsMillis" value="30000" />
		<!-- 连接最小空闲时间 -->
		<property name="minEvictableIdleTimeMillis" value="1800000" />
		<!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
		<property name="softMinEvictableIdleTimeMillis" value="10000" />
		<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
		<property name="maxWaitMillis" value="1500" />
		<!-- 在获取连接的时候检查有效性, 默认false -->
		<property name="testOnBorrow" value="true" />
		<!-- 在空闲时检查有效性, 默认false -->
		<property name="testWhileIdle" value="true" />
		<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
		<property name="blockWhenExhausted" value="false" />
	</bean>	
	
	<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
		<constructor-arg name="host" value="${redis.url}"></constructor-arg>
		<constructor-arg name="port" value="${redis.port}"></constructor-arg>
		<constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
	</bean>
</beans>

redis.properties

redis.url="ip地址" //自己查自己的
redis.port=6379
redis.pass=
redis.maxIdle=300
redis.maxTotal=30
redis.maxActive=1024
redis.maxWait=10000
redis.testOnBorrow=true

pom.xml

除了SSM中必须有的jar包外下面的也要有

<!--redis必须有的jar包-->
<dependency>
	    <groupId>org.springframework.data</groupId>
	    <artifactId>spring-data-redis</artifactId>
	    <version>1.8.10.RELEASE</version>
	</dependency>
  	<dependency>
	    <groupId>redis.clients</groupId>
	    <artifactId>jedis</artifactId>
	    <version>2.9.0</version>
	</dependency>
	<!--负责json字符串和javabean对象之间的互转换-->
	 <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.56</version>
	</dependency>

User类

package cn.qlq.bean;


public class User {

	private int id;
	private String name;
	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;
	}
	
	
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + "]";
	}
	
	
}

Mapper类(数据库类)

接口

package cn.qlq.mapper;

import java.util.List;
import org.apache.ibatis.annotations.Param;
import cn.qlq.bean.User;

public interface UserMapper {

	/**
	 * 获得所有的用户
	 * */
	List<User> getUser()throws Exception;
	/**
	 * 插入一个用户
	 * */
	void insertUser(@Param("user")User user)throws Exception;
	/**
	 * 通过id查询用户
	 * 
	 * @param id
	 * @return
	 */
	User findUserById(@Param("id")int id);

}

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">

<!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 注意:使用mapper代理方法开发,namespace有特殊重要的作用 -->
<mapper namespace="cn.qlq.mapper.UserMapper">
     <select id="getUser"  resultType="cn.qlq.bean.User">
        select * from book
    </select>
	<update id="insertUser" parameterType="cn.qlq.bean.User">
		INSERT INTO book (id,name) VALUES (#{user.id},#{user.name})
	
	</update>
    <select id="findUserById" parameterType="int" resultType="cn.qlq.bean.User">
        select * from book where id = #{id}
    </select>
</mapper>

缓存类

接口

/**
 * 
 */
package cn.qlq.Redis;

/**
 * @author 作者
 * @date 2019年5月21日 
 */
public interface RedisDao {
	/**
	 * show 获得缓存中的value
	 * */
	String get(String key) throws Exception;
	/**
	 * show 往缓存中添加value
	 * */
	void set(String key,String value) throws Exception;
	/**
	 * show 获取hash
	 * */
	String hget(String hkey,String key) throws Exception;
	/**
	 * show 插入一个hash
	 * */
	void hset(String hkey,String key,String value)throws Exception;

	
}

实现类

package cn.qlq.Redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import redis.clients.jedis.JedisPool;

/**
 * @author 作者
 * @date 2019年5月21日 
 */
@Repository("redisDao")
public class RedisDaoImpl implements RedisDao{
	@Autowired
	private JedisPool jedisPool ;

	@Override
	public String get(String key) throws Exception {
		
		return jedisPool.getResource().get(key);
	}

	@Override
	public void set(String key,String value) throws Exception {
		//获得6小时到9小时的随机时间
		int time=(int)(6+Math.random()*(4))*60*60;
		//添加键
		 jedisPool.getResource().set(key, value);
		 //给键添加生命周期
		 jedisPool.getResource().expire(key, time);
	}

	@Override
	public String hget(String hkey, String key) throws Exception {
		
		return jedisPool.getResource().hget(hkey, key);
	}

	@Override
	public void hset(String hkey, String key,String value) throws Exception {
		int time=(int)(6+Math.random()*(4))*60*60;
		 jedisPool.getResource().hset(hkey, key,value);
		 jedisPool.getResource().expire(key, time);
	}


}

Server类

接口

package cn.qlq.service;
import java.util.List;
import cn.qlq.bean.User;

public interface UserService {
	/**
	 * show 获取所有的User
	 * */
	List<User> getUser()throws Exception;
	/**
	 * show 插入新的User
	 * */
	void insertUser(User user)throws Exception;
	
	
	/**
	 * 通过id查询用户
	 * 
	 * @param id
	 * @return
	 * @throws Exception
	 */
	 User findUserById(int id) throws Exception;
	
	
}

实现类

package cn.qlq.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import com.alibaba.fastjson.JSON;
import cn.qlq.Redis.RedisDao;
import cn.qlq.bean.User;
import cn.qlq.mapper.UserMapper;
import cn.qlq.service.UserService;
@Transactional(rollbackFor=Exception.class)
@Service("userService")
public class UserServiceImpl implements UserService {

	@Autowired
	private UserMapper userMapper=null;
	@Autowired
	private RedisDao redisDao =null;
	@Override
	public List<User> getUser() throws Exception {
		
		return userMapper.getUser();
	}

	@Override
	public void insertUser(User user) throws Exception {
		userMapper.insertUser(user);
		String userJson = redisDao.get("user_"+user.getId());
		if(StringUtils.isEmpty(userJson)) {
			System.out.println("插入缓存");
			//因为是缓存中存的是字符串,所以需要转成json字符串
			redisDao.set("user_"+user.getId(), JSON.toJSONString(user));	
		}
		//还需要插入数据库中,没写,自己写
	}
	
	@Override
	public User findUserById(int id) throws Exception {
		String userjson = redisDao.get("user_"+id);
		User user =null;
		//判断缓存中存在对应的id的
		if(StringUtils.isEmpty(userjson)) {
			//不存在去数据库中取出,再放进缓存
			user = userMapper.findUserById(id);
			if(user != null) {
				redisDao.set("user_"+id, JSON.toJSONString(user));	
			}else {
				//数据库中也不存在就把这个id也存进缓存中标识,防止雪崩或者穿透
			}
		}else {
			//存在就直接把缓存里的json拿出来转换成对象
			System.out.println("从缓存拿是数据,不去数据库");
			user = JSON.parseObject(userjson,User.class);
		}
		return user;
	}
}

是面关于fastjson的转换字符串和对象不明白的可以参考https://segmentfault.com/a/1190000011212806

测试类


package text;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.qlq.bean.User;
import cn.qlq.service.UserService;


public class ssmTest {
	@Autowired
	 private ApplicationContext ctx = null;
	 @Autowired
     private UserService userService = null;
	 
   
     @Test	
 	public void testGetUsers() throws Exception{
    	 ctx = new ClassPathXmlApplicationContext("spring-service.xml");
         userService = ctx.getBean(UserService.class);
 		List<User> users = userService.getUser();
 		System.out.println(users);
 	}
 	
 	@Test
 	public void testInsertUser() throws Exception{
 		ctx = new ClassPathXmlApplicationContext("spring-service.xml");
        userService = ctx.getBean(UserService.class);
 		User user = new User();
 		user.setId(9);
 		user.setName("第一个");
 		
 		userService.insertUser(user);
 	}
 	
 	@Test
 	public void testGetUserById() throws Exception{
 		ctx = new ClassPathXmlApplicationContext("spring-service.xml");
        userService = ctx.getBean(UserService.class);
 		System.out.println(userService.findUserById(9));
 		
 	}




}

结果
第二个Test
在这里插入图片描述
在这里插入图片描述
第三个Test
在这里插入图片描述
没有经过数据库,直接进的缓存拿的数据,完成。

©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页