spring

Filter,Interceptor,AOP 区别与使用方法

2021-05-14  本文已影响0人  boyiis

1.Filter过滤器

过滤器拦截web访问url地址。 严格意义上讲,filter只是适用于web中,依赖于Servlet容器,利用Java的回调机制进行实现。
Filter过滤器:和框架无关,可以控制最初的http请求,但是更细一点的类和方法控制不了。
过滤器可以拦截到方法的请求和响应(ServletRequest request, ServletResponse response),并对请求响应做出像响应的过滤操作,
比如设置字符编码,鉴权操作等

用法:实现Filter接口,或继承其实现类
(eg: GenericFilterBean -> OncePerRequestFilter -> AbstractRequestLoggingFilter)

import javax.servlet.*;
import java.io.IOException;

public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 1. do something

        // 2. continue
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }
}

2.Interceptor拦截器

拦截器拦截以 .action结尾的url,拦截Action的访问。 Interfactor是基于Java的反射机制(APO思想)进行实现,不依赖Servlet容器。
拦截器可以在方法执行之前(preHandle)和方法执行之后(afterCompletion)进行操作,回调操作(postHandle),可以获取执行的方法的名称,请求(HttpServletRequest)
Interceptor:可以控制请求的控制器和方法,但控制不了请求方法里的参数(只能获取参数的名称,不能获取到参数的值)
(用于处理页面提交的请求响应并进行处理,例如做国际化,做主题更换,过滤等)。

用法
步骤1:继承HandlerInterceptorAdapter(是HandlerInterceptor接口的实现类,有默认的空实现,可以自由选择自己需要的method去实现)


import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor extends HandlerInterceptorAdapter {

    // 如果preHandle返回false,这个url请求的controller方法不会进去(被拦截)
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }

    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        super.afterConcurrentHandlingStarted(request, response, handler);
    }
}

步骤2:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

@Configuration
public class MyWebMvcConfigurer extends WebMvcConfigurationSupport {

    @Autowired
    private MyInterceptor myInterceptor;

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor)
                .addPathPatterns("/url1/**", "/url2/**")
                .excludePathPatterns("/url1/exclude");
        super.addInterceptors(registry);
    }

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/META-INF/resources/")
                .addResourceLocations("classpath:/resources/")
                .addResourceLocations("classpath:/static/")
                .addResourceLocations("classpath:/public/");
        super.addResourceHandlers(registry);
    }
}
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/url/**" />
        <bean class="path.MyInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>

3.AOP

只能拦截Spring管理Bean的访问(业务层Service)。 具体AOP详情参照 Spring AOP:原理、 通知、连接点、切点、切面、表达式
实际开发中,AOP常和事务结合:Spring的事务管理:声明式事务管理(切面)
AOP操作可以对操作进行横向的拦截,最大的优势在于他可以获取执行方法的参数(ProceedingJoinPoint.getArgs() ),对方法进行统一的处理。
Aspect : 可以自定义切入的点,有方法的参数,但是拿不到http请求,可以通过其他方式如RequestContextHolder获得
ServletRequestAttributes servletRequestAttributes= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
常见使用日志,事务,请求参数安全验证等

用法
@Aspect @Component @Pointcut @Around @Before

@Aspect:作用是把当前类标识为一个切面供容器读取
@Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
@Around:环绕增强,相当于MethodInterceptor
@AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行
@Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有
@AfterThrowing:异常抛出增强,相当于ThrowsAdvice
@After: final增强,不管是抛出异常或者正常退出都会执行
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class MyAspect {
    @Pointcut("execution(public * com.zq..controller..*Controller.*(..) ) && @annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object function(ProceedingJoinPoint joinPoint) throws Throwable {
        // do something
        // 获取增强的类
        // 获取增强的方法名
        // 获取增强方法的参数

        // 继续执行被拦截方法
        return joinPoint.proceed();
    }
}

顺序:Filter -> Interceptor -> ControllerAdvice -> Aspect -> Controller -> Aspect -> ControllerAdvice -> Interceptor -> Filter
*ps: ControllerAdvice 是controller的增强,和ExceptionHandler一起用来做全局异常。

- filter interceptor aspect
入参 ServletRequest, ServletResponse HttpServletRequest , HttpServletResponse ,Object handler ProceedingJoinPoint
原理 依赖于servlet容器,与框架无关 Spring框架拦截器,基于Java反射机制 动态代理(jdk动态代理/cglib)
范围 RESTful api RESTful api Spring Bean
执行示意图.png
上一篇下一篇

猜你喜欢

热点阅读