1、spring相關配置如下:
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="${redis.pool.maxIdle}" /> <!-- 最大能夠保持idel狀態的對象數 --> <property name="maxTotal" value="${redis.pool.maxTotal}" /> <!-- 最大分配的對象數 --> <property name="testOnBorrow" value="${redis.pool.testOnBorrow}" /> <!-- 當調用borrow Object方法時,是否進行有效性檢查 --> </bean> <!-- sprin_data_redis 單機配置 --> <bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" > <property name="hostName" value="${redis.host}" /> <property name="port" value="${redis.port}" /> <property name="timeout" value="${redis.timeout}" /> <property name="password" value="${redis.password}" /> <property name="poolConfig" ref="jedisPoolConfig" /> </bean> <!-- key序列化 --> <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" /> <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" p:connectionFactory-ref="jedisConnFactory" /> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connectionFactory-ref="jedisConnFactory" p:keySerializer-ref="stringRedisSerializer" p:hashKeySerializer-ref="stringRedisSerializer" /> <!-- spring自己的緩存管理器 --> <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager"> <property name="caches"> <set> <bean class="com.rd.ifaes.common.jedis.RdRedisCache" p:redis-template-ref="redisTemplate" p:name="sysCache"/> </set> </property> </bean> <!-- 啓用緩存註解功能,這個是必須的,否則註解不會生效,另外,該註解一定要聲明在spring主配置文件中才會生效 --> <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true" />
2、緩存工具類CacheUtils
package com.lh.core.core.util;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.CollectionUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rd.ifaes.common.dict.ExpireTime;
import com.lh.common.util.JsonMapper;
import com.rd.ifaes.common.util.SpringContextHolder;
import com.rd.ifaes.common.util.StringUtils;
/**
* 通用緩存工具類
* @author lh
* @version 3.0
* @since 2016-6-22
*
*/
public class CacheUtils {
private static StringRedisTemplate stringRedisTemplate = SpringContextHolder.getBean("stringRedisTemplate");
private static RedisTemplate<String, Object> redisTemplate = SpringContextHolder.getBean("redisTemplate");
/**
* 刪除緩存<br>
* 根據key精確匹配刪除
* @param key
*/
@SuppressWarnings("unchecked")
public static void del(String... key){
if(key!=null && key.length > 0){
if(key.length == 1){
redisTemplate.delete(key[0]);
}else{
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
/**
* 批量刪除<br>
* (該操作會執行模糊查詢,請儘量不要使用,以免影響性能或誤刪)
* @param pattern
*/
public static void batchDel(String... pattern){
for (String kp : pattern) {
redisTemplate.delete(redisTemplate.keys(kp + "*"));
}
}
/**
* 取得緩存(int型)
* @param key
* @return
*/
public static Integer getInt(String key){
String value = stringRedisTemplate.boundValueOps(key).get();
if(StringUtils.isNotBlank(value)){
return Integer.valueOf(value);
}
return null;
}
/**
* 取得緩存(字符串類型)
* @param key
* @return
*/
public static String getStr(String key){
return stringRedisTemplate.boundValueOps(key).get();
}
/**
* 取得緩存(字符串類型)
* @param key
* @return
*/
public static String getStr(String key, boolean retain){
String value = stringRedisTemplate.boundValueOps(key).get();
if(!retain){
redisTemplate.delete(key);
}
return value;
}
/**
* 獲取緩存<br>
* 注:基本數據類型(Character除外),請直接使用get(String key, Class<T> clazz)取值
* @param key
* @return
*/
public static Object getObj(String key){
return redisTemplate.boundValueOps(key).get();
}
/**
* 獲取緩存<br>
* 注:java 8種基本類型的數據請直接使用get(String key, Class<T> clazz)取值
* @param key
* @param retain 是否保留
* @return
*/
public static Object getObj(String key, boolean retain){
Object obj = redisTemplate.boundValueOps(key).get();
if(!retain){
redisTemplate.delete(key);
}
return obj;
}
/**
* 獲取緩存<br>
* 注:該方法暫不支持Character數據類型
* @param key key
* @param clazz 類型
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T get(String key, Class<T> clazz) {
return (T)redisTemplate.boundValueOps(key).get();
}
/**
* 獲取緩存json對象<br>
* @param key key
* @param clazz 類型
* @return
*/
public static <T> T getJson(String key, Class<T> clazz) {
return JsonMapper.fromJsonString(stringRedisTemplate.boundValueOps(key).get(), clazz);
}
/**
* 將value對象寫入緩存
* @param key
* @param value
* @param time 失效時間(秒)
*/
public static void set(String key,Object value,ExpireTime time){
if(value.getClass().equals(String.class)){
stringRedisTemplate.opsForValue().set(key, value.toString());
}else if(value.getClass().equals(Integer.class)){
stringRedisTemplate.opsForValue().set(key, value.toString());
}else if(value.getClass().equals(Double.class)){
stringRedisTemplate.opsForValue().set(key, value.toString());
}else if(value.getClass().equals(Float.class)){
stringRedisTemplate.opsForValue().set(key, value.toString());
}else if(value.getClass().equals(Short.class)){
stringRedisTemplate.opsForValue().set(key, value.toString());
}else if(value.getClass().equals(Long.class)){
stringRedisTemplate.opsForValue().set(key, value.toString());
}else if(value.getClass().equals(Boolean.class)){
stringRedisTemplate.opsForValue().set(key, value.toString());
}else{
redisTemplate.opsForValue().set(key, value);
}
if(time.getTime() > 0){
redisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
}
}
/**
* 將value對象以JSON格式寫入緩存
* @param key
* @param value
* @param time 失效時間(秒)
*/
public static void setJson(String key,Object value,ExpireTime time){
stringRedisTemplate.opsForValue().set(key, JsonMapper.toJsonString(value));
if(time.getTime() > 0){
stringRedisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
}
}
/**
* 更新key對象field的值
* @param key 緩存key
* @param field 緩存對象field
* @param value 緩存對象field值
*/
public static void setJsonField(String key, String field, String value){
JSONObject obj = JSON.parseObject(stringRedisTemplate.boundValueOps(key).get());
obj.put(field, value);
stringRedisTemplate.opsForValue().set(key, obj.toJSONString());
}
/**
* 遞減操作
* @param key
* @param by
* @return
*/
public static double decr(String key, double by){
return redisTemplate.opsForValue().increment(key, -by);
}
/**
* 遞增操作
* @param key
* @param by
* @return
*/
public static double incr(String key, double by){
return redisTemplate.opsForValue().increment(key, by);
}
/**
* 獲取double類型值
* @param key
* @return
*/
public static double getDouble(String key) {
String value = stringRedisTemplate.boundValueOps(key).get();
if(StringUtils.isNotBlank(value)){
return Double.valueOf(value);
}
return 0d;
}
/**
* 設置double類型值
* @param key
* @param value
* @param time 失效時間(秒)
*/
public static void setDouble(String key, double value, ExpireTime time) {
stringRedisTemplate.opsForValue().set(key, String.valueOf(value));
if(time.getTime() > 0){
stringRedisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
}
}
/**
* 設置double類型值
* @param key
* @param value
* @param time 失效時間(秒)
*/
public static void setInt(String key, int value, ExpireTime time) {
stringRedisTemplate.opsForValue().set(key, String.valueOf(value));
if(time.getTime() > 0){
stringRedisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
}
}
/**
* 將map寫入緩存
* @param key
* @param map
* @param time 失效時間(秒)
*/
public static <T> void setMap(String key, Map<String, T> map, ExpireTime time){
redisTemplate.opsForHash().putAll(key, map);
}
/**
* 將map寫入緩存
* @param key
* @param map
* @param time 失效時間(秒)
*/
@SuppressWarnings("unchecked")
public static <T> void setMap(String key, T obj, ExpireTime time){
Map<String, String> map = (Map<String, String>)JsonMapper.parseObject(obj, Map.class);
redisTemplate.opsForHash().putAll(key, map);
}
/**
* 向key對應的map中添加緩存對象
* @param key
* @param map
*/
public static <T> void addMap(String key, Map<String, T> map){
redisTemplate.opsForHash().putAll(key, map);
}
/**
* 向key對應的map中添加緩存對象
* @param key cache對象key
* @param field map對應的key
* @param value 值
*/
public static void addMap(String key, String field, String value){
redisTemplate.opsForHash().put(key, field, value);
}
/**
* 向key對應的map中添加緩存對象
* @param key cache對象key
* @param field map對應的key
* @param obj 對象
*/
public static <T> void addMap(String key, String field, T obj){
redisTemplate.opsForHash().put(key, field, obj);
}
/**
* 獲取map緩存
* @param key
* @param clazz
* @return
*/
public static <T> Map<String, T> mget(String key, Class<T> clazz){
BoundHashOperations<String, String, T> boundHashOperations = redisTemplate.boundHashOps(key);
return boundHashOperations.entries();
}
/**
* 獲取map緩存
* @param key
* @param clazz
* @return
*/
public static <T> T getMap(String key, Class<T> clazz){
BoundHashOperations<String, String, String> boundHashOperations = redisTemplate.boundHashOps(key);
Map<String, String> map = boundHashOperations.entries();
return JsonMapper.parseObject(map, clazz);
}
/**
* 獲取map緩存中的某個對象
* @param key
* @param field
* @param clazz
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getMapField(String key, String field, Class<T> clazz){
return (T)redisTemplate.boundHashOps(key).get(field);
}
/**
* 刪除map中的某個對象
* @author lh
* @date 2016年8月10日
* @param key map對應的key
* @param field map中該對象的key
*/
public void delMapField(String key, String... field){
BoundHashOperations<String, String, ?> boundHashOperations = redisTemplate.boundHashOps(key);
boundHashOperations.delete(field);
}
/**
* 指定緩存的失效時間
*
* @author FangJun
* @date 2016年8月14日
* @param key 緩存KEY
* @param time 失效時間(秒)
*/
public static void expire(String key, ExpireTime time) {
if(time.getTime() > 0){
redisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
}
}
/**
* 添加set
* @param key
* @param value
*/
public static void sadd(String key, String... value) {
redisTemplate.boundSetOps(key).add(value);
}
/**
* 刪除set集合中的對象
* @param key
* @param value
*/
public static void srem(String key, String... value) {
redisTemplate.boundSetOps(key).remove(value);
}
/**
* set重命名
* @param oldkey
* @param newkey
*/
public static void srename(String oldkey, String newkey){
redisTemplate.boundSetOps(oldkey).rename(newkey);
}
/**
* 短信緩存
* @author fxl
* @date 2016年9月11日
* @param key
* @param value
* @param time
*/
public static void setIntForPhone(String key,Object value,int time){
stringRedisTemplate.opsForValue().set(key, JsonMapper.toJsonString(value));
if(time > 0){
stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
}
}
/**
* 模糊查詢keys
* @param pattern
* @return
*/
public static Set<String> keys(String pattern){
return redisTemplate.keys(pattern);
}
}
3、JsonMaper
package com.lh.common.util;
import java.io.IOException;
import java.util.TimeZone;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
/**
* 簡單封裝Jackson,實現JSON String<->Java Object的Mapper.
*
*/
public class JsonMapper extends ObjectMapper {
private static final long serialVersionUID = 1L;
private final static Logger LOGGER = LoggerFactory.getLogger(JsonMapper.class);
private static JsonMapper mapper;
public JsonMapper() {
this(Include.NON_EMPTY);
}
public JsonMapper(Include include) {
// 設置輸出時包含屬性的風格
if (include != null) {
this.setSerializationInclusion(include);
}
// 設置輸入時忽略在JSON字符串中存在但Java對象實際沒有的屬性
this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 空值處理爲空串
this.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>(){
@Override
public void serialize(Object value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeString("");
}
});
// 進行HTML解碼。
this.registerModule(new SimpleModule().addSerializer(String.class, new JsonSerializer<String>(){
@Override
public void serialize(String value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeString(StringEscapeUtils.unescapeHtml4(value));
}
}));
// 設置時區
this.setTimeZone(TimeZone.getDefault());//getTimeZone("GMT+8:00")
}
/**
* 創建只輸出非Null且非Empty(如List.isEmpty)的屬性到Json字符串的Mapper,建議在外部接口中使用.
*/
public static JsonMapper getInstance() {
if (mapper == null){
mapper = new JsonMapper().enableSimple();
}
return mapper;
}
/**
* 創建只輸出初始值被改變的屬性到Json字符串的Mapper, 最節約的存儲方式,建議在內部接口中使用。
*/
public static JsonMapper nonDefaultMapper() {
if (mapper == null){
mapper = new JsonMapper(Include.NON_DEFAULT);
}
return mapper;
}
/**
* Object可以是POJO,也可以是Collection或數組。
* 如果對象爲Null, 返回"null".
* 如果集合爲空集合, 返回"[]".
*/
public String toJson(Object object) {
try {
return this.writeValueAsString(object);
} catch (IOException e) {
if(LOGGER.isWarnEnabled()){
LOGGER.warn("write to json string error:" + object, e);
}
return null;
}
}
/**
* 反序列化POJO或簡單Collection如List<String>.
*
* 如果JSON字符串爲Null或"null"字符串, 返回Null.
* 如果JSON字符串爲"[]", 返回空集合.
*
* 如需反序列化複雜Collection如List<MyBean>, 請使用fromJson(String,JavaType)
* @see #fromJson(String, JavaType)
*/
public <T> T fromJson(String jsonString, Class<T> clazz) {
if (StringUtils.isEmpty(jsonString)) {
return null;
}
try {
return this.readValue(jsonString, clazz);
} catch (IOException e) {
if(LOGGER.isWarnEnabled()){
LOGGER.warn("parse json string error:" + jsonString, e);
}
return null;
}
}
/**
* 反序列化複雜Collection如List<Bean>, 先使用函數createCollectionType構造類型,然後調用本函數.
* @see #createCollectionType(Class, Class...)
*/
@SuppressWarnings("unchecked")
public <T> T fromJson(String jsonString, JavaType javaType) {
if (StringUtils.isEmpty(jsonString)) {
return null;
}
try {
return (T) this.readValue(jsonString, javaType);
} catch (IOException e) {
if(LOGGER.isWarnEnabled()){
LOGGER.warn("parse json string error:" + jsonString, e);
}
return null;
}
}
/**
* 構造泛型的Collection Type如:
* ArrayList<MyBean>, 則調用constructCollectionType(ArrayList.class,MyBean.class)
* HashMap<String,MyBean>, 則調用(HashMap.class,String.class, MyBean.class)
*/
public JavaType createCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
return this.getTypeFactory().constructParametricType(collectionClass, elementClasses);
}
/**
* 當JSON裡只含有Bean的部分屬性時,更新一個已存在Bean,只覆蓋該部分的屬性.
*/
@SuppressWarnings("unchecked")
public <T> T update(String jsonString, T object) {
try {
return (T) this.readerForUpdating(object).readValue(jsonString);
} catch (JsonProcessingException e) {
if(LOGGER.isWarnEnabled()){
LOGGER.warn("update json string:" + jsonString + " to object:" + object + " error.", e);
}
} catch (IOException e) {
if(LOGGER.isWarnEnabled()){
LOGGER.warn("update json string:" + jsonString + " to object:" + object + " error.", e);
}
}
return null;
}
/**
* 輸出JSONP格式數據.
*/
public String toJsonP(String functionName, Object object) {
return toJson(new JSONPObject(functionName, object));
}
/**
* 設定是否使用Enum的toString函數來讀寫Enum,
* 為False時時使用Enum的name()函數來讀寫Enum, 默認為False.
* 注意本函數一定要在Mapper創建後, 所有的讀寫動作之前調用.
*/
public JsonMapper enableEnumUseToString() {
this.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
this.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
return this;
}
/**
* 支持使用Jaxb的Annotation,使得POJO上的annotation不用與Jackson耦合。
* 默認會先查找jaxb的annotation,如果找不到再找jackson的。
*/
public JsonMapper enableJaxbAnnotation() {
JaxbAnnotationModule module = new JaxbAnnotationModule();
this.registerModule(module);
return this;
}
/**
* 允許單引號
* 允許不帶引號的字段名稱
*/
public JsonMapper enableSimple() {
this.configure(Feature.ALLOW_SINGLE_QUOTES, true);
this.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
return this;
}
/**
* 取出Mapper做進一步的設置或使用其他序列化API.
*/
public ObjectMapper getMapper() {
return this;
}
/**
* 對象轉換爲JSON字符串
* @param object
* @return
*/
public static String toJsonString(Object object){
return JsonMapper.getInstance().toJson(object);
}
/**
* JSON字符串轉換爲對象
* @param jsonString
* @param clazz
* @return
*/
public static <T> T fromJsonString(String jsonString, Class<T> clazz){
return JsonMapper.getInstance().fromJson(jsonString, clazz);
}
/**
* 將obj對象轉換成 class類型的對象
* @param obj
* @param clazz
* @return
*/
public static <T> T parseObject(Object obj, Class<T> clazz){
return JSON.parseObject(JSON.toJSONString(obj), clazz);
}
}