一個簡單的Spring緩存機制整合Redis實例

這個實例的文件框架結構如下:
在這裏插入圖片描述

首先定義一個簡單的角色類:

Role.java

package com.ssm.example3.pojo;

import java.io.Serializable;

public class Role implements Serializable {
    private Long id;
    private String roleName;
    private String note;

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public Long getId() {
        return id;
    }

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

注意,該類實現了Serializable接口,這說明這個類支持序列化,這樣就可以通過Spring的序列化器,將其保存爲對應的編碼。緩存到Redis中,也可以通過Redis都會這些編碼,反序列化爲對應的java對象。

接下來是關於MyBatis的開發環境,這樣我們就可以操作數據庫了。

RoleMapper.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.ssm.example3.dao.RoleDao">

    <select id="getRole" resultType="com.ssm.example3.pojo.Role">
        select id, role_name as roleName,note from role where id=#{id}
    </select>

    <delete id="deleteRole">
        delete from role where id=#{id}
    </delete>

    <insert id="insertRole" parameterType="com.ssm.example3.pojo.Role" useGeneratedKeys="true" keyProperty="id">
        insert into role (role_name,note) values (#{roleName},#{note})
    </insert>

    <update id="updateRole" parameterType="com.ssm.example3.pojo.Role">
        update role set role_name=#{roleName},note=#{note}
    </update>

    <select id="findRoles" resultType="com.ssm.example3.pojo.Role">
        select id,role_name as roleName ,note from role
        <where>
            <if test="roleName != null">
                role_name like concat('%',#{roleName},'#')
            </if>
            <if test="note != note">
                note like concat('%',#{note},'%')
            </if>
        </where>
    </select>
</mapper>

然後需要一個MyBatis角色接口,以便使用這樣的一個映射文件。

RoleDao.java

package com.ssm.example3.dao;

import com.ssm.example3.pojo.Role;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface RoleDao {
   public Role getRole(Long id);

   public int deleteRole(Long id);

   public int insertRole(Role role);

   public int updateRole(Role role);

   public List<Role> findRoles(@Param("roleName") String roleName,@Param("note") String note);
}

注意@Repository便是他是一個持久層的接口。通過掃描和註解聯合定義DAO層,就完成了映射器方面的內容。接下來是定義服務接口定義角色服務接口。

RoleService.java

package com.ssm.example3.service;

import com.ssm.example3.pojo.Role;

import java.util.List;

public interface RoleService {
    public Role getRole(Long id);

    public int deleteRole(Long id);

    public Role insertRole(Role role);

    public Role updateRole(Role role);

    public List<Role> findRoles(String roleName,String note);
}

這個實例我是用註解來配置定義數據庫個相關的掃描內容。

RootConfig.java

package com.ssm.example3.config;

import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;


import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@ComponentScan("com.*")
//使用事務驅動管理器
@EnableTransactionManagement
//實現接口 TransactionManagementConfigurer,這樣可以配置註解驅動事務
public class RootConfig implements TransactionManagementConfigurer {

    private DataSource dataSource=null;

    /**
     * 配置數據庫
     * @return 數據庫連接池
     */
    @Bean(name = "dataSource")
    public DataSource initDataSource(){
        if(dataSource!=null){
            return dataSource;
        }
        Properties props=new Properties();
        props.setProperty("driveClassName","com.mysql.jdbc.Driver");
        props.setProperty("url","jdbc:mysql://localhost:3306/ssm");
        props.setProperty("username","root");
        props.setProperty("password","123456");
        try {
            dataSource= BasicDataSourceFactory.createDataSource(props);
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return dataSource;
    }

    /**
     * 配置SqlSessionFactoryBean
     * @return SqlSessionFactoryBean
     */
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactoryBean initSqlSessionFactory(){
        SqlSessionFactoryBean sqlSessionFactory=new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(initDataSource());
        //配置Mybatis配置文件
        Resource resource=new ClassPathResource("com/ssm/example3/mybatis/mybatis-cfg.xml");
        sqlSessionFactory.setConfigLocation(resource);
        return sqlSessionFactory;
    }

    /**
     * 通過自動掃描,發現Mybatis Mapper接口
     * @return Mapper 掃描器
     */
    @Bean
    public MapperScannerConfigurer initMapperScannerConfigurer(){
        MapperScannerConfigurer msc=new MapperScannerConfigurer();
        //掃描包
        msc.setBasePackage("com.*");
        msc.setSqlSessionFactoryBeanName("sqlSessionFactory");
        //區分註解掃描
        msc.setAnnotationClass(Repository.class);
        return msc;
    }

    /**
     * 實現接口方法,註冊註解事務,當@Transactional使用的時候產生數據庫事務
     * @return
     */
    @Override
    @Bean(name = "annotationDrivenTransactionManeger")
    public TransactionManager annotationDrivenTransactionManager() {
        DataSourceTransactionManager transactionManager=new DataSourceTransactionManager();
        transactionManager.setDataSource(initDataSource());
        return transactionManager;
    }
}

在裏面引入了一個關於MyBatis的一個配置文件——mybatis-config.xml。

<?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>
    <mappers>
        <mapper resource="com/ssm/example3/sqlMapper/RoleMapper.xml"></mapper>
    </mappers>
</configuration>

下面我們再來配置Redis的相關內容。

RedisConfig.java

package com.ssm.example3.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

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

/**
 * 配置Spring緩存管理器
 */
@Configuration
@EnableCaching
public class RedisConfig {

    @Bean(name = "redisTemplate")
    public RedisTemplate initRedisTemplate(){
        JedisPoolConfig poolConfig=new JedisPoolConfig();
        //最大空閒數
        poolConfig.setMaxIdle(50);
        //最大連接數
        poolConfig.setMaxTotal(100);
        //最大等待毫秒數
        poolConfig.setMaxWaitMillis(20000);
        //創建Jedis連接工廠
        JedisConnectionFactory connectionFactory=new JedisConnectionFactory(poolConfig);
        connectionFactory.setHostName("localhost");
        connectionFactory.setPort(6379);
        connectionFactory.setPassword("123456");
        //調用後初始化方法,沒有它將拋出異常
        connectionFactory.afterPropertiesSet();
        //自定義Redis序列化器
        RedisSerializer jdkSerializationRedisSerializer=new JdkSerializationRedisSerializer();
        RedisSerializer stringRedisSerializer=new StringRedisSerializer();
        //定義RedisTemplate,並設置連接工程
        RedisTemplate redisTemplate=new RedisTemplate();
        redisTemplate.setConnectionFactory(connectionFactory);
        //設置序列化器
        redisTemplate.setDefaultSerializer(stringRedisSerializer);
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(jdkSerializationRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(jdkSerializationRedisSerializer);
        return redisTemplate;
    }

    @Bean(name = "redisCacheManager")
    public CacheManager initRedisCacheManager(@Autowired RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager=new RedisCacheManager(redisTemplate);
        //設置超時時間爲10分鐘,單位爲秒
        cacheManager.setDefaultExpiration(600);
        //設置緩存名稱
        List<String> cacheNames=new ArrayList<String>();
        cacheNames.add("redisCacheManager");
        cacheManager.setCacheNames(cacheNames);
        return cacheManager;
    }
}

最後我們在編寫RoleService的實現類——RoleServiceImpl。

RoleServiceImpl.java

package com.ssm.example3.service.impl;

import com.ssm.example3.dao.RoleDao;
import com.ssm.example3.pojo.Role;
import com.ssm.example3.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class RoleServiceImpl implements RoleService {

    //角色DAO,方便執行SQL
    @Autowired
    private RoleDao roleDao=null;

    /**
     * 使用@Cacheable定義緩存策略
     * 當緩存中有值,則返回緩存數據,否則訪問方法得到數據。
     * 通過value引用緩存管理器,通過key定義鍵
     * @param id 角色編號
     * @return 角色
     */
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
    @Cacheable(value = "redisCacheManager",key = "'redis_role_'+#id")
    public Role getRole(Long id) {
        return roleDao.getRole(id);
    }

    /**
     * 使用@CachePut則表示無論如何都會執行方法,最後將方法的返回值在保存到緩存中
     * 使用在插入數據的地方,則表示保存到數據庫後,會同時插入Redis緩存中
     * @param role 角色對象
     * @return
     */
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
    @CachePut(value = "redisCacheManager",key = "'redis_role_'+#result.id")
    public Role insertRole(Role role) {
        roleDao.insertRole(role);
        return role;
    }

    /**
     * 使用@CachePut,表示更新數據庫數據的同時,也會同步更新緩存
     * @param role 角色對象
     * @return
     */
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
    @CachePut(value = "redisCacheManager",key = "'redis_role_'+#role.id")
    public Role updateRole(Role role) {
        roleDao.updateRole(role);
        return role;

    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
    public List<Role> findRoles(String roleName, String note) {
        return roleDao.findRoles(roleName,note);
    }

    /**
     * 使用@CacheEvict刪除緩存對應的key
     * @param id 角色編號
     * @return 返回刪除記錄數
     */
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
    @CacheEvict(value = "redisCacheManager",key = "'redis_role_'+#id")
    public int deleteRole(Long id) {
        return roleDao.deleteRole(id);
    }
}

到此已全部配置完成,現在我們用一個測試類來測試一下

testRedis.java

package com.ssm.example3.test;


import com.ssm.example3.config.RedisConfig;
import com.ssm.example3.config.RootConfig;
import com.ssm.example3.pojo.Role;
import com.ssm.example3.service.RoleService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class testRedis {
    public static void main(String[] args){
        ApplicationContext ctx=new AnnotationConfigApplicationContext(RootConfig.class,RedisConfig.class);
        //獲取角色服務類
        RoleService roleService=ctx.getBean(RoleService.class);
        Role role=new Role();
        role.setRoleName("role_name_1");
        role.setNote("role_note_1");
        //插入角色
        roleService.insertRole(role);
        //獲取角色
        Role getRole=roleService.getRole(role.getId());
        getRole.setNote("role_note_2");
        //修改角色信息
        roleService.updateRole(getRole);
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章