Solon Web 开发,六、过滤器、处理、拦截器

1、过滤器,全局请求的管控(Filter)

完整的Web处理,会经过三个路段:过滤器->处理者->拦截器。具体可以再看看《想法与架构笔记》关于请求的处理过程。

过滤器,一般用于:

  • 全局的请求异常处理
  • 性能记时
  • 响应状态调整
  • 上下文日志记录
  • 链路跟踪等...
@Slf4j
@Component
public class AppFilter implements Filter {
    @Override
    public void doFilter(Context ctx, FilterChain chain) throws Throwable {
        //1.开始计时(用于计算响应时长)
        long start = System.currentTimeMillis();
        try {
            chain.doFilter(ctx);

            //2.未处理设为404状态
            if(! ctx.getHandled()){
                ctx.status(404);
            }
            
            //3.404状态的定制(也可对别的状态处理)
            if (ctx.status() == 404) { 
                ctx.setHandled(true);
                ctx.output("没有:(");
            }
        } catch (Throwable e) {
            //4.异常捕促与控制
            log.error(e);
        }

        //5.获得接口响应时长
        long times = System.currentTimeMillis() - start;
        System.out.println("用时:"+ times);
    }
}  

2、处理者,争对请求的具体路径的处理(Handler)

可以用Handler的模式写,也可以用Controller的模式写(Action 也是 Handler)。

处理者分为:

类型 说明
前置处理者 一般做些验证或检测工作,有一定的拦阻效果
主处理者 默认都是这种
后置处理者 一般是做些补充工作
// handler模式(前置处理)。
//
Solon.global().before("/hello/", ctx->{
    if(ctx.param("name") == null){    
        ctx.setHandled(true);    //如果没有name, 则终止处理
    }
});

// controller模式
//
@Controller
public class HelloInterceptor  {
    //(申明前置处理)
    @Mapping(value = "/hello/" , before = true)   
    public void handle(Context ctx, String name) {
        if(name == null){            
            ctx.setHandled(true);  //如果没有name, 则终止处理
        }
    }
}

3、拦截器,对Method拦截(Interceptor)

只有被动态代理的Bean,才能对Method进行拦截。一般用于切面开发,用注解做为切点配合起来用。比如缓存控制注解@Cache、事务控制注解@Tran等。

//定义事务拦截器
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;
    }
}

//将拦截器注册到容器
Aop.context().beanAroundAdd(Tran.class, new TranInterceptor(), 120);

//应用示例(目前:@Controller、@Service、@Dao 注解的类,都是被动态代理的)
@Service
public class DemoService{
    @Inject
    UserMapper userMapper;
    
    @Tran
    public void add(User user){
        userMapper.add(user);
    }
}
上一篇:HTML复习day02


下一篇:Netty源码解析-ReadTimeoutHandler、WriteTimeoutHandler