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);
}
}