攔截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方法的方法的參數列表。。。。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM