过滤器 Filter
前置参考:
过滤器(最外层的 web 过滤或拦截,范围包括了静态文档),可用于全局,也可用于局部(Local gateway、Action)。
1、接口声明
package org.noear.solon.core.handle;
@FunctionalInterface
public interface Filter {
/**
* 过滤
*
* @param ctx 上下文
* @param chain 过滤器调用链
* */
void doFilter(Context ctx, FilterChain chain) throws Throwable;
}
2、应用范围
- 全局过滤
@Component
public class DemoFilter1 implements Filter { ... }
- 本地网关过滤
public class DemoFilter2 implements Filter { ... }
@Component
@Mapping("/api/v2/**")
public class DemoLocalGateway2 extends Gateway {
@Override
protected void register() {
filter(new DemoFilter2());
...
}
}
- 动作过滤(“@Addition” 可参考:@Addition 使用说明(AOP))
public class DemoFilter31 implements Filter { ... }
public class DemoFilter32 implements Filter { ... }
public class DemoFilter33 implements Filter { ... }
//可加在类上
@Addition(DemoFilter31.class)
@Controller
public class DemoController3 {
//可加在方法上
@Addition(DemoFilter32.class)
@Mapping("hello")
public String hello(){
...
}
}
//或者使用注解别名(用一个新注解,替代 "@Addition(DemoFilter33.class)")
@Addition(DemoFilter33.class)
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Whitelist {
}
//可加在类上
@Whitelist
@Controller
public class DemoController3 {
//可加在方法上
@Whitelist
@Mapping("hello")
public String hello(){
...
}
}
3、定制参考1:
public class I18nFilter implements Filter {
@Override
public void doFilter(Context ctx, FilterChain chain) throws Throwable {
//尝试自动完成地区解析
I18nUtil.getLocaleResolver().getLocale(ctx);
chain.doFilter(ctx);
}
}
4、定制参考2:
public class ContextPathFilter implements Filter {
private final String contextPath0;
private final String contextPath1;
private final boolean forced;
public ContextPathFilter() {
this(Solon.cfg().serverContextPath(), Solon.cfg().serverContextPathForced());
}
/**
* @param contextPath '/demo/'
*/
public ContextPathFilter(String contextPath, boolean forced) {
this.forced = forced;
if (Utils.isEmpty(contextPath)) {
contextPath0 = null;
contextPath1 = null;
} else {
String newPath = null;
if (contextPath.endsWith("/")) {
newPath = contextPath;
} else {
newPath = contextPath + "/";
}
if (newPath.startsWith("/")) {
this.contextPath1 = newPath;
} else {
this.contextPath1 = "/" + newPath;
}
this.contextPath0 = contextPath1.substring(0, contextPath1.length() - 1);
//有可能是 ContextPathFilter 是用户手动添加的!需要补一下配置
Solon.cfg().serverContextPath(this.contextPath1);
}
}
@Override
public void doFilter(Context ctx, FilterChain chain) throws Throwable {
if (contextPath0 != null) {
if (ctx.pathNew().equals(contextPath0)) {
//www:888 加 abc 后,仍可以用 www:888/abc 打开
ctx.pathNew("/");
} else if (ctx.pathNew().startsWith(contextPath1)) {
ctx.pathNew(ctx.pathNew().substring(contextPath1.length() - 1));
} else {
if (forced) {
ctx.status(404);
return;
}
}
}
chain.doFilter(ctx);
}
}