实战 Gateway 模式效果
基于网关的开发,是一种责任链模式的实践,一关一责任,互不相扰,按需组合。
1、定制网关(仅供参考)
- 增加 before 和 after 处理,以实现“线性”处理模型。相对的 filter 则为“包围”处理模型。
- 同时,修改 render 方法,将真正的渲染处理交由 after 处理(可以方法,配置式切换)。
public abstract class UapiGateway extends Gateway {
private List<Handler> beforeHandlers = new ArrayList<>();
private List<Handler> afterHandlers = new ArrayList<>();
/**
* 语言
*/
public Locale lang(Context c) {
return c.getLocale();
}
/**
* 前置处理
*/
public void before(Handler handler) {
beforeHandlers.add(handler);
}
/**
* 后置处理
*/
public void after(Handler handler) {
afterHandlers.add(handler);
}
@Override
protected void mainBefores(Context c) throws Throwable {
for (Handler h : beforeHandlers) {
h.handle(c);
}
}
@Override
protected void mainAfters(Context c) throws Throwable {
for (Handler h : afterHandlers) {
h.handle(c);
}
}
/**
* 渲染定制
*/
@Override
public void render(Object obj, Context c) throws Throwable {
if (c.getRendered()) {
return;
}
c.setRendered(true);
//
// 有可能根本没数据过来
//
if (obj instanceof ModelAndView) {
//如果有模板,则直接渲染
//
c.result = obj;
c.render(obj);
} else {
//如果没有按Result tyle 渲染
//
if (obj == null && c.status() == 404) {
obj = UapiCodes.CODE_4001011;
}
Result result = null;
if (obj instanceof UapiCode) {
c.attrSet(Attrs.log_level, Level.WARN.toInt());
//处理标准的状态码
UapiCode err = (UapiCode) obj;
String description = UapiCodes.CODE_note(lang(c), err);
result = Result.failure(err.getCode(), description);
} else if (obj instanceof Throwable) {
c.attrSet(Attrs.log_level, Level.WARN.toInt());
//处理未知异常
String description = UapiCodes.CODE_note(lang(c), UapiCodes.CODE_400);
result = Result.failure(Result.FAILURE_CODE, description);
} else if (obj instanceof ONode) {
//处理ONode数据(为兼容旧的)
result = Result.succeed(((ONode) obj).toData());
} else if (obj instanceof Result) {
//处理Result结构
result = (Result) obj;
} else {
//处理java bean数据(为扩展新的)
result = Result.succeed(obj);
}
if (Utils.isEmpty(result.getDescription()) && result.getCode() > Result.SUCCEED_CODE) {
result.setDescription(UapiCodes.CODE_note(lang(c), result.getCode()));
}
c.result = result;
}
}
}
2、效果预览
定制过的本地网关
@Mapping("/api/v3/app/**")
@Component
public class ApiGateway3x extends UapiGateway {
@Override
protected void register() {
filter(new BreakerFilter()); //融断
before(new StartHandler()); //开始计时
before(new ParamsParseHandler()); //参数解析
before(new ParamsSignCheckHandler(new Md5Encoder())); //参数签名较验
before(new ParamsRebuildHandler(new AesDecoder())); //参数重构
after(new OutputBuildHandler(new AesEncoder())); //输出构建
after(new OutputSignHandler(new Md5Encoder())); //输出签名
after(new OutputHandler()); //输出
after(new EndBeforeLogHandler()); //日志
after(new EndHandler("v3.api.app")); //结束计时
//添加一批具体的接口处理Bean
addBeans(bw -> "api".equals(bw.tag()));
}
}
接口
@Component(tag = "api")
public class API_config_set extends ApiBase {
@Inject
ConfigService configService;
@NotEmpty({"tag", "key"})
@Mapping("config.set")
public void exec(String tag, String key, String value) throws Throwable {
configService.setConfig(tag, key, value);
}
}
3、具体参考:
https://gitee.com/noear/marsh/tree/main/_demo/marsh-api-demo2