1. 程式人生 > >SSM整合Redis做快取(含完整Demo)

SSM整合Redis做快取(含完整Demo)

之前一段時間自學了Redis,進行一下總結

三個部分:

    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;

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

<?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.3.xsd">

	<!-- 連線池配置 -->
	<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<!-- 最大空閒數 -->
		<property name="maxIdle" value="50"></property>
		<!-- 最大連線數 -->
		<property name="maxTotal" value="100"></property>
		<!-- 最大等待時間 -->
		<property name="maxWaitMillis" value="20000"></property>
	</bean>
	
	<!-- 配置連線工廠 -->
	<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
		<property name="hostName" value="192.168.80.131"></property>
		<property name="port" value="6379"></property>
		<!-- <property name="password" value=""></property> -->
		<property name="poolConfig" ref="poolConfig"></property>
	</bean>
	
	<!-- 配置 key 和 value 的序列化器 -->
	<bean id="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
	<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
	
	<!-- 配置Redis模板物件 -->
	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="connectionFactory"></property>
		<property name="keySerializer" ref="stringRedisSerializer"></property>
		<property name="valueSerializer" ref="jdkSerializationRedisSerializer"></property>
	</bean>
	
</beans>

    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<Role>(){
			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專案):



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<Integer> 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<User> userList = new ArrayList<User>();
        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<User> userList = new ArrayList<User>();
        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<User> selectAllUser();

    public int insertUser(User user);

    public int deleteUser(int id);

    public List<User> findUsers(String keyWords);

    public int editUser(User user);

    public Integer selectUsersCount();

    public List<Integer> selectIds();
}

UserMapper.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.dao.UserMapper">
    <resultMap id="BaseResultMap" type="com.ssm.pojo.User">
        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="userName" property="userName" jdbcType="VARCHAR" />
        <result column="sex" property="sex" jdbcType="VARCHAR" />
        <result column="age" property="age" jdbcType="INTEGER" />
    </resultMap>
    <sql id="Base_Column_List">
        id,userName,sex,age
    </sql>
    
    <select id="selectByPrimaryKey" resultMap="BaseResultMap">
    	select
    	<include refid="Base_Column_List" />
    	from tb_user
    	where id = #{userId}
    </select>
    
    <select id="findUsers" resultMap="BaseResultMap" parameterType="String">
        select
        <include refid="Base_Column_List" />
        from tb_user
        where id like #{keyWords}
        or userName like '%' #{keyWords} '%'
        or sex like '%' #{keyWords} '%'
        or age like #{keyWords}
    </select>

    <!-- 查詢所有的user -->
    <select id="selectAllUser" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from tb_user
    </select>

    <!-- 新增一個使用者 -->
    <insert id="insertUser" parameterType="com.ssm.pojo.User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO
        tb_user(userName,sex,age) VALUES
        (#{userName},#{sex},#{age})
    </insert>

    <!-- 刪除使用者 -->
    <delete id="deleteUser" parameterType="int">
        DELETE FROM tb_user WHERE
        id=#{id}
    </delete>

    <!-- 更新user資訊 -->
    <update id="editUser" parameterType="com.ssm.pojo.User">
        UPDATE tb_user
        <set>
        	<if test="userName != null">
        		userName=#{userName},
        	</if>
        	<if test="sex != null">
        		sex=#{sex},
        	</if>
        	<if test="age != null">
        		age=#{age}
        	</if>
        </set>
        WHERE id=#{id}
    </update>
    
    <select id="selectUsersCount" resultType="Integer">
    	select count(*) from tb_user
    </select>
    
    <select id="selectIds" resultType="Integer">
    	select id from tb_user
    </select>
</mapper>

User.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 + "]";
    }
}

IUserService.java

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<User> getAllUser();

	/**
	 * 新增一個user
	 * 
	 * @param user
	 */
	public User insertUser(User user);

	/**
	 * 通過ID刪除使用者
	 * 
	 * @param id
	 * @return 
	 */
	public int deleteUser(int id);

	/**
	 * 通過關鍵字查詢使用者
	 * 
	 * @param keyWords
	 * @return
	 */
	public List<User> findUsers(String keyWords);

	/**
	 * 更新使用者
	 * 
	 * @param user
	 * @return int
	 */
	public int editUser(User user);

	/**
	 * 查詢網站註冊使用者數量(一小時更新一次)
	 * @return Integer
	 */
	public Integer selectUsersCount();

	/**
	 * 查詢現有ID
	 * @return List<Integer>
	 */
	public List<Integer> selectNowIds();
}

