From 7f2b450769059ecfdd66b49b76338b2d0cd79c2a Mon Sep 17 00:00:00 2001 From: gudaoxuri Date: Tue, 11 Apr 2017 10:09:46 +0800 Subject: [PATCH] Add common interceptor --- README.md | 1 + pom.xml | 2 +- .../common/interceptor/DewInterceptExec.java | 12 ++ .../interceptor/DewInterceptRespBody.java | 33 ++++++ .../common/interceptor/DewInterceptor.java | 52 +++++++++ .../interceptor/DewInterceptorProcessor.java | 100 ++++++++++++++++ .../ecfront/dew/common/InterceptorTest.java | 108 ++++++++++++++++++ 7 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/ecfront/dew/common/interceptor/DewInterceptExec.java create mode 100644 src/main/java/com/ecfront/dew/common/interceptor/DewInterceptRespBody.java create mode 100644 src/main/java/com/ecfront/dew/common/interceptor/DewInterceptor.java create mode 100644 src/main/java/com/ecfront/dew/common/interceptor/DewInterceptorProcessor.java create mode 100644 src/test/java/com/ecfront/dew/common/InterceptorTest.java diff --git a/README.md b/README.md index 98ceda1..85a3b8b 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Dew公共模块 1. 定时器(TimerHelper) 1. 常用时间处理(TimeHelper) 1. 主流文件MIME整理(MimeHelper) +1. 通用拦截器栈(DewInterceptorProcessor) ### 使用 diff --git a/pom.xml b/pom.xml index eeb2f9d..3daf3d3 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ ${java.version} ${java.version} ${java.version} - 2.8.6 + 2.8.7 1.9.3 0.3m 1.7.22 diff --git a/src/main/java/com/ecfront/dew/common/interceptor/DewInterceptExec.java b/src/main/java/com/ecfront/dew/common/interceptor/DewInterceptExec.java new file mode 100644 index 0000000..d71fc12 --- /dev/null +++ b/src/main/java/com/ecfront/dew/common/interceptor/DewInterceptExec.java @@ -0,0 +1,12 @@ +package com.ecfront.dew.common.interceptor; + +import com.ecfront.dew.common.Resp; + +import java.util.Map; + +@FunctionalInterface +public interface DewInterceptExec { + + Resp> exec(E obj, Map context); + +} diff --git a/src/main/java/com/ecfront/dew/common/interceptor/DewInterceptRespBody.java b/src/main/java/com/ecfront/dew/common/interceptor/DewInterceptRespBody.java new file mode 100644 index 0000000..bd923ff --- /dev/null +++ b/src/main/java/com/ecfront/dew/common/interceptor/DewInterceptRespBody.java @@ -0,0 +1,33 @@ +package com.ecfront.dew.common.interceptor; + +import java.util.Map; + +public class DewInterceptRespBody { + + private E obj; + private Map context; + + public static DewInterceptRespBody build(E obj, Map context) { + DewInterceptRespBody body = new DewInterceptRespBody<>(); + body.setObj(obj); + body.setContext(context); + return body; + } + + public E getObj() { + return obj; + } + + public void setObj(E obj) { + this.obj = obj; + } + + public Map getContext() { + return context; + } + + public void setContext(Map context) { + this.context = context; + } + +} diff --git a/src/main/java/com/ecfront/dew/common/interceptor/DewInterceptor.java b/src/main/java/com/ecfront/dew/common/interceptor/DewInterceptor.java new file mode 100644 index 0000000..7b870a4 --- /dev/null +++ b/src/main/java/com/ecfront/dew/common/interceptor/DewInterceptor.java @@ -0,0 +1,52 @@ +package com.ecfront.dew.common.interceptor; + +import com.ecfront.dew.common.Resp; + +import java.util.Map; + +/** + * 拦截器栈定义 + * + * @param 对象的类型 + */ +public interface DewInterceptor { + + /** + * 获取拦截器所属类型,用于区别不同的栈 + */ + String getCategory(); + + /** + * 获取拦截器名称 + */ + String getName(); + + /** + * 前置执行 + * + * @param obj 对象 + * @param context 参数 + * @return 执行后结果 + */ + Resp> before(E obj, Map context); + + /** + * 后置执行 + * + * @param obj 对象 + * @param context 参数 + * @return 执行后结果 + */ + Resp> after(E obj, Map context); + + /** + * 错误处理,在前置/后置执行错误时触发,多用于资源回收 + * + * @param obj 对象 + * @param context 参数 + */ + default void error(E obj, Map context) { + + } + +} diff --git a/src/main/java/com/ecfront/dew/common/interceptor/DewInterceptorProcessor.java b/src/main/java/com/ecfront/dew/common/interceptor/DewInterceptorProcessor.java new file mode 100644 index 0000000..8eca0a8 --- /dev/null +++ b/src/main/java/com/ecfront/dew/common/interceptor/DewInterceptorProcessor.java @@ -0,0 +1,100 @@ +package com.ecfront.dew.common.interceptor; + +import com.ecfront.dew.common.Resp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 拦截器栈执行器 + */ +public class DewInterceptorProcessor { + + private static Logger logger = LoggerFactory.getLogger(DewInterceptorProcessor.class); + + private static Map>> CONTAINER = new HashMap<>(); + + /** + * 注册拦截器栈 + * + * @param category 拦截类型 + * @param interceptor 拦截器 + */ + public static void register(String category, DewInterceptor interceptor) { + if (!CONTAINER.containsKey(category)) { + CONTAINER.put(category, new ArrayList<>()); + } + CONTAINER.get(category).add(interceptor); + } + + /** + * 注册拦截器栈 + * + * @param category 拦截类型 + * @param interceptors 拦截器列表 + */ + public static void register(String category, List> interceptors) { + CONTAINER.put(category, interceptors); + } + + /** + * 拦截器栈处理方法 + * + * @param category 拦截类型 + * @param obj 初始入栈对象 + * @param context 初始入栈参数 + * @param fun 实际执行方法 + * @tparam E 对象的类型 + */ + public static Resp> process(String category, E obj, Map context, DewInterceptExec fun) { + logger.debug("[DewInterceptorProcessor] Process [{}]", category); + if (!CONTAINER.containsKey(category)) { + return fun.exec(obj, context); + } + List> interceptors = CONTAINER.get(category); + Resp> beforeR = doProcess(obj, context, interceptors, true); + if (!beforeR.ok()) { + return beforeR; + } + Resp> execR = fun.exec(beforeR.getBody().getObj(), beforeR.getBody().getContext()); + if (!execR.ok()) { + return execR; + } + return doProcess(obj, context, interceptors, false); + } + + private static Resp> doProcess(E obj, Map context, List> interceptors, boolean isBefore) { + Resp> result = Resp.success(DewInterceptRespBody.build(obj, context)); + for (DewInterceptor interceptor : interceptors) { + logger.trace("[DewInterceptorProcessor] Process interceptor [{}]:{}-{}", interceptor.getCategory(), interceptor.getName(), isBefore ? "before" : "after"); + E preObj = result.getBody().getObj(); + Map preContext = result.getBody().getContext(); + DewInterceptor interceptorE = (DewInterceptor) interceptor; + try { + if (isBefore) { + result = interceptorE.before(preObj, preContext); + } else { + result = interceptorE.after(preObj, preContext); + } + if (!result.ok()) { + logger.warn("[DewInterceptorProcessor] Process interceptor error [{}]:{}-{},[{}]{}", + interceptor.getCategory(), interceptor.getName(), isBefore ? "before" : "after", result.getCode(), result.getMessage()); + interceptorE.error(preObj, preContext); + return result; + } + } catch (Throwable e) { + result = Resp.serverError(e.getMessage()); + logger.error("[DewInterceptorProcessor] Process interceptor error [{}]:{}-{},[{}]{}", + interceptor.getCategory(), interceptor.getName(), isBefore ? "before" : "after", result.getCode(), result.getMessage()); + interceptorE.error(preObj, preContext); + return result; + } + } + return result; + } + +} diff --git a/src/test/java/com/ecfront/dew/common/InterceptorTest.java b/src/test/java/com/ecfront/dew/common/InterceptorTest.java new file mode 100644 index 0000000..42c6b4a --- /dev/null +++ b/src/test/java/com/ecfront/dew/common/InterceptorTest.java @@ -0,0 +1,108 @@ +package com.ecfront.dew.common; + +import com.ecfront.dew.common.interceptor.DewInterceptRespBody; +import com.ecfront.dew.common.interceptor.DewInterceptor; +import com.ecfront.dew.common.interceptor.DewInterceptorProcessor; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class InterceptorTest { + + @Test + public void testInterceptor() throws Exception { + // none + Resp> resp = DewInterceptorProcessor.process("none", new Obj("1"), new HashMap<>(), (obj, context) -> + Resp.success(DewInterceptRespBody.build(obj, context)) + ); + Assert.assertTrue(resp.ok()); + Assert.assertEquals("1", resp.getBody().getObj().getF()); + // has one + DewInterceptorProcessor.register("test",new InterceptorA()); + resp = DewInterceptorProcessor.process("test", new Obj("1"), new HashMap<>(), (obj, context) -> + Resp.success(DewInterceptRespBody.build(obj, context)) + ); + Assert.assertTrue(resp.ok()); + Assert.assertEquals("3", resp.getBody().getObj().getF()); + // error + DewInterceptorProcessor.register("test",new InterceptorB()); + resp = DewInterceptorProcessor.process("test", new Obj("1"), new HashMap<>(), (obj, context) -> + Resp.success(DewInterceptRespBody.build(obj, context)) + ); + Assert.assertTrue(!resp.ok()); + } + + + public class Obj { + private String f; + + public Obj(String f) { + this.f = f; + } + + public String getF() { + return f; + } + + public void setF(String f) { + this.f = f; + } + } + + public class InterceptorA implements DewInterceptor { + + @Override + public String getCategory() { + return "test"; + } + + @Override + public String getName() { + return "A"; + } + + @Override + public Resp> after(Obj obj, Map context) { + obj.setF("3"); + return Resp.success(DewInterceptRespBody.build(obj,context)); + } + + @Override + public Resp> before(Obj obj, Map context) { + obj.setF("2"); + return Resp.success(DewInterceptRespBody.build(obj, context)); + } + } + + public class InterceptorB implements DewInterceptor { + + @Override + public String getCategory() { + return "test"; + } + + @Override + public String getName() { + return "B"; + } + + @Override + public Resp> after(Obj obj, Map context) { + return Resp.success(DewInterceptRespBody.build(obj,context)); + } + + @Override + public Resp> before(Obj obj, Map context) { + return Resp.badRequest("some error"); + } + + @Override + public void error(Obj obj, Map context) { + obj.setF("error"); + } + } + + +} \ No newline at end of file