这个实例的文件框架结构如下:
首先定义一个简单的角色类:
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);
}
}