Authored by hugufei

使用SerializerFeature.DisableCircularReferenceDetect解决同个对象的序列化问题

package com.yoho.search.cache.beans;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
import com.yoho.search.base.utils.MD5Util;
import com.yoho.search.cache.impls.EhCache;
... ... @@ -77,7 +78,7 @@ public abstract class AbstractCacheComponent<T> {
if (!useRedis()) {
return;
}
String jsonString = JSON.toJSONString(result);
String jsonString = JSON.toJSONString(result, SerializerFeature.WriteMapNullValue,SerializerFeature.DisableCircularReferenceDetect);
CacheObject toCacheResult = new CacheObject(jsonString);
searchRedis.addOrUpdate(redisKeyBuilder, toCacheResult, this.cacheTimeInMinute());
}
... ...
package com.yoho.search.cache.beans;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
... ... @@ -20,116 +19,114 @@ import java.lang.reflect.Type;
@Service
public class SearchCacheService {
@Autowired
private SearchServiceConfiger searchServiceConfiger;
@Autowired
private SearchServiceConfiger searchServiceConfiger;
private void addObjectToCache(RedisKeyBuilder redisKeyBuilder, Object object, SearchCache searchCache) {
// 1、如果不适用缓存,则直接返回
if (!searchServiceConfiger.useCache()) {
return;
}
// 2、如果缓存不存在,则直接返回
if (searchCache == null || searchCache.getCache() == null) {
return;
}
// 3、加入缓存
CacheObject cacheObject = null;
if (object instanceof JSONObject) {
cacheObject = new CacheObject((JSONObject) object);
} else if (object instanceof JSONArray) {
cacheObject = new CacheObject((JSONArray) object);
} else {
cacheObject = new CacheObject(object);
}
searchCache.getCache().addOrUpdate(redisKeyBuilder, cacheObject, searchCache.getCacheInMinute());
}
private void addObjectToCache(RedisKeyBuilder redisKeyBuilder, Object object, SearchCache searchCache) {
// 1、如果不适用缓存,则直接返回
if (!searchServiceConfiger.useCache()) {
return;
}
// 2、如果缓存不存在,则直接返回
if (searchCache == null || searchCache.getCache() == null) {
return;
}
// 3、加入缓存
CacheObject cacheObject = null;
if (object instanceof JSONObject) {
cacheObject = new CacheObject((JSONObject) object);
} else {
cacheObject = new CacheObject(object);
}
searchCache.getCache().addOrUpdate(redisKeyBuilder, cacheObject, searchCache.getCacheInMinute());
}
/**
* 从缓存中取数据
*
* @param redisKeyBuilder
* @return
*/
private CacheObject getCacheObjectFromCache(RedisKeyBuilder redisKeyBuilder, SearchCache searchCache) {
// 1、如果不适用缓存,则直接返回
if (!searchServiceConfiger.useCache()) {
return null;
}
// 2、如果缓存不存在,则直接返回
if (searchCache == null || searchCache.getCache() == null) {
return null;
}
// 3、增加缓存访问次数
searchCache.incTotalCount();
/**
* 从缓存中取数据
*
* @param redisKeyBuilder
* @return
*/
private CacheObject getCacheObjectFromCache(RedisKeyBuilder redisKeyBuilder, SearchCache searchCache) {
// 1、如果不适用缓存,则直接返回
if (!searchServiceConfiger.useCache()) {
return null;
}
// 2、如果缓存不存在,则直接返回
if (searchCache == null || searchCache.getCache() == null) {
return null;
}
// 3、增加缓存访问次数
searchCache.incTotalCount();
// 4、从缓存中获取cacheObject
CacheObject cacheObject = searchCache.getCache().get(redisKeyBuilder);
// 4、从缓存中获取cacheObject
CacheObject cacheObject = searchCache.getCache().get(redisKeyBuilder);
// 5、如果从缓存中拿不到数据,则直接返回
if (cacheObject == null) {
return null;
}
// 6、增加缓存命中次数,并返回缓存对象
searchCache.incMatchCount();
return cacheObject;
}
// 5、如果从缓存中拿不到数据,则直接返回
if (cacheObject == null) {
return null;
}
// 6、增加缓存命中次数,并返回缓存对象
searchCache.incMatchCount();
return cacheObject;
}
/*********************************** JSONObject *****************************************/
public RedisKeyBuilder genSearchParamString(String indexName, SearchParam searchParam) {
//1、拼装内容
StringBuilder redisKeyValue = new StringBuilder();
redisKeyValue.append("indexName:").append(indexName).append(';');
redisKeyValue.append("searchType:").append(searchParam.getSearchType() == null ? "" : searchParam.getSearchType().name()).append(';');
SearchSourceBuilder searchSourceBuilder = SearchParamUtils.genSearchSourceBuilderFromSearchParam(searchParam);
redisKeyValue.append("searchSource:").append(searchSourceBuilder).append(';');
/*********************************** JSONObject *****************************************/
public RedisKeyBuilder genSearchParamString(String indexName, SearchParam searchParam) {
//1、拼装内容
StringBuilder redisKeyValue = new StringBuilder();
redisKeyValue.append("indexName:").append(indexName).append(';');
redisKeyValue.append("searchType:").append(searchParam.getSearchType() == null ? "" : searchParam.getSearchType().name()).append(';');
SearchSourceBuilder searchSourceBuilder = SearchParamUtils.genSearchSourceBuilderFromSearchParam(searchParam);
redisKeyValue.append("searchSource:").append(searchSourceBuilder).append(';');
//2、构建RedisKeyBuilder
RedisKeyBuilder redisKeyBuilder = RedisKeyBuilder.newInstance();
redisKeyBuilder.appendFixed("YOHOSEARCH:");
redisKeyBuilder.appendFixed("DEFAULT1:");
redisKeyBuilder.appendVar(MD5Util.string2MD5(redisKeyValue.toString()));
return redisKeyBuilder;
}
//2、构建RedisKeyBuilder
RedisKeyBuilder redisKeyBuilder = RedisKeyBuilder.newInstance();
redisKeyBuilder.appendFixed("YOHOSEARCH:");
redisKeyBuilder.appendFixed("DEFAULT1:");
redisKeyBuilder.appendVar(MD5Util.string2MD5(redisKeyValue.toString()));
return redisKeyBuilder;
}
public void addJSONObjectToCache(SearchCache searchCache, String indexName, SearchParam searchParam, JSONObject jsonObject) {
RedisKeyBuilder key = this.genSearchParamString(indexName, searchParam);
this.addObjectToCache(key, jsonObject, searchCache);
}
public void addJSONObjectToCache(SearchCache searchCache, String indexName, SearchParam searchParam, JSONObject jsonObject) {
RedisKeyBuilder key = this.genSearchParamString(indexName, searchParam);
this.addObjectToCache(key, jsonObject, searchCache);
}
public JSONObject getJSONObjectFromCache(SearchCache searchCache, String indexName, SearchParam searchParam) {
RedisKeyBuilder key = this.genSearchParamString(indexName, searchParam);
CacheObject cacheObject = this.getCacheObjectFromCache(key, searchCache);
if (cacheObject == null) {
return null;
}
return cacheObject.toJSONObject();
}
public JSONObject getJSONObjectFromCache(SearchCache searchCache, String indexName, SearchParam searchParam) {
RedisKeyBuilder key = this.genSearchParamString(indexName, searchParam);
CacheObject cacheObject = this.getCacheObjectFromCache(key, searchCache);
if (cacheObject == null) {
return null;
}
return cacheObject.toJSONObject();
}
/*********************************** object *****************************************/
public <T> T getSerializableObjectFromCache(SearchCache searchCache, RedisKeyBuilder redisKeyBuilder, Type type, boolean useJsonSerializable) {
try {
CacheObject cacheObject = this.getCacheObjectFromCache(redisKeyBuilder, searchCache);
if (cacheObject == null) {
return null;
}
if (useJsonSerializable) {
String stringValue = (String)cacheObject.toObject();
return JSON.parseObject(stringValue, type);
} else {
return (T) cacheObject.getValue();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/*********************************** object *****************************************/
public <T> T getSerializableObjectFromCache(SearchCache searchCache, RedisKeyBuilder redisKeyBuilder, Type type, boolean useJsonSerializable) {
try {
CacheObject cacheObject = this.getCacheObjectFromCache(redisKeyBuilder, searchCache);
if (cacheObject == null) {
return null;
}
if (useJsonSerializable) {
String stringValue = (String) cacheObject.toObject();
return JSON.parseObject(stringValue, type);
} else {
return (T) cacheObject.getValue();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public <T> void addSerializableObjectToCache(SearchCache searchCache, RedisKeyBuilder redisKeyBuilder, T object, boolean useJsonSerializable) {
if (useJsonSerializable) {
String jsonStr = JSON.toJSONString(object,SerializerFeature.WriteMapNullValue,SerializerFeature.DisableCircularReferenceDetect);
this.addObjectToCache(redisKeyBuilder, jsonStr, searchCache);
} else {
this.addObjectToCache(redisKeyBuilder, object, searchCache);
}
}
public <T> void addSerializableObjectToCache(SearchCache searchCache, RedisKeyBuilder redisKeyBuilder, T object, boolean useJsonSerializable) {
if (useJsonSerializable) {
String jsonStr = JSON.toJSONString(object, SerializerFeature.WriteMapNullValue, SerializerFeature.DisableCircularReferenceDetect);
this.addObjectToCache(redisKeyBuilder, jsonStr, searchCache);
} else {
this.addObjectToCache(redisKeyBuilder, object, searchCache);
}
}
}
... ...
package com.yoho.search.cache.model;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.io.Serializable;
/**
* 暂时只支持JSONObject和jsonArray
*
* @author hugufei
*
*/
public class CacheObject implements Serializable {
private static final long serialVersionUID = -3949382156604252137L;
private String type;
private Object value;
public CacheObject() {
}
public CacheObject(Object object) {
super();
this.type = "Object";
this.value = object;
}
public CacheObject(JSONObject jsonObject) {
super();
this.type = "JSONObject";
this.value = JSON.toJSONString(jsonObject, SerializerFeature.WriteMapNullValue);
}
public CacheObject(JSONArray jsonArray) {
super();
this.type = "JSONArray";
this.value = JSON.toJSONString(jsonArray, SerializerFeature.WriteMapNullValue);
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public JSONObject toJSONObject() {
try {
if (value == null) {
return null;
}
if ("JSONObject".equals(type)) {
return JSON.parseObject(value.toString());
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public JSONArray toJSONArray() {
try {
if (value == null) {
return null;
}
if ("JSONArray".equals(type)) {
return JSON.parseArray(value.toString());
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public Object toObject() {
try {
if (value == null) {
return null;
}
if ("Object".equals(type)) {
return value;
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
package com.yoho.search.cache.model;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.io.Serializable;
/**
* 暂时只支持JSONObject和jsonArray
*
* @author hugufei
*
*/
public class CacheObject implements Serializable {
private static final long serialVersionUID = -3949382156604252137L;
private String type;
private Object value;
public CacheObject() {
}
public CacheObject(Object object) {
super();
this.type = "Object";
this.value = object;
}
public CacheObject(JSONObject jsonObject) {
super();
this.type = "JSONObject";
this.value = JSON.toJSONString(jsonObject, SerializerFeature.WriteMapNullValue,SerializerFeature.DisableCircularReferenceDetect);
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public JSONObject toJSONObject() {
try {
if (value == null) {
return null;
}
if ("JSONObject".equals(type)) {
return JSON.parseObject(value.toString());
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public Object toObject() {
try {
if (value == null) {
return null;
}
if ("Object".equals(type)) {
return value;
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
... ...