JFinal 多重 拦截器

JFinal中拦截器实现Interceptor接口,有Controller,Service级别,但默认只启动Controller层的拦截器,启动Service层的拦截器需要ehance(),我现在想要实现一个多重拦截的功能,比如UserSongLikeValidator,判断用户有没有对歌曲点赞,在这个拦截器上加@ Before({UserIdValidator,SongIdValidator}),这样在Action方法上加一个@Before(UserSongLikeValidator)就相当于加了@Before({UserIdValidator,SongIdValidator,UserSongLikeValidator})三个拦截器

请问:

JFinal框架中有没有可以默认开启所有类上Interceptor的设置?


评论区

pfjia

2017-06-30 16:41

查了以下代码,如果修改InterceptorManager中的createInterceptor()和一些其他方法可以实现上述功能,但是InterceptorManager的构造器是private的,不能继承

EATI001

2017-07-01 10:20

在yourConfig configInterceptor的配置就是全局拦截器。

JFinal

2017-07-01 10:24

@pfjia 继承一下InterceptorStack 即可实现

pfjia

2017-07-01 16:44

@EATI001 不是做类似全局拦截器那样的功能,而是对拦截器进行拦截

pfjia

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);
}

JFinal

2017-07-01 20:17

用 InterceptorStack 就几行代码的事:
public class UserSongLikeValidator extends InterceptorStack {
public void config() {
addInterceptors(new UserIdValidator());
addInterceptors(new UserSongLikeValidator();
}
}

用的时候这样:
@Before(UserSongLikeValidator.class)

不存在研究一说,继承 InterceptorStack 之后,eclipse 会自动提示你要实现哪个方法,实现方法后,在里面添加两行代码即可打完收工

JFinal

2017-07-01 20:17

InterceptorStack 就是用来将你的多个拦截器组合成为在外部看来是一个拦截器,用的时候当成一个拦截器

热门反馈

扫码入社