UserServiceImpl.java

最重要的便是serviceImpl類,

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<User>
     * 		key的值通過com.ssm.utils.RedisCacheConfig中重寫的generate()方法生成
     * 	2).在用來記錄aboutUser快取區間中的快取資料的key的aboutUser~keys(zset型別)中新新增一個value,
     * 	        值為上面新增資料的key
     */
    @Cacheable(value="aboutUser")
    @Override
    public List<User> 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<User> 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<Integer> selectNowIds() {
		return iUserDao.selectIds();
	}
	
	/**
	 * 統計註冊使用者個數
	 * 	對資料一致性要求不高,所以在controller中使用redisTemplate存入redis,
	 * 並指定生存時間為1小時
	 */
	@Override
	public Integer selectUsersCount() {
		return iUserDao.selectUsersCount();
	}
}

RedisCacheConfig.java

    重寫的generate()方法為那些需要將資料存入快取的無參的方法指定存入快取中的資料的key,可以根據需求自己設計。

package com.ssm.utils;

import java.lang.reflect.Method;

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
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;

/**
 * 通過spring管理redis快取配置
 * 
 * @author Administrator
 *
 */
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
	private volatile JedisConnectionFactory jedisConnectionFactory;
	private volatile RedisTemplate<String, String> redisTemplate;
	private volatile RedisCacheManager redisCacheManager;

	public RedisCacheConfig() {
		super();
	}

	/**
	 * 帶引數的構造方法 初始化所有的成員變數
	 * 
	 * @param jedisConnectionFactory
	 * @param redisTemplate
	 * @param redisCacheManager
	 */
	public RedisCacheConfig(JedisConnectionFactory jedisConnectionFactory, RedisTemplate<String, String> redisTemplate,
			RedisCacheManager redisCacheManager) {
		this.jedisConnectionFactory = jedisConnectionFactory;
		this.redisTemplate = redisTemplate;
		this.redisCacheManager = redisCacheManager;
	}

	public JedisConnectionFactory getJedisConnecionFactory() {
		return jedisConnectionFactory;
	}

	public RedisTemplate<String, String> getRedisTemplate() {
		return redisTemplate;
	}

	public RedisCacheManager getRedisCacheManager() {
		return redisCacheManager;
	}

	@Bean
	public KeyGenerator keyGenerator() {
		return new KeyGenerator() {
			@Override
			public Object generate(Object target, Method method, Object... objects) {
				StringBuilder sb = new StringBuilder();
				//sb.append(target.getClass().getName());
				sb.append(method.getName());
				if(objects.length != 0){
					sb.append("_");
					for (Object obj : objects) {
						sb.append(obj.toString());
					}
				}
				return sb.toString();
			}
		};
	}
}

applicationContext.xml

重點在快取區間的配置,對應快取註解中指定value的值;如不進行配置可value可以隨意寫,但是如果進行了配置value只能等於已配置的值

