SSM集成Redis做缓存(含完整Demo)

三个部分:

1. Linux环境下的redis客户端操作

2. 在java程序中使用redis:

    2.1)导入jedis.jar包
    2.2)直接 Jedis jedis = new Jedis("192.168.80.131", 6379);获取jedis对象,然后进行操作
    2.3)也可以创建jedis连接池JedisPoolUtil,然后需要的时候从连接池中get,使用完release即可
package com.ludada.redis.test;
package com.ludada.redis.test;
 
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
 
public class JedisPoolUtil {
    // 被volatile修饰的变量不会被本地线程缓存,对该变量的读写都是直接操作共享内存。
    private static volatile JedisPool jedisPool = null;
 
    // 私有化静态方法,不能new
    private JedisPoolUtil() {};
 
    //对外提供一个get方法
    public static JedisPool getJedisPoolInstance() {
        if (jedisPool == null) {
            synchronized (JedisPoolUtil.class) {
                if (jedisPool == null) {
                    JedisPoolConfig poolConfig = new JedisPoolConfig();
                    poolConfig.setMaxActive(1000);
                    poolConfig.setMaxIdle(32);
                    poolConfig.setMaxWait(100 * 1000);
                    poolConfig.setTestOnBorrow(true);
 
                    jedisPool = new JedisPool(poolConfig, "192.168.80.131",6379);
                }
            }
        }
        return jedisPool;
    }
    
    //释放回池子
    public static void release(JedisPool jedisPool,Jedis jedis){
        if(jedis != null){
            jedisPool.returnResourceObject(jedis);
        }
    }
}

3. 然后是spring整合redis,也就是通过redisTemplate对redis进行操作(底层应该也是调用的jedis):

3.1)导入spring-data-redis.jar和jedis.jar

3.2)在spring的配置文件配置redisTemplate


 
    
    
        
        
        
        
        
        
    
    
    
    
        
        
        
        
    
    
    
    
    
    
    
    
        
        
        
    
    

3.3)使用redisTemplate
package ldd.Spring_Redis;
 
 
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
 
public class myTest {
 
    RedisTemplate redisTemplate = null;
    
    @Before
    public void before(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        redisTemplate = ctx.getBean(RedisTemplate.class);
    }
    
    @Test
    public void Test01() {
        Role role = new Role();
        role.setId(1L);
        role.setNote("note_1");
        role.setRoleName("role_name_1");
        
        //存储到到内存中的不是map而是string,进行了序列化
        redisTemplate.opsForValue().set("role_1", role);
        Role role1 = (Role) redisTemplate.opsForValue().get("role_1");
        //上面两步不能保证每次使用RedisTemplate是操作同一个对Redis的连接
        
        System.out.println(role1.toString());
    }
    
    @Test
    public void Test02(){
        final Role role = new Role();
        role.setId(1L);
        role.setNote("note_1");
        role.setRoleName("role_name_1");
        
        SessionCallback callback = new SessionCallback(){
            public Role execute(RedisOperations ops) throws DataAccessException {
                ops.boundValueOps("role_1").set(role);
                return (Role) ops.boundValueOps("role_1").get();
            }
        };
        Role savedRole = (Role) redisTemplate.execute(callback);
        System.out.println(savedRole.getRoleName());
    }
    
 
}

4.最后便是今天要说的spring缓存整合redis

环境:jdk 1.8 + tomcat 7 + redis 3.0.4 + spring 4.2 + mybatis 3.3.0

先上demo(maven项目):

image
image

UserController:

处理器方法

 对于数据一致性要求不高的数据,通过redisTemplate进行查找,添加。

对于数据一致性要求较高的数据,直接调用service层方法。


package com.ssm.controller;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
 
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
 
import com.ssm.pojo.User;
import com.ssm.service.IUserService;
 
/**
 * user控制器
 * 
 */
 
@Controller
@RequestMapping("/UserCRUD")
public class UserController {
 
    @Resource
    private IUserService userService;
    
