環境:項目採用springMvc+spring4.25+hibernate5.08+Mysql
目的:將Redis作爲緩存數據庫,具體Redis的優勢網上都有,就不在贅述了。
1.所需jar包
除了spring以及與hibnenate 相關的依賴包外 spring-data-redis-1.7.2.RELEASE.jar jedis-2.9.0.jar
commons-pool2-2.5.0.jar redis配置線程池
2.配置文件
springMVC.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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!-- 啓用spring mvc 註解 -->
<!-- 掃描註解 -->
<context:component-scan base-package="com.fh.panghu.controller"/>
<mvc:annotation-driven />
<bean id="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
<!-- 靜態資源(js/image)的訪問 ,可添加多個-->
<mvc:resources location="/views/images/" mapping="/views/images/**"/>
<mvc:resources location="/views/js/" mapping="/views/js/**"/>
<mvc:resources location="/views/css/" mapping="/views/css/**"/>
<!-- 定義跳轉的文件的前後綴 ,視圖模式配置 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 這裏的配置自動給後面action的方法return的字符串加上前綴和後綴,變成一個 可用的url地址 -->
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/views/" />
<property name="suffix" value=".html" />
</bean>
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.Throwable">error</prop>
</props>
</property>
</bean>
<!-- 配置文件上傳,如果沒有使用文件上傳可以不用配置,當然如果不配,那麼配置文件中也不必引入上傳組件包 -->
<bean name="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 默認編碼 -->
<property name="defaultEncoding" value="utf-8" />
<!-- 文件大小最大值 -->
<property name="maxUploadSize" value="10485760000" />
<!-- 內存中的最大值 -->
<property name="maxInMemorySize" value="40960" />
</bean>
</beans>
springCore2.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-4.0.xsd">
<context:component-scan base-package="com.fh.panghu.service" />
<cache:annotation-driven />
<task:annotation-driven/>
<context:annotation-config/>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<context:component-scan base-package="com.fh.panghu.schedule"/>
<!-- 屬性文件位置 -->
<!-- 公共配置文件信息 -->
<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:public.properties</value>
</list>
</property>
</bean>
<!-- 讀取數據庫信息 -->
<bean id="annotationPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<value>classpath:redis.properties</value>
</list>
</property>
</bean>
<!-- 配置線程池 -->
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="keepAliveSeconds" value="200" />
<property name="maxPoolSize" value="10" />
<property name="queueCapacity" value="20" />
<property name="rejectedExecutionHandler">
<bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
</property>
</bean>
<!-- 配置數據源 c3p0 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- 請求超時時間 -->
<property name="checkoutTimeout" value="30000" />
<!-- 每60秒檢查所有連接池中的空閒連接。默認值: 0,不檢查 -->
<property name="idleConnectionTestPeriod" value="30" />
<!-- 連接數據庫連接池最大空閒時間 -->
<property name="maxIdleTime" value="30" />
<!-- 連接池初始化連接數 -->
<property name="initialPoolSize" value="5" />
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<!--當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數。默認值: 3 -->
<property name="acquireIncrement" value="5" />
</bean>
<!-- 配置hibernate的SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 注入數據源 相關信息看源碼 -->
<property name="dataSource" ref="dataSource" />
<!-- hibernate配置信息 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<!-- 開啓二級緩存 ehcache -->
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">${hibernate.cache.provider_configuration_file_resource_path}
</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
</props>
</property>
<!-- 掃描hibernate註解配置的entity -->
<property name="packagesToScan" value="com.fh.panghu.entity" />
</bean>
<!-- 配置事務管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Spring aop事務管理 -->
<aop:config proxy-target-class="true">
<aop:advisor pointcut="execution(* com.fh.panghu.service.*.*(..))" advice-ref="transactionAdvice" />
</aop:config>
<!-- 配置事務增強處理Bean,指定事務管理器 -->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<!-- 配置詳細事務處理語義 -->
<tx:attributes>
<tx:method name="query*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="load*" read-only="true" />
<tx:method name="list*" read-only="true" />
<tx:method name="save*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
<tx:method name="update*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
<tx:method name="del*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
<tx:method name="create*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
<tx:method name="*" rollback-for="Exception"/>
</tx:attributes>
</tx:advice>
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean name="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- redis連接池配置-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" >
<!--最大空閒數-->
<property name="maxIdle" value="${redis.maxIdle}" />
<!--連接池的最大數據庫連接數 -->
<property name="maxTotal" value="${redis.maxTotal}" />
<!--最大建立連接等待時間-->
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<!--逐出連接的最小空閒時間 默認1800000毫秒(30分鐘)-->
<property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}" />
<!--每次逐出檢查時 逐出的最大數目 如果爲負數就是 : 1/abs(n), 默認3-->
<property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}" />
<!--逐出掃描的時間間隔(毫秒) 如果爲負數,則不運行逐出線程, 默認-1-->
<property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}" />
<!--是否在從池中取出連接前進行檢驗,如果檢驗失敗,則從池中去除連接並嘗試取出另一個-->
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
<!--在空閒時檢查有效性, 默認false -->
<property name="testWhileIdle" value="${redis.testWhileIdle}" />
</bean >
<!--redis連接工廠 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
<property name="poolConfig" ref="jedisPoolConfig"></property>
<!--IP地址 -->
<property name="hostName" value="${redis.hostName}"></property>
<!--端口號 -->
<property name="port" value="${redis.port}"></property>
<!--如果Redis設置有密碼 -->
<property name="password" value="${redis.password}" />
<!--客戶端超時時間單位是毫秒 -->
<property name="timeout" value="${redis.timeout}"></property>
</bean>
<!--redis操作模版,使用該對象可以操作redis -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >
<property name="connectionFactory" ref="jedisConnectionFactory" />
<!--如果不配置Serializer,那麼存儲的時候缺省使用String,如果用User類型存儲,那麼會提示錯誤User can't cast to String!! -->
<property name="keySerializer" >
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer" >
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" />
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
</property>
<!--開啓事務 -->
<property name="enableTransactionSupport" value="true"></property>
</bean >
<!-- 配置緩存 -->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg ref="redisTemplate" />
</bean>
</beans>
redis.properties
redis.hostName=127.0.0.1
redis.port=6379
redis.password=
redis.timeout=10000
redis.maxIdle=300
redis.maxTotal=1000
redis.maxWaitMillis=1000
redis.minEvictableIdleTimeMillis=300000
redis.numTestsPerEvictionRun=1024
redis.timeBetweenEvictionRunsMillis=30000
redis.testOnBorrow=true
redis.testWhileIdle=true
3.實現代碼
RedisCacheUser.java 實體類 對應Mysql字段
@Entity
@Table(name="rediscacheuser")
public class RedisCacheUser {
//用戶ID
private String redisuserid;
//名字
private String redisusername;
//密碼
private String redispassword;
//ID
private String redisddid;
//用戶電話
private String redismobile;
public RedisCacheUser(){
}
@Id
public String getUserid() {
return redisuserid;
}
public void setUserid(String userid) {
this. redisuserid = userid;
}
@Column(name="USERNAME",nullable=false,length=32)
public String getUsername() {
return redisusername;
}
public void setUsername(String username) {
this. redisusername = username;
}
@Column(name="PASSWORD",nullable=false,length=64)
public String getPassword() {
return redispassword;
}
public void setPassword(String password) {
this. redispassword = password;
}
@Column(name="DDID",nullable=false,length=128)
public String getDdid() {
return redisddid;
}
public void setDdid(String ddid) {
this.redisddid = ddid;
}
@Column(name="MOBILE",length=32)
public String getMobile() {
return redismobile;
}
public void setMobile(String mobile) {
this.redismobile = mobile;
}
@Override
public String toString() {
return "RedisCacheUser [redisuserid=" + redisuserid + ", redisusername=" + redisusername + ", redispassword="
+ redispassword + ", redisddid=" + redisddid + ", redismobile=" + redismobile + ", getUserid()="
+ getUserid() + ", getUsername()=" + getUsername() + ", getPassword()=" + getPassword() + ", getDdid()="
+ getDdid() + ", getMobile()=" + getMobile() + ", getClass()=" + getClass() + ", hashCode()="
+ hashCode() + ", toString()=" + super.toString() + "]";
}
}
RedisCacheTestService.java BaseTxService 裏面封裝了hibernate操作 可以通過hibernateTemplate操作Mysql
@Service
public class RedisCacheTestService extends BaseTxService {
@CachePut(key="#redisCacheUser.getUserid()",value="RedisCacheUser")
public String addRedisCacheTestUser(RedisCacheUser redisCacheUser) {
this.hibernateTemplate.save(redisCacheUser);
return JSONObject.fromObject(redisCacheUser).toString();
}
@CachePut(key="#redisCacheUser.getUserid()",value="RedisCacheUser")
public RedisCacheUser addRedisCacheTestUser1(RedisCacheUser redisCacheUser) {
this.hibernateTemplate.save(redisCacheUser);
return redisCacheUser;
}
/**
* 根據userId查詢對象 先從緩存 沒有則再數據庫
* @param userId
* @return
*/
@Cacheable(key="#userId",value="RedisCacheUser")
@SuppressWarnings("unchecked")
public String getRedisCacheUserByuserId(String userId) {
String string = getRedisCacheUserByuserIdDB(userId);
return string;
}
public String getRedisCacheUserByuserIdDB(String userId) {
List <RedisCacheUser> redisCacheUsers = new ArrayList <RedisCacheUser>() ;
RedisCacheUser redisCacheUser = new RedisCacheUser() ;
redisCacheUsers = (List<RedisCacheUser>) this.hibernateTemplate.find("from RedisCacheUser where userid = '" + userId + "'");
if(redisCacheUsers.size()>0) {
redisCacheUser = redisCacheUsers.get(0);
return JSONObject.fromObject(redisCacheUser).toString();
}
return null;
}
/**
* 根據userName模糊查詢多個對象 先從緩存 沒有則再數據庫
* @param userId
* @return
*/
/*@Cacheable(key="#username",value="RedisCacheUser")
@SuppressWarnings("unchecked")*/
public String getRedisCacheUsers(String username) {
String string = getRedisCacheUsersDB(username);
return string;
}
public String getRedisCacheUsersDB(String username) {
List <RedisCacheUser> redisCacheUsers = new ArrayList <RedisCacheUser>() ;
RedisCacheUser redisCacheUser = new RedisCacheUser() ;
redisCacheUsers = (List<RedisCacheUser>) this.hibernateTemplate.find("from RedisCacheUser where username like '%" + username + "%'");
if(redisCacheUsers.size()>0) {
System.out.println("redisCacheUsers:"+redisCacheUsers);
return JSONObject.fromObject(redisCacheUsers).toString();
}
return null;
}
/**
* 根據userName模糊查詢多個對象 先從緩存 沒有則再數據庫
* @param username
* @return List
*/
/*@Cacheable(key="#username",value="RedisCacheUser")
@SuppressWarnings("unchecked")*/
public List<RedisCacheUser> getRedisCacheUsers1(String username) {
List <RedisCacheUser> redisCacheUsers = new ArrayList <RedisCacheUser>() ;
redisCacheUsers = (List<RedisCacheUser>) this.hibernateTemplate.find("from RedisCacheUser where username like '%" + username + "%'");
return redisCacheUsers;
}
/**
* 根據userId刪除對象
* @param userId
* @return
*/
@CacheEvict(key="#redisCacheUser.getUserid()",value="RedisCacheUser")
public Boolean deleteRedisCacheUserByuserId(RedisCacheUser redisCacheUser) {
this.hibernateTemplate.delete(redisCacheUser);
// TODO Auto-generated method stub
return true;
}
/**
* 清空所有緩存 只是清除了Redis中的RedisCacheUser 但要刪除數據庫的需自己實現
* @return
*/
@CacheEvict(value="RedisCacheUser",allEntries=true)
public void deleteRedisCacheUsers() {
// TODO Auto-generated method stub
}
}
RedisCacheTest.java 使用Junit4測試
/*** 測試redis緩存和Mysql的增刪查改DEMO JUnit測試
* @author Administrator
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:springCore2.xml", "classpath:springMVC.xml" })
public class RedisCacheTest {
@Autowired
private RedisCacheTestService redisCacheTestService;
/**
* 新增一條對象 緩存Redis爲String的
*/
public void saveUser() {
RedisCacheUser user= new RedisCacheUser();
//構造數據
user.setUserid("2");
user.setDdid("1111");
user.setMobile("183213123");
user.setPassword("root");
user.setUsername("root");
redisCacheTestService.addRedisCacheTestUser(user);
}
/**
*根據ID獲取String的
*/
public void getUserById() {
RedisCacheUser user= new RedisCacheUser();
String string = redisCacheTestService.getRedisCacheUserByuserId("13");
if(Objects.equals(string, null)) {
System.out.println("空空");
}else {
System.out.println(string);
}
}
/**
* 根據name 獲取多個user string的
*/
public void getUsers() {
RedisCacheUser user= new RedisCacheUser();
String string = redisCacheTestService.getRedisCacheUsers("root");
if(Objects.equals(string, null)) {
System.out.println("空空");
}else {
System.out.println(string);
}
}
/**
* 新增一個緩存對象
*/
public void saveUser1() {
RedisCacheUser user= new RedisCacheUser();
//構造數據
user.setUserid("3");
user.setDdid("1111");
user.setMobile("183213123");
user.setPassword("root");
user.setUsername("root");
redisCacheTestService.addRedisCacheTestUser1(user);
}
/**
* 根據name返回對象List的
*/
public void getUsers1() {
RedisCacheUser user= new RedisCacheUser();
List<RedisCacheUser> redisCacheUsers= new ArrayList <RedisCacheUser>();
redisCacheUsers = redisCacheTestService.getRedisCacheUsers1("root");
if(redisCacheUsers.size()>0) {
System.out.println(JSONArray.fromObject(redisCacheUsers));
}else {
System.out.println("空空");
}
}
/**
* 刪除Mysql數據庫和Redis一個User對象
*/
public void deleteUser() {
//ArrayList<Object> redisCacheUsersObj = new ArrayList <Object>();
RedisCacheUser user= new RedisCacheUser();
//構造數據
user.setUserid("2");
user.setDdid("1111");
user.setMobile("183213123");
user.setPassword("root");
user.setUsername("root");
redisCacheTestService.deleteRedisCacheUserByuserId(user);
}
/**
* 清空Redis中所有的RedisCacheUser
*/
@Test
public void deleteUsers() {
redisCacheTestService.deleteRedisCacheUsers();
}
}
使用Redis視圖工具查看