RESTFul api攔截順序
Filter ->Interceptor->ControllerAdvice->Aspect->controller
Filter過濾器
(通過註解)開發一個過濾器(此過濾器會對所有url進行攔截)
創建一個類,並添加component註解,使spring自動注入
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;
/**
* @author mjp
* @ClassName : TimeFilter
* @Date: 2019/5/30 15:41
* @Description:
* @Copyright 2019 www.videasoft.com Inc. All rights reserved.
* 注意:本內容僅限於蘇州微締軟件股份有限公司內部傳閱,禁止外泄以及用於其他的商業目的
* @Version 1.0
*/
@Component
public class TimeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("TimeFilter init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("TimeFilter start");
long start = System.currentTimeMillis();
chain.doFilter(request,response);
System.out.println("TimeFilter 耗時: "+(System.currentTimeMillis()- start));
System.out.println("TimeFilter finish");
}
@Override
public void destroy() {
System.out.println("TimeFilter destroy");
}
}
通過配置的方式啓動過濾器(推薦使用,可以選擇性的加載第三方過濾器)
創建攔截器類(實現Filter接口)
import javax.servlet.*;
import java.io.IOException;
/**
* @author mjp
* @ClassName : TimeFilter
* @Date: 2019/5/30 15:41
* @Description:
* @Copyright 2019 www.videasoft.com Inc. All rights reserved.
* 注意:本內容僅限於蘇州微締軟件股份有限公司內部傳閱,禁止外泄以及用於其他的商業目的
* @Version 1.0
*/
public class TimeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("TimeFilter init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("TimeFilter start");
long start = System.currentTimeMillis();
chain.doFilter(request,response);
System.out.println("TimeFilter 耗時: "+(System.currentTimeMillis()- start));
System.out.println("TimeFilter finish");
}
@Override
public void destroy() {
System.out.println("TimeFilter destroy");
}
}
創建配置類 (繼承WebMvcConfigurerAdapter )
import com.imooc.web.filter.TimeFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.util.ArrayList;
import java.util.List;
/**
* 手動配置過濾器,加載第三方過濾器
*/
@Configuration
public class WebConfig{
@Bean
public FilterRegistrationBean timeFilter(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
TimeFilter timeFilter = new TimeFilter();
registrationBean.setFilter(timeFilter);
// 設置攔截路徑
List<String> urls = new ArrayList<>();
urls.add("/*");
registrationBean.setUrlPatterns(urls);
return registrationBean;
}
}
攔截器 Interceptor
創建攔截器類,繼承HandlerInterceptor,並添加spring註解
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;
/**
* 攔截器,
* 與過濾器不一樣的是一個component註解並不能夠是攔截器起作用還需要些配置
*/
@Component
public class TimeInterceptor implements HandlerInterceptor {
/**
* 方法調用前調用
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
System.out.println("preHandle");
System.out.println(((HandlerMethod)o).getBean().getClass().getName());
System.out.println(((HandlerMethod)o).getMethod().getName());
request.setAttribute("startTime",System.currentTimeMillis());
return true;
}
/**
* 如果方法出現異常,此處可能就不會調用
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
Long startTime = (Long) request.getAttribute("startTime");
System.out.println("time interceptor 耗時:" +(System.currentTimeMillis() - startTime));
}
/**
* 方法調用後調用.
* 當成功調用沒有異常的時候 e是空de
* 當拋出的異常的時候 e是有值得
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) throws Exception {
System.out.println("afterCompletion");
Long startTime = (Long) request.getAttribute("startTime");
System.out.println("time interceptor 耗時:" +(System.currentTimeMillis() - startTime));
/**
* 控制器的異常處理器,會在此攔截器之前處理,所有如果異常被控制器的異常處理器處理le,
* 此處的 異常就是空的
*
*/
System.out.println("ex is "+ e);
}
}
配置攔截器,需要繼承WebMvcConfigurerAdapter 並重寫addInterceptors方法
import com.imooc.web.interceptor.TimeInterceptor;
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.WebMvcConfigurerAdapter;
/**
* 手動配置過濾器,加載第三方過濾器
*/
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
private TimeInterceptor timeInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(timeInterceptor);
}
}
Aspect AOP 切面
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
/**
* 切片
*/
@Aspect
@Component
public class TimeAspect {
// @Before() 在方法前
// @After() 在方法後
// @AfterThrowing() 在拋出異常
// @Around() 環繞
// 切入點
@Around("execution(* com.imooc.web.controller.UserController.*(..))")
// 增強
public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(" time aspect start ");
// 獲取請求參數
Object[] args = pjp.getArgs();
for (Object arg : args) {
System.out.println("arg is "+ arg);
}
long l = System.currentTimeMillis();
Object proceed = pjp.proceed();
System.out.println(" time aspect 耗時: "+ (System.currentTimeMillis() - l));
System.out.println(" time aspect end ");
return proceed;
}
}
總結
- Fiter 過濾器可以獲取請求的request和response,但是不能獲取該請求所對應的類和方法
- Inteceptor 攔截器,可以獲取請求的request和response,也能獲取到請求所對應的類和方法,但是不能獲取方法被調用的時候參數對應的值(攔截器過後,spring纔開始封裝參數)
- 可以獲取到請求參數的值,但是不能獲取請求的request和response