    @Resource
    private RedisTemplate redisTemplate;
    
 
    /**
     * 统计注册用户总数
     * @param null
     * @return String
     * @throws Exception 
     */
    
    @RequestMapping("/indexMSG")
    public String getIndexMSG(Model model) throws Exception{
        String usersCount = null;
        
        //尝试从缓存中取数据
        usersCount = (String) redisTemplate.opsForValue().get("users_count");
        
        if(usersCount == null){
            //redis缓存中无数据,从数据库中查询,并放入redis缓存中,设置生存时间为1小时
            System.out.println("从数据库中取当前已注册用户数量");
            usersCount = Integer.toString(userService.selectUsersCount());
            redisTemplate.opsForValue().set("users_count", usersCount, 1, TimeUnit.HOURS);
        } else {
            System.out.println("从redis缓存中取当前已注册用户数量");
        }
        
        List ids = null;
        ids = userService.selectNowIds();
        
        model.addAttribute("usersCount", usersCount);
        model.addAttribute("ids", ids);
        return "forward:/index.jsp";
    }
    
    /**
     * 通过ID查询User
     * 
     * @param userId
     * @param model
     * @return String
     */
    @RequestMapping(value = "/getUserById", method = RequestMethod.GET)
    public String getUserById(Model model, Integer userId) {
        System.out.println("**********getUserById********");
        User user = userService.getUserById(userId);
        model.addAttribute("user", user); // 填充数据到model
        return "showUser";
    }
    
    /**
     * 查询所有User
     * 
     * @param request
     * @param model
     * @return
     */
    @RequestMapping(value = "/showUser", method = RequestMethod.GET)
    public String showUsers(Model model) {
        System.out.println("**********showUsers********");
        List userList = new ArrayList();
        userList = userService.getAllUser();
        model.addAttribute("userList", userList); // 填充数据到model
        return "showUser";
    }
 
    /**
     * 增加一个用户
     * 
     * @param userName
     * @param sex
     * @param age
     * @throws Exception 
     */
    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    public void addUser(User user, HttpServletResponse response) throws Exception {
        System.out.println("******addUser********");
        User result = userService.insertUser(user);
        if (result.getId() != 0) {
            response.getWriter().print("OK");
        } else {
            response.getWriter().print("FAIL");
        }
    }
 
    /**
     * 通过userID删除用户
     * 
     * @param userID
     * @throws Exception 
     */
    @RequestMapping(value = "/delUser/{userID}", method = RequestMethod.POST)
    public void delUser(@PathVariable int userID, HttpServletResponse response) throws Exception {
        System.out.println(userID);
        int i = userService.deleteUser(userID);
        if(i == 1){
            response.getWriter().print("OK");
        }else{
            response.getWriter().print("删除失败!");
        }
        
    }
 
    /**
     * 查询用户
     * 
     * @param model
     * @param keyWords
     * @return
     */
    @RequestMapping("/search")
    public ModelAndView findUsers(String keyWords) {
        System.out.println(keyWords);
        ModelAndView mv = new ModelAndView();
        List userList = new ArrayList();
        userList = userService.findUsers(keyWords);
        
        mv.addObject("userList", userList);
        mv.setViewName("showUser");
 
        return mv;
    }
    
    /**
     * 更新用户信息
     * @param userName
     * @param sex
     * @param age
     * @param id
     * @return
     * @throws Exception 
     */
    @RequestMapping(value="/editUser",method=RequestMethod.POST)
    public void editUser(int id, String name, String sex, int age, HttpServletResponse res) throws Exception {
        User user = new User();
        user.setId(id);
        user.setAge(age);
        user.setsex(sex);
        user.setUserName(name);
        System.out.println(user.toString());
        int rows = userService.editUser(user);
        if(rows == 1){
            res.getWriter().print("OK");
        } else {
            res.getWriter().print("FAIL");
        }
    }
}

UserMapper.java

package com.ssm.dao;
 
import java.util.List;
import com.ssm.pojo.User;
 
 
public interface UserMapper {
 
    public User selectByPrimaryKey(Integer userId);
 
