2017-08-25 11:05
@JFinal 今天刚发现这个问题,
如果使用FstSerializer,虽然无法与hincrBy()混合使用,但是序列化与反序列化时保存了"类型信息",存一个Integer,使用hgetAll()时类型一定是Integer
如果使用MyFstSerializer,虽然可以与hincrBy()混合使用,若存一个Integer,但是序列化时:keyToBytes(String.valueOf(value))存放的是String,自然hgetAll()返回的也是String
又看了一下Jedis的方法,方法签名为: public String hmset(final String key, final Map hash),也即Jedis存放的值全部当作String,无类型区分
总结:cache使用FstSerializer就是"封装"了使用Jedis存取数据时的"类型转换",缺点是无法与hincrBy()等方法混合使用,现在使用MyFstSerializer等于将cache封装的"类型转换"暴露出来,由应用程序处理,有利也有弊
2017-08-22 14:57
源代码修改如下:
public class MyFstSerializer implements ISerializer {
	public static final ISerializer me = new MyFstSerializer();
	private ISerializer subject = FstSerializer.me;
	private static final Set NOT_SERIALIZER_SET = new HashSet() {
		private static final long serialVersionUID = 2303504492407898281L;
		{
			add(Integer.class);
			add(Integer.TYPE);
			add(Long.class);
			add(Long.TYPE);
			add(Float.class);
			add(Float.TYPE);
			add(Double.class);
			add(Double.TYPE);
		}
	};
	@Override
	public byte[] keyToBytes(String key) {
		return FstSerializer.me.keyToBytes(key);
	}
	@Override
	public String keyFromBytes(byte[] bytes) {
		return subject.keyFromBytes(bytes);
	}
	@Override
	public byte[] fieldToBytes(Object field) {
		return valueToBytes(field);
	}
	@Override
	public Object fieldFromBytes(byte[] bytes) {
		return valueFromBytes(bytes);
	}
	@Override
	public byte[] valueToBytes(Object value) {
		if (NOT_SERIALIZER_SET.contains(value.getClass())) {
			return keyToBytes(String.valueOf(value));
		}
		return subject.valueToBytes(value);
	}
	/**
	 * 反序列化,利用FstSerializer解析,出错则利用keyFromBytes解析
	 * @param bytes
	 * @return
	 */
	@Override
	public Object valueFromBytes(byte[] bytes) {
		try {
			return subject.valueFromBytes(bytes);
		} catch (Exception e) {
			return keyFromBytes(bytes);
		}
	}
}
修改:
1.使用了NOT_SERIALIZER_SET,仿照RestInterceptor,方便修改
2.将ISerializer设置为一变量,方便修改
2017-08-14 18:40
@JFinal 站长,我找到了新的解决方法了  : )
http://www.jfinal.com/share/389
2017-08-09 15:51
@JFinal 那用hmset就没有办法存放hash的value是integer的情况,如果一个record中有的value是integer,有的value不是integer,那就需要hmset存放所有域,然后用hdel删除value是integer的域,然后再使用hincrBy存放integer的域,这样需要三个操作,有没有简便一点的方法?
2017-07-01 18:12
上面哪个问题算是解决了,但是解决方式非常丑,我是直接修改了InterceptorManager源码,因为InterceptorManager的构造器是private的,没法继承
另:我是用的idea,在自己的项目中建了与框架中InterceptorManager相同的包名,相同的类名,编译可以通过,没有报类冲突,运行时直接使用了项目中的InterceptorManager类
备注:至于站长说的继承InterceptorStack,还没有研究,有时间再说(可能不会有时间了~~),以后若有优雅的方法再行整理
以下是修改后的InterceptorManager源码,
/**
	 * 修改此方法实现多重拦截
	 * 但是遇到循环拦截会无穷递归(一定不要循环拦截)
	 * @param interceptorClasses
	 * @return
	 */
	public Interceptor[] createInterceptor(
			Class[] interceptorClasses) {
		if (interceptorClasses == null || interceptorClasses.length == 0) {
			return NULL_INTERS;
		}
		// 使用List存放在action之前的拦截器,因为可能有多重拦截,长度不确定
		List interceptorList = new ArrayList<>();
		try {
			for (Class interceptorClass : interceptorClasses) {
				// 获取interceptorClass及其上的拦截器实例
				List singleList = getMultipleInter(
						interceptorClass);
				interceptorList.addAll(singleList);
			}
			// 去重
			deDuplicates(interceptorList);
			return interceptorList.toArray(new Interceptor[] {});
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		// 框架源码
		// Interceptor[] result = new Interceptor[interceptorClasses.length];
		// try {
		// for (int i = 0; i < result.length; i++) {
		// result[i] = singletonMap.get(interceptorClasses[i]);
		// if (result[i] == null) {
		// result[i] = (Interceptor) interceptorClasses[i]
		// .newInstance();
		// // result[i] = Enhancer.enhance(result[i]);
		// singletonMap.put(interceptorClasses[i], result[i]);
		// }
		// }
		// return result;
		// } catch (Exception e) {
		// throw new RuntimeException(e);
		// }
	}
	/**
	 * 获取interceptorClass实例及其上的多重拦截器
	 * 1.多重拦截器只能定义在Class上
	 * 2.一个递归函数
	 * 
	 * @param interceptorClass
	 * @return
	 */
	private List getMultipleInter(
			Class interceptorClass) {
		// 返回最终结果
		List interList = new ArrayList<>();
		//
		List multiInterList = null;
		// 获取定义在interceptorClass上的@Before
		Before before = interceptorClass.getAnnotation(Before.class);
		// 判断是否有多重拦截器
		if (before != null) {
			// 判断是否有缓存
			multiInterList = multipleMap.get(interceptorClass);
			if (multiInterList == null) {
				// 无缓存
				// 有多重拦截器则需获取interceptorClass上的多重拦截器实例
				multiInterList = new ArrayList<>();
				Class[] multiClasses = before.value();
				for (Class multiClass : multiClasses) {
					multiInterList.addAll(getMultipleInter(multiClass));
				}
				// 添加缓存(mutipleMap是自定义的)
				multipleMap.put(interceptorClass, multiInterList);
			}
		}
		// 由于定义在interceptorClass上的拦截器需在interceptorClass之前add到interList中
		// 获取interceptorClass实例
		Interceptor now = singletonMap.get(interceptorClass);
		if (now == null) {
			try {
				now = interceptorClass.newInstance();
				// 添加缓存
				singletonMap.put(interceptorClass, now);
			} catch (InstantiationException | IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		// ArrayList.addAll()参数不能为null
		if (multiInterList != null) {
			interList.addAll(multiInterList);
		}
		interList.add(now);
		// 去重
		deDuplicates(interList);
		return interList;
	}
	/**
	 * 去掉interList中重复值
	 * @param interList
	 */
	private void deDuplicates(List interList) {
		// 双重循环去重
		for (int i = interList.size() - 1; i >= 0; i--) {
			for (int j = 0; j < i; j++) {
				if (interList.get(i) == interList.get(j)) {
					interList.remove(i);
				}
			}
		}
		// 使用set去重
		// Set interSet = new LinkedHashSet<>(interList);
		// interList.clear();
		// interList.addAll(interSet);
	}