<?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:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:cache="http://www.springframework.org/schema/cache"
	xsi:schemaLocation="http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.2.xsd
		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.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
        
    <!-- class annotation related... start -->
    <context:component-scan base-package="com.ssm.serviceImpl" />
    <context:component-scan base-package="com.ssm.utils" />
    <!-- class annotation related... end -->
    <!-- mybatis related... start -->
    <bean
        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="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUrl" value="jdbc:mysql://${jdbc.host}:${jdbc.port}/${jdbc.database}?useUnicode=true&characterEncoding=utf8" />
        <property name="user" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="acquireIncrement" value="1" />
        <property name="initialPoolSize" value="5" />
        <property name="maxPoolSize" value="20" />
        <property name="minPoolSize" value="5" />
        <property name="maxStatements" value="100" />
        <property name="testConnectionOnCheckout" value="true" />
    </bean>

    <!-- spring和MyBatis完美整合,不需要mybatis的配置對映檔案 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!-- 自動掃描mapping.xml檔案 <property name="mapperLocations" value="classpath:com/ssm/mapper/*.xml"></property> -->
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.ssm.dao" />
    </bean>
    <!-- mybatis related... end -->

    <!-- transaction config related... start -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!-- transaction config related... end -->

    <!-- redis config start -->
    <!-- 配置JedisPoolConfig例項 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxTotal" value="${redis.maxActive}" />
        <property name="maxWaitMillis" value="${redis.maxWait}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>

    <!-- 配置JedisConnectionFactory -->
    <bean id="jedisConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.host}" />
        <property name="port" value="${redis.port}" />
        <!-- <property name="password" value="${redis.pass}" /> -->
        <property name="database" value="${redis.dbIndex}" />
        <property name="poolConfig" ref="poolConfig" />
    </bean>

	<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>

    <!-- 配置RedisTemplate -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <property name="hashKeySerializer" ref="stringRedisSerializer"/>
        <property name="keySerializer" ref="stringRedisSerializer"/>
    </bean>

    <!-- 配置RedisCacheManager -->
    <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg name="redisOperations" ref="redisTemplate" />
        <property name="defaultExpiration" value="${redis.expiration}" />
        <!-- 配置快取區間 -->
        <property name="cacheNames">
        	<list>
        		<value>aboutUser</value>
        	</list>
        </property>
    </bean>

	<!-- 配置RedisCacheConfig -->
	<bean id="redisCacheConfig" class="com.ssm.utils.RedisCacheConfig">
		<constructor-arg ref="jedisConnectionFactory"/>
		<constructor-arg ref="redisTemplate"/>
		<constructor-arg ref="redisCacheManager"/>
	</bean>

    <!-- redis config end -->
</beans>

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:p="http://www.springframework.org/schema/p"    
    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-3.1.xsd      
                        http://www.springframework.org/schema/context      
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd      
                        http://www.springframework.org/schema/mvc      
                        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">    
    <!-- class annotation related... start 
    <context:component-scan base-package="com.ssm.controller" />
     class annotation related... end 
     -->
     <!-- 添加註解驅動  使用註解標註的類生效-->      
    <mvc:annotation-driven />
    <!-- 設定能訪問靜態資源 -->    
    <mvc:default-servlet-handler/>
    <!--掃描controller-->
    <context:component-scan base-package="com.ssm.controller" />    

    <!-- jsp page related... start -->
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <!-- jsp page related... end -->

    <!-- rest json related... start -->
    <bean id="mappingJacksonHttpMessageConverter"
        class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>application/json;charset=UTF-8</value>
            </list>
        </property>
    </bean>

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="mappingJacksonHttpMessageConverter" />
            </list>
        </property>
    </bean>
    <!-- rest json related... end -->
</beans>

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"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>show user</title>
<!-- 螢幕和裝置的螢幕一致,初始縮放為1:1,禁止使用者縮放 -->
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/bootstrap.min.css">
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container-fluid">
	<div class="row">
		<div class="col-md-2">
			<h1>showUser</h1>
		</div>
		<div class="col-md-10">
			<br>
			<button class="btn btn-success" onclick="javascript:history.back(-1);">返回上一頁</button>
		</div>
	</div>
	<hr>
	<div class="row">
		<div class="col-md-2">
			<c:if test="${empty userList && empty user}">
				<p class="text-warning">未查詢到使用者資訊!</p>
			</c:if>
		</div>
	</div>
	<div class="row">
		<div class="col-md-3">
			<div class="table-responsive">
				<table class="table table-bordered table-hover table-striped table-condensed">
					<c:if test="${requestScope.user != null }">
						<tr>
							<td>id</td>
							<td>userName</td>
							<td>sex</td>
							<td>age</td>
						</tr>
						<tr>
							<td>${user.id }</td>
							<td>${user.userName }</td>
							<td>${user.sex }</td>
							<td>${user.age }</td>
						</tr>
					</c:if>
					<c:if test="${requestScope.userList != null }">
						<tr>
							<td>id</td>
							<td>userName</td>
							<td>sex</td>
							<td>age</td>
						</tr>
						<c:forEach items="${userList }" var="user">
							<tr>
								<td>${user.id }</td>
								<td>${user.userName }</td>
								<td>${user.sex }</td>
								<td>${user.age }</td>
							</tr>
						</c:forEach>
					</c:if>
				</table>
			</div>
		</div>
	</div>
