Solon 的过滤器 Filter 和两种拦截器 Handler、 Interceptor
在web开发中,过滤器、拦截器是经常用到的功能。它可以帮我们限制流量、验证是否登陆、记录日志以及统计执行效率等等。
今天主要交流一下 Solon 框架中的过滤器和拦截器。
Solon 是什么框架?
Solon 是一个插件式的 Java 微型开发框架。强调,克制 + 简洁 + 开放的原则;力求,更小、更快、更自由的体验。支持:RPC、REST API、 MVC、Micro service、WebSocket、Socket 等多种开发模式。
一、Solon 的过滤器
Solon 是一个 Servelt 无关的开发框架,所以有自己专属的 Filter,但与 Servelt 的 Filter 功能相差不大。另外,Solon 是一个多信号源的开发框架,所以 Filter 对 Http、Socket、WebSocket 的请求信号统统有效。
//接口代码 @FunctionalInterface public interface Filter { void doFilter(Context ctx, FilterChain chain) throws Throwable; }
Solon Filter 是最根级的、最粗颗料度的过滤手段。它不能选择路径过滤,只能对所有的请求进行过滤。如果需要仅对某路径处理,需要代码内控制,这是与 Servelt Filter 的一大区别。
一个限流的示例:
public class DemoApp{ public static void main(String[] args){ SolonApp app = Solon.start(DemoApp.class, args); app.filter((ctx, chain)->{ try(AutoCloseable entry = Limiter.entry()){ chain.doFilter(ctx); }catch (Exception e){ ctx.output("服务器有点忙,请稍后再试"); } }); } }
也可以用组件的形式申明:
@Component public class BreakerFilter implements Filter { @Override public void doFilter(Context ctx, FilterChain chain) throws Throwable { try(AutoCloseable entry = Limiter.entry()){ chain.doFilter(ctx); }catch (Exception e){ ctx.output("服务器有点忙,请稍后再试"); } } }
Solon Filter 绝大部份的工作,都可以由 Solon 拦截器 Handler 完成。
二、Solon 的拦截器
Solon 中拦截器分为两种。一是 Handler,争对请求地址与上下文对象的拦截;一是 Interceptor,对 Bean 的 Method 进行拦截。
1、Handler(Context 拦截器)
Solon 对web请求处理的本质,即是对 Context 的一路拦截处理并最终输出。这一路的拦截处理可称之为拦截链,拦截链上每个处理节点,即为 Context 拦截器,每个拦截器即为 Handler 。
//接口代码 @FunctionalInterface public interface Handler { void handle(Context context) throws Throwable; }
Handler 在顺位上可分为:前置拦截器(可以多个)、中置拦截器(最多一个)、后置拦截器(可以多个),提供了三段拦截能力。在使用上又有三种模式可选,具体如下代码:
使用模式一:纯手写模式(这种模式,可以偷偷为控制器加点东西)
public class DemoApp{ public static void main(String[] args){ SolonApp app = Solon.start(DemoApp.class, args); //中置拦截处理 app.get("/hello",c->c.output("Hello world!")); //前置拦截处理(验证Token) app.before("/hello",c->{ if(c.header("Token") == null){ //如果没有Token则中止后续处理 c.setHandled(true); } }); //前置拦截处理(记录Log)-- 拦截链,可以形成一种"装配"的感觉 app.before("/hello",c->{ System.out.println("记录日志"); }); //后前置拦截处理 app ad8 .after("/hello",c->{ System.out.println("记录时间消耗"); }); } }
使用模式二:控制器编写模式(这种模式比较有透明度,自己给自己加点料)
@Controller public class DemoController { //前置拦截处理(验证Token) @Mapping(value = "hello", before = true) public void helloBef1(Context c) { if (c.header("Token") == null) { //如果没有Token则中止后续处理 c.setHandled(true); } } //前置拦截处理(记录Log) @Mapping(value = "hello", before = true) public void helloBef2(Context c) { System.out.println("记录日志"); } //中置拦截处理 @Get @Mapping("hello") public String hello() { return "Hello world!"; } //后前置拦截处理 @Mapping(value = "hello", after = true) public void helloAft1(Context c) { System.out.println("记录时间消耗"); } }
使用模式三:注解模式(通过:@Before、@After 注解附加;这种模式比较有装配感)
// //1. 三个拦截处理 // public class HelloBef1Handler implements Handler { @Override public void handle(Context c) throws Throwable { if (c.header("Token") == null) { //如果没有Token则中止后续处理 c.setHandled(true); } } } public class HelloBef1Handler implements Handler { @Override public void handle(Context c) throws Throwable { if (c.header("Token") == null) { //如果没有Token则中止后续处理 c.setHandled(true); } } } public class HelloBef2Handler implements Handler { @Override public void handle(Context c) throws Throwable { System.out.println("记录日志"); } } // // 2.通过注解,附加在Action上 // @Controller public class DemoController { //此注入,也可附加在控制器类上 @After({HelloAft1Handler.class}) @Before({HelloBef1Handler.class, HelloBef2Handler.class}) @Get @Mapping("hello") public String hello() { return "Hello world!"; } }
2、Interceptor(Method 拦截器)
Interceptor 拦截的目标是方法,所以被代理的 Bean Method。
//接口代码 @FunctionalInterface public interface Interceptor { Object do 1f96 Intercept(Invocation inv) throws Throwable; }
Interceptor 同样有三种使用模式。
使用模式一:手写模式
//定义一个拦截器 public class TranInterceptor implements Interceptor { @Override public Object doIntercept(Invocation inv) throws Throwable{ ValHolder val0 = new ValHolder(); Tran anno = inv.method().getAnnotation(Tran.class); TranExecutorImp.global.execute(anno, () -> { val0.value = inv.invoke(); }); return val0.value; } } //定义一个注解 @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Tran { } //注册一个环境处理到Aop容器 Aop.context().beanAroundAdd(Tran.class, new TranInterceptor(), 120); //使用 @Service public class UserService{ //通过@Tran,实现拦截并添加事务支持 @Tran public void addUser(User user){ userMapper.insert(user); } }
使用模式二:通过注解桥接模式(通过:@Around 注解桥接一个拦截器)
//定义一个拦截器 public class TranInterceptor implements Interceptor { @Override public Object doIntercept(Invocation inv) throws Throwable{ ValHolder val0 = new ValHolder(); Tran anno = inv.method().getAnnotation(Tran.class); TranExecutorImp.global.execute(anno, () -> { val0.value = inv.invoke(); }); return val0.value; } } //定义一个注解(通过@Aroud 关联一个拦截器) @Around(value = TranInterceptor.class, index = 120)) @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Tran { } //使用 @Service public class UserService{ //通过@Tran,实现拦截并添加事务支持 @Tran public void addUser(User user){ userMapper.insert(user); } }
使用模式三:直接注解模式(通过:@Around 注解直接申明拦截器)
//定义一个拦截器 public class TranInterceptor implements Interceptor { @Override public Object doIntercept(Invocation inv) throws Throwable{ ValHolder val0 = new ValHolder(); Tran anno = inv.method().getAnnotation(Tran.class); TranExecutorImp.global.execute(anno, () -> { val0.value = inv.invoke(); }); return val0.value; } } //使用 @Service public class UserService{ @Around(value = TranInterceptor.class, index = 120)) public void addUser(User user){ userMapper.insert(user); } }
附:项目地址
附:入门示例
- Solon 入门教程示例:https://gitee.com/noear/solon_demo
- Solon Rpc 入门教程示例:https://gitee.com/noear/solon_rpc_demo
- Solon Cloud 入门教程示例:https://gitee.com/noear/solon_cloud_demo
- Solon 进阶教程示例:https://gitee.com/noear/solon_advance_demo
- 拦截器Interceptor和过滤器Filter的用法区别
- Spring MVC中的拦截器/过滤器HandlerInterceptorAdapter的使用
- 过滤器(opensessioninviewfilter)与拦截器(opensessioninviewinterceptor)的区别?
- SSM项目中的拦截器(Interceptor)和过滤器(Filter)介绍及简单实现验证登录
- 拦截器(interceptor)和过滤器(filter)
- 自定义过滤器Filter与拦截器Interceptor
- 过滤器(Filter)和拦截器(Interceptor)的区别
- 三.SSM框架整合之过滤器Filter与拦截器Interceptor(登陆拦截)
- 过滤器:filter 拦截器:interceptor
- 拦截器Interceptor 与过滤器 Filter
- 过滤器(Filter)和拦截器(Interceptor)的区别
- struts2的拦截器(Interceptor)与过滤器(Filter)
- SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系
- SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系
- 拦截器(Interceptor)和过滤器(Filter)的执行顺序和区别
- 过滤器: Filter 和 拦截器: Interceptor
- 过滤器(Filter)、拦截器(Interceptor)、监听器(Listener)
- Servlet 过滤器(filter)和Spring 拦截器(Interceptor)区别
- 过滤器(Filter)和拦截器(Interceptor)的区别
- SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系