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.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 doIntercept(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
Solon 的过滤器 Filter 和两种拦截器 Handler、 Interceptor的更多相关文章
- 过滤器Filter的四种拦截方式
过滤器有四种拦截方式!分别是:REQUEST.FORWARD.INCLUDE.ERROR. REQUEST: 直接访问目标资源时执行过滤器.包括:在地址栏中直接访问.表单提交.超链接.重定向,只要在地 ...
- 过滤器(Filter)与拦截器(Interceptor )区别
目录 过滤器(Filter) 拦截器(Interceptor) 拦截器(Interceptor)和过滤器(Filter)的区别 拦截器(Interceptor)和过滤器(Filter)的执行顺序 拦截 ...
- java中过滤器(Filter)与拦截器(Interceptor )区别
过滤器(Filter) Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是设置字符集.控制权限.控制转向.做一些业务逻辑判断等.其工作 ...
- Spring Boot实践——三种拦截器的创建
引用:https://blog.csdn.net/hongxingxiaonan/article/details/48090075 Spring中的拦截器 在web开发中,拦截器是经常用到的功能.它可 ...
- 过滤器(Filter)与拦截器(Interceptor)区别
过滤器(Filter)与拦截器(Interceptor)区别 过滤器(Filter) Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途 ...
- 拦截器(Interceptor)与过滤器(Filter)
目录 用户的普通Http请求执行顺序 过滤器.拦截器添加后的执行顺序 拦截器(Interceptor)的基本定义 拦截器(Interceptor)必须实现的三个方法 单个拦截器(Interceptor ...
- springboot(十七):过滤器(Filter)和拦截器(Interceptor)
概述 在做web开发的时候,过滤器(Filter)和拦截器(Interceptor)很常见,通俗的讲,过滤器可以简单理解为“取你所想取”,忽视掉那些你不想要的东西:拦截器可以简单理解为“拒你所想拒”, ...
- 拦截器(Interceptor)与过滤器(Filter)的区别
转自:https://www.jianshu.com/p/cf088baa9b04 过滤器,是在java web中将你传入的request.response提前过滤掉一些信息,或者提前设置一些参数.然 ...
- SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系
摘自: http://blog.csdn.net/xiaoyaotan_111/article/details/53817918 一 简介 (1)过滤器: 依赖于servlet容器.在实现上基于函数回 ...
随机推荐
- Win 10 下Pipenv源码安装 odoo12
因为,本身电脑已经安装odoo8,9,10等odoo的版本,当时,没有考虑是直接是统一的环境很配置. 现在,在odoo11的环境下,需要Python 3的语言环境可以很好地支持odoo11的功能,所以 ...
- 《C++反汇编与逆向分析技术揭秘》--认识启动函数,找到用户入口
<C++反汇编与逆向分析>和<程序员的自我修养>都是以VC6的代码作为例子讲解的.这里是在vs2017下,CRT代码有些区别,但整体流程上都是初始化环境,设置参数,最后转到用户 ...
- 4、MyBatis教程之配置解析
5.配置解析 核心配置文件 mybatis-config.xml 系统核心配置文件 MyBatis 的配置文件会深深影响 MyBatis 行为的设置和属性信息. 能配置的内容如下: configura ...
- c/s应用程序自动更新组件GeneralUpdate3.2.1发布
一.组件简介 GeneralUpdate是基于.net standard 开发的一款(c/s应用)自动升级程序.该组件将更新的核心部分抽离出来方便应用于多种项目当中目前适用于wpf,控制台应用,win ...
- 如何优雅地学习计算机编程-C++1
如何优雅的学习计算机编程--C++ 0.导入 如何优雅地学习计算机编程.我们得首先了解编程是什么?打个比方--写信. 大家都知道写信所用的语言双方都懂,这样的信才做到了信息交流,人和计算机也是如此人和 ...
- (原创)在Linux上安装运行Python3(CentOS7为例)
在win10上开发好的python项目要部署在Linux上要面对的问题:怎么在Linux上跑py文件呢? 以Lunix CentOS7.x平台为例,CentOS系统上自带的已有python2.x 的版 ...
- Android Studio 之 编写精美的聊天界面
•准备工作 首先制作一张 .9 格式的聊天气泡,参见我的这篇博客: 需要注意的是,制作完成后,应该将原始文件删除,否则AS会分不清楚而报错. 新建一个 Empty Activity,Java 和 XM ...
- Linux标准输入、重定向与参数传递
Linux标准输入.重定向与参数传递 按惯例,每当运行一个新程序时,所有shell都为其打开3个文件描述符,即标准输入.标准输出以及标准错误.如果不做特殊处理,例如就像简单的命令ls,则这三个描述符都 ...
- 三分钟玩转微软AI量化投资开源库QLib
更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流. 微软QLib简介 微软亚洲研究院发布了 AI 量化投资开源平台"微矿 Qlib".Q ...
- JavaCV 采集摄像头和麦克风数据推送到流媒体服务器
越来越觉得放弃JavaCV FFmpeg native API,直接使用JavaCV二次封装的API开发是很明智的选择,使用JavaCV二次封装的API开发避免了各种内存操作不当引起的crash. 上 ...