</div>
</body>
</html>

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" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>SSM-Redis</title>
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/bootstrap.min.css">
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
</head>
<script type="text/javascript">
	function addUser(){
		var name = $("#userName");
		var sex = $("#sex");
		var age = $("#age");
		var msg = "";
		
		if ($.trim(name.val()) == ""){
			msg = "姓名不能為空!";
			name.focus();
		}else if ($.trim(sex.val()) == ""){
			msg = "性別不能為空!";
			sex.focus();
		}else if($.trim(age.val()) == ""){
			msg = "年齡不能為空!";
			age.focus();
		}
		
		if(msg != ""){
			alert(msg);
			return false;
		} else {
			$.post("${pageContext.request.contextPath}/UserCRUD/addUser",
					$("#addForm").serialize(),function(data){
						if(data == "OK"){
							alert("新增成功!");
							//window.location.href="${pageContext.request.contextPath}/UserCRUD/showUser";
							//jQuery沒有reset方法,jq物件需要呼叫dom物件的js方法
							$("#addForm")[0].reset();
							window.location.reload();
						} else {
							alert("新增失敗!");
							return false;
						}
				});
		}
	}
	function update(){
		var ids = new Array();
		<c:forEach items="${ids}" var="id">  
			ids.push("${id}");  
    	</c:forEach> 
		var id = $("#mdf_id");
		var name = $("#mdf_userName");
		var sex = $("#mdf_sex");
		var age = $("#mdf_age");
		var flag = false;//標識ID是否有效
		//var flag2 = false;//標識資訊是否有效
		
		if($.trim(id.val()) == ""){
			alert("請指定要更改使用者的ID!");
			id.focus();
			return false
		} else {
			for(var i=0;i<ids.length;i++){
				if($.trim(id.val()) == ids[i]){
					flag = true;
				}
			}
			if(flag==false){
				alert("輸入的ID不存在")
				id.focus();
				return false;
				}
		}
		
		if($.trim(name.val()) == "" && $.trim(sex.val()) == "" && $.trim(age.val()) == ""){
			alert("未進行修改");
			return false;
		} else {
			$.post("${pageContext.request.contextPath}/UserCRUD/editUser",
					{
						id:id.val(),
						name:name.val(),
						sex:sex.val(),
						age:age.val()
					},
					function(data){
						if(data == "OK"){
							alert("資訊修改成功!");
							window.location.href="${pageContext.request.contextPath}/UserCRUD/search?keyWords=" + $.trim(id.val());
						} else {
							alert("資訊修改失敗!");
							return false;
						}
				});
		}
		
	}
	function searchByKeyWords(val) {
		window.location.href = "${pageContext.request.contextPath}/UserCRUD/search?keyWords=" + val;
	}
	function showUsers() {
		window.location.href = "${pageContext.request.contextPath}/UserCRUD/showUser";
	}
	function getUserById(val) {
		window.location.href = "${pageContext.request.contextPath}/UserCRUD/getUserById?userId=" + val;
	}
	function deleteById(id){
		var UID = $("#UID");
		var flag = false;
		if(id == null || id == ""){
			alert("請輸入id!");
			UID.focus();
	    	return false;
		}
		var ids = new Array();
		<c:forEach items="${ids}" var="id">  
			ids.push("${id}");  
    	</c:forEach> 
    	for(var i=0;i<ids.length;i++){
            if(id == ids[i]){
            	flag = true;
            	$.post("${pageContext.request.contextPath}/UserCRUD/delUser/" + id,
						   function(data){
	 						  if(data == "OK"){
	 								alert("使用者刪除成功!");
	 								//window.location.href="${pageContext.request.contextPath}/UserCRUD/showUser";
	 								UID.val("");
	 								window.location.reload();
	 							} else {
	 								alert(data);
	 								return false;
	 							}
				   });
            }
        }
    	if(flag == false){
	    	alert("請輸入正確的id!");
	    	UID.focus();
    	}
    	return false;
	}
	$(function (){
		var text = $("#num").text();
		if(text==null || text == ""){
			window.location.href="${pageContext.request.contextPath}/UserCRUD/indexMSG";
		}
		$("#userName").focus();
	})
