拦截Restful API的三种方式

如题, 方式有三种。

(1). 过滤器filter

  javaEE规范

(2). 拦截器interceptor

  springmvc提供

(3). 切片 aspect  

一. Filter使用示例

import org.springframework.stereotype.Component;

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

/**
 * 使用@Component注解,该Filter就生效了。
 * 还可以使用配置方式使用过滤生效 {@link FilterRegistrationBean}
 */
@Component
public class LoggerFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("LoggerFilter doFilter begin");
        long startTime = System.currentTimeMillis();
        filterChain.doFilter(servletRequest,servletResponse);
        long endTime = System.currentTimeMillis();
        System.out.println("used time :" + (endTime - startTime));
        System.out.println("LoggerFilter doFilter end");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("LoggerFilter init...");
    }

    @Override
    public void destroy() {
        System.out.println("LoggerFilter destroy...");
    }
}

二. Interceptor使用示例

2.1 自定义一个拦截器

import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * 定义一个拦截器, 它会拦截所有的控制器,包括spring自带的控制器,诸如BasicErrorController.class
 * 注意: interceptor与filter不同,仅仅使用一个@Component注解,该interceptor并不会生效
 */
@Component
public class LoggerInterceptor implements HandlerInterceptor {
    /**
     * 在进入controller方法之前调用
     *
     * @param handler : 就是启用的controller方法
     * @return true: 执行下一个拦截器
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("LoggerInterceptor preHandle...");
        request.setAttribute("startTime", System.currentTimeMillis());
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        System.out.println("Controller类名:"+ handlerMethod.getBean().getClass().getName());
        System.out.println("Controller方法名:"+ handlerMethod.getMethod().getName());
        return true;
    }

    /**
     * 在执行完controller方法之后调用,如果controller方法抛出异常,则不会调用
     *
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("LoggerInterceptor postHandle begin");
        long startTime = (long) request.getAttribute("startTime");
        System.out.println("used time :" + ( System.currentTimeMillis()-startTime));
        System.out.println("LoggerInterceptor postHandle end");
    }

    /**
     * 在视图渲染之后调用,controller有无异常抛出,都会被调用
     * @param  ex  如果controller方法无异常抛出,ex 为null , 否则就是controller中抛出来的异常
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("LoggerInterceptor afterCompletion begin");
        long startTime = (long) request.getAttribute("startTime");
        System.out.println("used time :" + ( System.currentTimeMillis()-startTime));
        System.out.println("LoggerInterceptor afterCompletion ex = " + ex);
        System.out.println("LoggerInterceptor afterCompletion end");
    }
}

2.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.WebMvcConfigurer;
import qinfeng.zheng.mockmvcdemo.interceptor.LoggerInterceptor;

/**
 * SpringBoot 1.X 使用WebMvcConfigurerAdapter.java即可,
 * SpringBoot 2.x WebMvcConfigurerAdapter.java已过时了
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoggerInterceptor loggerInterceptor;

    /**
     * 注册拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(new LoggerInterceptor());
        registry.addInterceptor(loggerInterceptor);
    }
}

三. 切片

/**
 * 定义一个切片
 */
@Aspect
@Component
public class LoggerAspect {
    /**
     * 第一个 * : 方法的任意返回值
     * 第二个 * : qinfeng.zheng.mockmvcdemo.controller.TestController类中的任意方法
     *  ..  : 方法的任意参数
     * @param pjp
     * @return
   *
   * 参考: https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/core.html#aop   5.4.3
     */
    @Around("execution(* qinfeng.zheng.mockmvcdemo.controller.TestController.*(..))")
    public Object handle(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("LoggerAspect handle start...");
        // 方法参数列表
        Object[] args = pjp.getArgs();
        Arrays.stream(args).forEach(x-> System.out.println(x));
        long startTime = System.currentTimeMillis();
        Object result = pjp.proceed();
        System.out.println("used time :" + (System.currentTimeMillis() - startTime));
        System.out.println("LoggerAspect handle end...");
        return result;
    }
}

四. 总结

  Filter最弱,只能获取request对象

  Interceptor,比Filter好,它不但能获取request对象 ,而且还能拿到HandlerMethoh对象,从而知道调用那个Controller ,以及具体的方法

  Aspect,功能最强大,它可以获取Controller方法的方法的参数列表。。。。。

猜你喜欢

转载自www.cnblogs.com/z-qinfeng/p/11749612.html