    public List selectAllUser();
 
    public int insertUser(User user);
 
    public int deleteUser(int id);
 
    public List findUsers(String keyWords);
 
    public int editUser(User user);
 
    public Integer selectUsersCount();
 
    public List selectIds();
}

UserMapper.xml

  


    
        
        
        
        
    
    
        id,userName,sex,age
    
    
    
    
    
 
    
    
 
    
    
        INSERT INTO
        tb_user(userName,sex,age) VALUES
        (#{userName},#{sex},#{age})
    
 
    
    
        DELETE FROM tb_user WHERE
        id=#{id}
    
 
    
    
        UPDATE tb_user
        
            
                userName=#{userName},
            
            
                sex=#{sex},
            
            
                age=#{age}
            
        
        WHERE id=#{id}
    
    
    
    
    


IUserService.java


package com.ssm.pojo;
 
import java.io.Serializable;
 
/**
 * User实体类对应数据库中的tb_user表
 * 
 */
public class User implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = -5244288298702801619L;
    private int id;
    private String userName;
    private String sex;
    private int age;
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getUserName() {
        return userName;
    }
 
    public void setUserName(String userName) {
        this.userName = userName;
    }
 
    public String getsex() {
        return sex;
    }
 
    public void setsex(String sex) {
        this.sex = sex;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    @Override
    public String toString() {
        return "User [id=" + id + ", userName=" + userName + ", sex=" + sex + ", age=" + age + "]";
    }
}

UserServiceImpl.java

最重要的便是serviceImpl类,

package com.ssm.service;
 
import java.util.List;
import com.ssm.pojo.User;
 
/**
 * user表的操作接口
 * 
 */
public interface IUserService {
 
    /**
     * 通过id查询user接口方法
     * 
     * @param userId
     * @return User
     */
    public User getUserById(Integer userId);
 
    /**
     * 查询所有的user
     * 
     * @return 返回userList
     */
    public List getAllUser();
 
    /**
     * 添加一个user
     * 
     * @param user
     */
    public User insertUser(User user);
 
    /**
     * 通过ID删除用户
     * 
     * @param id
     * @return 
     */
    public int deleteUser(int id);
 
    /**
     * 通过关键字查询用户
     * 
     * @param keyWords
     * @return
     */
    public List findUsers(String keyWords);
 
    /**
     * 更新用户
     * 
     * @param user
     * @return int
     */
    public int editUser(User user);
 
    /**
     * 查询网站注册用户数量(一小时更新一次)
     * @return Integer
     */
    public Integer selectUsersCount();
 
    /**
     * 查询现有ID
     * @return List
     */
    public List selectNowIds();
}

RedisCacheConfig.java

重写的generate()方法为那些需要将数据存入缓存的无参的方法指定存入缓存中的数据的key,可以根据需求自己设计。

package com.ssm.serviceImpl;
 
import java.util.List;
import javax.annotation.Resource;
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.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.ssm.dao.UserMapper;
import com.ssm.pojo.User;
import com.ssm.service.IUserService;
 
/**
 * 
 * 缓存机制说明:所有有缓存注解的查询结果都放进了缓存,也就是把MySQL查询的结果放到了redis中去,
 * 然后第二次发起该条查询时就可以从redis中去读取查询的结果,从而不与MySQL交互,从而达到优化的效果,
 * redis的查询速度之于MySQL的查询速度相当于 内存读写速度 /硬盘读写速度
 * 
 * @Cacheable(value="xxx" key="zzz")注解:标注该方法查询的结果进入缓存,再次访问时直接读取缓存中的数据
 * 1.对于有参数的方法,指定value(缓存区间)和key(缓存的key);
 *     对于无参数的方法,只需指定value,存到数据库中数据的key通过com.ssm.utils.RedisCacheConfig中重写的generate()方法生成。
 * 2.调用该注解标识的方法时,会根据value和key去redis缓存中查找数据,如果查找不到,则去数据库中查找,然后将查找到的数据存放入redis缓存中;
 * 3.向redis中填充的数据分为两部分:
 *      1).用来记录xxx缓存区间中的缓存数据的key的xxx~keys(zset类型)
 *      2).缓存的数据,key:数据的key;value:序列化后的从数据库中得到的数据
 * 4.第一次执行@Cacheable注解标识的方法,会在redis中新增上面两条数据
 * 5.非第一次执行@Cacheable注解标识的方法,若未从redis中查找到数据,则执行从数据库中查找,并:
 *      1).新增从数据库中查找到的数据
 *      2).在对应的zset类型的用来记录缓存区间中键的数据中新增一个值,新增的value为上一步新增的数据的key
 */
@Service("userService")
//事务注解
@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)  
public class UserServiceImpl implements IUserService {
 