</script>
<body style="background: #333">
	<h3>
		<span style="color:#FFFFFF">當前註冊使用者數量(一個小時更新一次):</span>
		<a id="num" href="${pageContext.request.contextPath}/UserCRUD/showUser">${usersCount }</a>
	</h3>
	<hr>
	<div class="container-fluid" style="background-color: #fff">
		<div class="col-md-2">
			<h2 class="page-header">增</h2>
			<form id="addForm" action="" method="post">
				<div class="form-group">
					<label for="userName">姓名</label><span style="color:red"> *</span>
					<input type="text" name="userName" id="userName" placeholder="UserName" class="form-control">
				</div>
				<div class="form-group">
					<label for="sex">性別</label><span style="color:red"> *</span>
					<input type="text" name="sex" id="sex" placeholder="UserSex" class="form-control">
				</div>
				<div class="form-group">
					<label for="age">年齡</label><span style="color:red"> *</span>
					<input type="text" name="age" id="age" placeholder="UserAge" class="form-control">
				</div>
			</form>
			<div class="text-right">
				<button class="btn btn-info" onclick="return addUser();">
					<span class="glyphicon glyphicon-plus"></span> 新增使用者
				</button>
			</div>
		</div>
		<div class="col-md-3">
			<h2 class="page-header">刪</h2>
			<p class="text-muted">現有ID(${fn:length(ids)}個):</p>
			<p class="text-success">
				<c:forEach items="${ids }" var="id">
					<a href="${pageContext.request.contextPath}/UserCRUD/getUserById?userId=${id }">${id } </a>
				</c:forEach>
			</p>
			<div class="form-inline">
				<div class="form-group">
					<div class="input-group">
						<span class="input-group-addon">UID:</span>
						<input type="text" name="UID" id="UID" placeholder="填入上方ID" class="form-control">
					</div>
				</div>
				<button class="btn btn-info" onclick="return deleteById($('#UID').val());">
					<span class="glyphicon glyphicon-remove"></span> 刪除
				</button>
			</div>
		</div>
		<div class="col-md-3">
			<h2 class="page-header">改</h2>
			<form id="updateForm" action="" method="post">
				<div class="form-group">
					<label for="id">UID</label><span style="color:red"> *</span>
					<input type="text" name="mdf_id" id="mdf_id" placeholder="要修改使用者ID" class="form-control">
				</div>
				<div class="form-group">
					<label for="mdf_userName">姓名</label> 
					<input type="text" name="mdf_userName" id="mdf_userName" placeholder="留空則不進行更改" class="form-control">
				</div>
				<div class="form-group">
					<label for="mdf_sex">性別</label> 
					<input type="text" name="mdf_sex" id="mdf_sex" placeholder="留空則不進行更改" class="form-control">
				</div>
				<div class="form-group">
					<label for="mdf_age">年齡</label> 
					<input type="text" name="mdf_age" id="mdf_age" placeholder="留空則不進行更改" class="form-control">
				</div>
			</form>
			<div class="text-right">
				<button class="btn btn-info" onclick="return update();">
					<span class="glyphicon glyphicon-refresh"></span> 更新資訊
				</button>				
			</div>
		</div>
		<div class="col-md-4">
			<h2 class="page-header">查</h2>
			<button class="btn btn-info" onclick="showUsers();">查詢全部</button><br><br>
			<div class="form-inline">
				<div class="form-group">
					<div class="input-group">
						<span class="input-group-addon">關鍵字:</span>
						<input type="text" name="keyWords" id="keyWords" class="form-control">
					</div>
				</div>
				<button class="btn btn-info" onclick="searchByKeyWords($('#keyWords').val());">
					<span class="glyphicon glyphicon-search"></span> 查詢
				</button>
			</div>
			<br>
			<div class="form-inline">
				<div class="form-group">
					<div class="input-group">
						<span class="input-group-addon">UserID:</span>
						<input type="text" name="ById" id="ById" class="form-control">
					</div>
				</div>
				<button class="btn btn-info" onclick="getUserById($('#ById').val());">
					<span class="glyphicon glyphicon-search"></span> 查詢
				</button>
			</div>
		</div>
	</div>
