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