    @Resource
    private UserMapper iUserDao;
 
    /**
     * 根据ID查找user
     * 查到的数据存到users缓存区间,key为user_id,value为序列化后的user对象
     * 
     */
    @Cacheable(value = "aboutUser", key="'user_'+#userId") 
    @Override
    public User getUserById(Integer userId) {
        return iUserDao.selectByPrimaryKey(userId);
    }
 
    /**
     * 获取所有用户信息
     * 1.对数据一致性要求较高,所以在执行增删改操作后需要将redis中该数据的缓存清空,
     * 从数据库中获取最新数据。
     * 2.若缓存中没有所需的数据,则执行该方法后:
     *  1).在redis缓存中新增一条数据
     *      key:getAllUser  value:序列化后的List
     *      key的值通过com.ssm.utils.RedisCacheConfig中重写的generate()方法生成
     *  2).在用来记录aboutUser缓存区间中的缓存数据的key的aboutUser~keys(zset类型)中新添加一个value,
     *          值为上面新增数据的key
     */
    @Cacheable(value="aboutUser")
    @Override
    public List getAllUser() {
        return iUserDao.selectAllUser();
    }
    
    /**
     * @CacheEvict()注解:移除指定缓存区间的一个或者多个缓存对象
     * @param value + key 或者 value + allEntries=true
     * 1.value + key 移除value缓存区间内的键为key的数据
     * 2.value + allEntries=true 移除value缓存区间内的所有数据
     */
    //@CacheEvict(value= "aboutUser", key="'user_'+#result.id")
    @CacheEvict(value= "aboutUser", allEntries=true)
    @Override
    public User insertUser(User user) {
        iUserDao.insertUser(user);//进行了主键回填
        return user;
    }
 
    /**
     * 根据id删除用户
     */
    @CacheEvict(value= "aboutUser", allEntries=true)
    @Override
    public int deleteUser(int id) {
        return iUserDao.deleteUser(id);
    }
 
    /**
     * 根据关键词模糊查询用户,命中率较低,不存入redis缓存中
     */
    @Override
    public List findUsers(String keyWords) {
        return iUserDao.findUsers(keyWords);
    }
 
    @CacheEvict(value= {"aboutUser"},allEntries=true)
    @Override
    public int editUser(User user) {
        return iUserDao.editUser(user);
    }
 
    /**
     * 统计当前所有用户ID
     * 1.对数据一致性要求较高,所以在执行增删改操作后需要将redis中该数据的缓存清空,
     * 从数据库中获取最新数据。
     * 2.执行该方法后,在redis缓存中新增一条数据
     *  1) selectNowIds 缓存的数据的key,可以在com.ssm.utils.RedisCacheConfig中重写generate()方法自定义
     * 3.然后在zset类型的aboutUser中添加一个值,值为上线的key
     */
 
    @Cacheable(value = "aboutUser")
    @Override
    public List selectNowIds() {
        return iUserDao.selectIds();
    }
    
    /**
     * 统计注册用户个数
     *  对数据一致性要求不高,所以在controller中使用redisTemplate存入redis,
     * 并指定生存时间为1小时
     */
    @Override
    public Integer selectUsersCount() {
        return iUserDao.selectUsersCount();
    }
}

applicationContext.xml

