- 过滤器有两种创建方式,第一种需要直接实现Filter
package com.imooc.filter;
import java.io.IOException;
import java.util.Date;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.stereotype.Component;
/**
* 只需要声明Component注解就能起作用
* @author caijiajun
* @date 2018年9月11日
*/
@Component
public class TimeFilter implements Filter {
/**
*容器紧跟在垃圾收集之前调用 destroy()方法,以便能够执行任何必需的清理代码。
*/
@Override
public void destroy() {
System.out.println("time filter destroy");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("time filter start");
long start = new Date().getTime();
chain.doFilter(request, response);
System.out.println("time filter:" +(new Date().getTime() - start));
System.out.println("time filter finish");
}
@Override
public void init(FilterConfig arg0) throws ServletException {
System.out.println("time filter init");
}
}
- 第二种实现过滤器实现一个WebMvcConfigurationAdapter加载适配器
package com.imooc.web.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
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.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.imooc.filter.TimeFilter;
import com.imooc.web.interceptor.TimeInterceptor;
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{
@Autowired
private TimeInterceptor timeInterceptor;
/**
* 自定义加载过滤器
*spring中 filter是以
*FilterRegistrationBean形式存在的,然后我们
*setFilter为这个filter放入spring 容器管理。
*可以用setOrder方法为filter设置排序值
* @return
*/
@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;
}
}
3.拦截器,拦截器的配置必须在重写注册,自定义拦截器TimeInterceptor类
package com.imooc.web.interceptor;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class TimeInterceptor implements HandlerInterceptor {
/**
* 无论如何都会被调用在postHandle后面,只有在preHandle返回true才会执行
* 在DispatcherServlet 渲染了对应的视图之后执行。用于进行资源清理。
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception ex)
throws Exception {
System.out.println("afterCompletion");
long start = (long)request.getAttribute("startTime");
System.out.println("time interceptor 耗时: " + (new Date().getTime() - start));
System.out.println("ex :" + ex);
}
/**
* 控制器处理后被调用,如果controller方法抛出异常,就不会被调用
* 该方法将在请求处理之后,DispatcherServlet进行视图返回渲染之前进行调用
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndeVidw)
throws Exception {
System.out.println("postHandle");
long start = (long)request.getAttribute("startTime");
System.out.println("time interceptor 耗时: " + (new Date().getTime() - start));
}
/**
* controller方法调用前被调用
* 只有该方法返回true,后面的Interceptor和cotroller才会被执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
//对应的类名
System.out.println(((HandlerMethod)handler).getBean().getClass().getName());
//对应的方法名
System.out.println(((HandlerMethod)handler).getMethod().getName());
request.setAttribute("startTime", new Date().getTime());
return true;
}
}
- 重写注册器,加载拦截器
package com.imooc.web.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
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.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.imooc.filter.TimeFilter;
import com.imooc.web.interceptor.TimeInterceptor;
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{
@Autowired
private TimeInterceptor timeInterceptor;
/**
* 自定义加载过滤器
*spring中 filter是以
*FilterRegistrationBean形式存在的,然后我们
*setFilter为这个filter放入spring 容器管理。
*可以用setOrder方法为filter设置排序值
* @return
*/
@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;
}
/**
* 重写注册器 加载拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(timeInterceptor);
}
}
5 . Aspect增强
package com.imooc.web.aspect;
import java.util.Date;
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 {
/**
* 设置切入点
* proceedingJoinPoint 里面包含拦截的方法的信息
* @param proceedingJoinPoint
* @return
*/
@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("args is "+arg);
}
long start = new Date().getTime();
//调用被加强的方法、
Object object = pjp.proceed();
System.out.println("time aspect 耗时:" + (new Date().getTime() -start));
System.out.println("time aspect end");
return object;
}
}
- 正常Controller运行Filter,interceptor,Aspect的顺序
总结:Filter(init) -> Filter(doFilter) -> interceptor(preHandle) -> Aspect(around) -> Controller
-> Aspect(Around) ->interceptor(postHandle) -> interceptor(AfterCompletion) ->Filter(doFilter) -> Filter(destroy)
注释:如果interceptor中prehandle()方法返回false 则不会进入后面两个方法,如果interceptor中prehandle()方法返回true,但是controller报异常,则不会进入postHandle()方法