</body>
</html>

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>ldd</groupId>
  <artifactId>SSMRedisDemo</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>SSMRedisDemo Maven Webapp</name>
  <url>http://maven.apache.org</url>
  
	<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>4.2.0.RELEASE</spring.version>
    </properties>

    <dependencies>

        <!-- spring mvc related.....start --> <!-- TODO: replace jackson with fastjson -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.13</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.6.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.6.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.6.1</version>
        </dependency>
        <!-- spring mvc related.....end -->

        <!-- mybatis orm related.....start -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.36</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.3.0</version>
        </dependency>
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>
        <!-- mybatis orm related.....end -->

        <!-- project log related.....start -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <!-- project log related.....end -->

        <!-- redis cache related.....start -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.6.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.7.3</version>
        </dependency>
        <!-- redis cache related.....end -->

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <warSourceDirectory>WebContent</warSourceDirectory>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

效果圖:


然後簡述一下Demo資料需求:

    資料庫很簡單,只有一個user表,屬性有自增的ID,字串型別的使用者名稱、性別,整型的年齡。

對於Demo中需求的資料分為兩種:

    一種是對一致性要求不高的,比如說頁面頭部的統計當前註冊使用者的總數,所以對於這種型別的資料,使用redisTemplate進行讀取,先從redis中讀取,讀取不到的話就從資料庫中讀取,然後存放入redis快取中,並設定生存時間,比如說1小時。

    另一種是對一致性要求較高的,比如說現有的ID,因為這個ID列表需要輸出到首頁,供刪除使用者或者修改使用者資訊時參考,所以像這種不需要設定生存時間的資料,直接使用spring快取放入redis中即可,然後執行增刪改的時候,清空對應快取即可。

快取註解:

    執行到serviceImp時,如果方法的上面有@Cacheable、@CachePut、@CacheEvict註解時,則表示該方法需要spring快取管理,簡單說一下這三個註解,

@Cacheable:表明在進入方法之前,Spring會先去快取伺服器中查詢對應key的快取值,如果找到快取值,那麼Spring將不會再呼叫方法,而是將快取值獨處,返回給呼叫者;如果沒有找到快取值,那麼Spring就會執行你的方法,將最後的結果通過key儲存到快取伺服器中。

@CachePut:表明Spring會將該方法返回的值快取到快取伺服器中,這裡需要注意的是,Spring不會事先去快取伺服器中查詢,而是直接執行方法,然後快取。換句話說,該方法始終會被Spring所呼叫。

@CacheEvict:表示執行方法後從快取伺服器移除對應key的值;

一般而言,對於查詢,我們會考慮@Cacheable;對於插入和修改我們會考慮使用@CachePut;對於刪除,我們會考慮@CacheEvict;

具體的使用方法可以請參考spring文件:

僅用於學習記憶與總結,如有錯誤的地方還請各位指出。

相關推薦

SSM整合Redis快取(完整Demo)