重点在缓存区间的配置,对应缓存注解中指定value的值;如不进行配置可value可以随意写,但是如果进行了配置value只能等于已配置的值



        
    
    
    
    
    
    
        
            
                classpath:jdbc.properties
                classpath:redis.properties
            
        
    
    
        
        
        
        
        
        
        
        
        
        
    
 
    
    
        
        
    
 
    
        
    
    
 
    
    
    
        
    
    
 
    
    
    
        
        
        
        
    
 
    
    
        
        
        
        
        
    
 
    
 
    
    
        
        
        
    
 
    
    
        
        
        
        
            
                aboutUser
            
        
    
 
    
    
        
        
        
    
 
    

springmvc.xml

    
    
    
           
    
        
    
    
        
 
    
    
        
        
        
    
    
 
    
    
        
            
                application/json;charset=UTF-8
            
        
    
 
    
        
            
                
            
        
    
    


jdbc.properties

jdbc.host=127.0.0.1
jdbc.database=user
jdbc.port=3306
jdbc.username=root
jdbc.password=111

log4j.properties


# Global logging configuration
log4j.rootLogger=WARN,stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c:%L - %m%n
# mybatis log
log4j.logger.com.ssm.dao.UserMapper=DEBUG
# lyz log
log4j.logger.com.ssm.controller=DEBUG
log4j.logger.com.ssm.service=DEBUG

redis.properties


# Redis settings  
redis.host=192.168.80.132
redis.port=6379  
#redis.pass=password
redis.dbIndex=0  
redis.expiration=3000  
redis.maxIdle=300  
redis.maxActive=600  
redis.maxWait=1000  
redis.testOnBorrow=true

showUser.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>




show user







showUser



未查找到用户信息!

id userName sex age
${user.id } ${user.userName } ${user.sex } ${user.age }
id userName sex age
${user.id } ${user.userName } ${user.sex } ${user.age }

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>



SSM-Redis







    

当前注册用户数量(一个小时更新一次): ${usersCount }


*
*
*

现有ID(${fn:length(ids)}个):

${id }

UID:
*


关键字:

UserID:

pom.xml


  4.0.0
  ldd
  SSMRedisDemo
  war
  0.0.1-SNAPSHOT
  SSMRedisDemo Maven Webapp
  http://maven.apache.org
  
    
        UTF-8
        4.2.0.RELEASE
    
 
    
 
         
        
            org.springframework
            spring-context
            ${spring.version}
        
        
            org.springframework
            spring-aop
            ${spring.version}
        
        
            org.springframework
            spring-webmvc
            ${spring.version}
        
        
            org.springframework
            spring-web
            ${spring.version}
        
        
            javax.servlet
            jstl
            1.2
        
        
            commons-logging
            commons-logging
            1.1.3
        
        
            org.codehaus.jackson
            jackson-mapper-asl
            1.9.13
        
        
            com.fasterxml.jackson.core
            jackson-annotations
            2.6.1
        
        
            com.fasterxml.jackson.core
            jackson-core
            2.6.1
        
        
            com.fasterxml.jackson.core
            jackson-databind
            2.6.1
        
        
 
        
        
            org.springframework
            spring-orm
            ${spring.version}
        
        
            org.mybatis
            mybatis-spring
            1.2.3
        
        
            mysql
            mysql-connector-java
            5.1.36
        
        
            org.mybatis
            mybatis
            3.3.0
        
        
            c3p0
            c3p0
            0.9.1.2
        
        
            org.slf4j
            slf4j-log4j12
            1.7.12
        
        
 
        
        
            log4j
            log4j
            1.2.17
        
        
 
        
        
            org.springframework.data
            spring-data-redis
            1.6.0.RELEASE
        
        
            redis.clients
            jedis
            2.7.3
        
        
 
    
 
    
        
            
                maven-compiler-plugin
                3.1
                
                    1.7
                    1.7
                
            
            
                maven-war-plugin
                2.4
                
                    WebContent
                    false
                
            
        
    

你可能感兴趣的:(SSM集成Redis做缓存(含完整Demo))