过滤器,拦截器,切面
Filter过滤器
@Component
@Slf4j
public class ForwardFilter implements Filter{
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if(){
// 直接跳转到下一个过滤器
filterChain.doFilter(request, response);
}else{
// 转发请求
targetResponse = forwardRequest(request, forwardRequest);
response.setStatus();
response.getOutputStream().write(targetResponse.getBody());
}
}
}
Interceptor拦截器
@Component
@Slf4j
public class VerifyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 不拦截swagger页面
if (request.getRequestURI().contains("api-docs")
|| request.getRequestURI().contains("swagger")) {
return true;
}
if(){
// 校验通过
log.info("");
response.setStatus(200);
return true;
}else{
// 校验不通过
log.error("");
response.setStatus(401);
return false;
}
}
}
切面
定义一个切面注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExternalLog {
}
用此注解标记一个method
@Override
@ExternalLog
public List<Instance> getAllInstances() {
// 被@ExternalLog标记的方法称为切入点Join Point
log.info("in getAllInstances() and will sleep 2s");
CompletableFuture<List<Instance>> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return instanceRepository.findAll();
});
try {
return future.get(3000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (TimeoutException e) {
throw new RuntimeException(e);
}
}
定义一个切面
@Aspect
@Component
@Slf4j
public class ExternalLogAspect {
@Pointcut("@annotation(cc.cocobolo.common.aop.ExternalLog)")
public void externalLogPointCut() {
// 一个切点PointCut
// 这个切点定义了一个注解@ExternalLog,表示切入点是被此注解标记的方法
}
@Around("externalLogPointCut()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
// 切面Aspect,用于定义在何处以及如何应用额外逻辑
long startTime = System.currentTimeMillis();
log.info("before joinPoint.proceed() at {}", startTime);
Object result = joinPoint.proceed();
if (result instanceof List) {
List<String> listResult = (List<String>) result;
log.info("joinPoint result size: {}", listResult.size());
} else {
log.warn("result abnormal");
}
long endTime = System.currentTimeMillis();
log.info("after joinPoint.proceed() at {}", endTime);
log.info("cost {} milliseconds", endTime - startTime);
return result;
}
}
来理一下切点/切入点/切面的关系:
概念 | Name | 形式 | 作用 | 类比 |
---|---|---|---|---|
切点 | PointCut | 通常由切面类中的方法来定义。这些方法通常使用 @Pointcut 注解进行标注,并且方法体为空 |
唯一目的是定义一个切点表达式 | 定义在哪里下刀的规则 |
切入点 | Join Point | 实际被拦截的程序执行点。切入点通常指的是被切面拦截的方法,但它也可以是其他连接点,比如字段访问或者异常抛出 | 方法or异常抛出 | 被切的对象 |
切面 | Aspect | doAround方法 | 定义在切入点处怎么执行额外的逻辑 | 切了之后做什么 |