Solon v3.5.1

过滤器 Filter

</> markdown

前置参考:

过滤器(最外层的 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());
        ...
    }
}
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);
    }
}