之前一段時間自學了Redis,進行一下總結三個部分:    1. Linux環境下的redis客戶端操作    2. 在java程式中使用redis:        2.1)匯入jedis.jar包        2.2)直接 Jedis jedis = new Jedis(

springboot 整合redis 快取

  一、新增依賴jar包 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-re

Maven+SSM使用redis快取 Spring5(JavaConfig註解配置)

1. 配置環境 Redis 4 安裝教程自行google Spring 5.0.9 Mybatis 3.4.6 2. 依賴 注意: 預設你配置好了SSM的依賴環境,我只說在SSM配好過後怎麼把redis加進去 我用的依賴是如下的版本,基本都沒有最新jar包

SSM+redis整合(mybatis整合redis二級快取)

SSM:是Spring+Struts+Mybatis ,另外還使用了PageHelper    前言:   這裡主要是利用redis去做mybatis的二級快取,mybaits對映檔案中所有的select都會重新整理已有快取,如果不存在就會新建快取,所有的insert,update操作都

Spring整合redis帶測試用例Demo完整程式碼

專案結構 jar包 <!--redis--> <dependency> <groupId>redis.clients</groupId> <artifa

SSM整合Redis,用快取減少對資料庫的訪問次數?

資料: 一、首先匯入依賴: <spring-version>4.3.13.RELEASE</spring-version> <mybatis-version>3.4.5</mybatis-version>

springboot2.x 和用redis快取整合,有專案地址的呦

1. springboot和用redis做快取的整合 這裡要整合的是springboot2.x和redis,所以你要把你的springboot 版本在開始之前換成springboot2.0之後的 具體怎麼換其實就是換一下版本號,不換的話後面會有很多問題,樓主踩了無數坑 專案地

springboot整合mybatis,mysql資料庫儲存,redis快取

redis應用的場景通過快取來減少對關係型資料庫的查詢次數,減輕資料庫壓力。在執行DAO類的select***(), query***()方法時,先從Redis中查詢有沒有快取資料,如果有則直接從Redis拿到結果,如果沒有再向資料庫發起查詢請求取資料。springboot已

Spring Boot整合redis資料快取

package com.fcc.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.faste

spring-boot-route(十二)整合redis快取

## redis簡介 redis作為一種非關係型資料庫,讀寫非常快,應用十分廣泛,它採用key-value的形式儲存資料,value常用的五大資料型別有string(字串),list(連結串列),set(集合),zset(有序集合)和hash(雜湊表)。 redis的特性決定了它的功能,它可以用來做以下這

Spring整合Redis數據緩存(Windows環境)

端口號 init 技術分享 factory redis-cli @service tab long 配置 當我們一個項目的數據量很大的時候,就需要做一些緩存機制來減輕數據庫的壓力,提升應用程序的性能,對於java項目來說,最常用的緩存組件有Redis、Ehcache和Mem

springboot整合redis實現快取

使用redis做快取整合起來並不難,在整合的時候一定要將show sql開啟,這樣才能測試你寫整合的redis快取是否成功了。首先,你需要在官網下載一個redis,然後啟動redis-server,預設埠是6379,啟動後的介面如下:   redis在springboot

2018 SSM 整合 Redis

一、pom.xml 二、redis.properties 三、spring-redis.xml 四、工具類 1.RedisCache.java 2.RedisCacheTransfer 3.RedisUtil 五、測試 一、pom.xml <!--

SSM整合Redis連線不上

1.關閉Redis的保護機制         2.關閉防火牆 firewall-cmd --state #檢視預設防火牆狀態(關閉後顯示notrunning,開啟後顯示running)  關閉防火牆: sys

使用redis快取的單機、叢集版的簡單使用

一.簡介與安裝 Redis是c語言開發的。(裝c語言環境、解壓、編譯、安裝)埠號6379 很多專案中,為了緩解我們伺服器與資料庫的壓力,我們使用快取。 安裝redis需要c語言的編譯環境。如果沒有gcc需要線上安裝。yum install gcc-c++ 安裝步驟: 第一步:re

精通SpringBoot——第七篇:整合Redis實現快取

專案中用到快取是很常見的事情, 快取能夠提升系統訪問的速度,減輕對資料庫的壓力等好處。今天我們來講講怎麼在spring boot 中整合redis 實現對資料庫查詢結果的快取。 首先第一步要做的就是在pom.xml檔案新增spring-boot-starter-data-redis。 要整合快取,必

ssm整合redis(二)

在spring中整合redis很簡單,這裡用的是ssm框架+maven構建的專案。 首先是需要引入的pom.xml檔案: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://w

Springboot之使用Redis快取資料

一、新增Redis依賴 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.o

學習yijun zhang 老師的商品秒殺專案所得(1)——使用Redis快取優化的簡單實現

主要使用的功能: 1.基於java的redis工具——Jedis 2.JDK本身提供的序列化方式——實現Serializable 3.實現序列化要用到的IO流——ByteArrayInputStream,ByteArrayOutputStream,ObjectI

Spring boot如何使用redis快取快取註解的用法總結

1. 概述 本文介紹Spring boot 如何使用redis做快取,如何對redis快取進行定製化配置(如key的有效期)以及spring boot 如