一、熟悉 Gateway
Gateway (本地网关)是 Solon 框架的特殊的 Handler 实现。它通过注册收集之后,在局部范围内提供:二级路由、拦截、过滤、融断、异常处理等功能,并统一到网关处理。
另一个作用:可以为同一批接口安排多个网关,进而定制不同的协议效果。
1、定义2个组件
API_0
@Component(tag = "api")
public class API_0 {
@Mapping
public Result exec() {
return Result.failure(404, "Interface does not exist");
}
}
API_hello_world
@Component(tag = "api")
public class API_hello_world {
@Mapping("hello")
public Result exec(String name) {
return Result.succeed("Hello " + name);
}
}
这2个组件,很特别???有@Mapping,看起来像控制器类。但它确用@Component注解,而且还有tag属性。
其实它们跟平常开发的控制器类是一样的。改用 @Component ,是为了不被根路由器扫描进去。而增加tag属性,是为了方便 Gateway 做局部扫描。
@Mapping 值为空时,会被 Gateway 做为默认接口对待。即找不到别的接口时,就用它。
2、定义 Gateway
ApiGateway
@Mapping("/api/**")
@Component
public class ApiGateway extends Gateway {
@Override
protected void register() {
addBeans(bw -> "api".equals(bw.tag()));
}
}
最简单的 Gateway 只需要完成注册即可,输出效果跟普通的控制器差不多。启动服务后,我们就可以访问 http://localhost:8080/api/hello
。
3、在 Gateway 上做点什么
加一个前置处理,做令牌验证。再重写渲染,对未处理异常做控制。
@Mapping("/api/**")
@Component
public class ApiGateway extends Gateway {
@Override
protected void register() {
//添加个前置处理
filter((c, chain) -> {
//检测有没有token(用 param 替代;方便手浏览器测试)
if (c.param("t") == null) {
//如果没有令牌;直接设定结果
c.result = Result.failure(403, "Missing authentication information");
//设为已处理(主接口就不会进去了)
c.setHandled(true);
}
chain.doFilter(c);
});
//添加Bean
addBeans(bw -> "api".equals(bw.tag()));
}
//重写渲染处理异常
@Override
public void render(Object obj, Context c) throws Throwable {
if (obj instanceof Throwable) {
c.render(Result.failure("unknown error"));
} else {
c.render(obj);
}
}
}