在某些情况下,我们需要对REST API 做一些统一的处理 ,最常用的场景是我希望记录所有的REST API 处理的时间 ,那么如何的来实现这种需求呢?就需要用到这种RESTful API的拦截
过滤器( Filter )
拦截器( Interceptor)
切片( Aspect)
记录所有服务的处理时间
/**
* 记录所有服务处理的时间
* Created by ZhuPengWei on 2017/11/22.
*/
@Component
public class TimeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter初始化成功了");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
Long time = new Date().getTime();
System.out.println("Filter方法执行前时间:" +time);
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Filter方法执行后时间:"+new Date().getTime()+ ",共耗时:"+(new Date().getTime()-time));
}
@Override
public void destroy() {
System.out.println("Filter销毁了");
}
}
(1)、启动服务器时加载过滤器的实例,并调用init()方法来初始化实例;
(2)、每一次请求时都只调用方法doFilter()进行处理;
(3)、停止服务器时调用destroy()方法,销毁实例。
如果引用了第三方的过滤器,并且没有Conponent注解 怎么把第三方的过滤器引入到项目之中来呢?在传统的项目中一般有web.xml这个配置文件,在springboot之中一般是没有这个配置文件的
/**
* Created by ZhuPengWei on 2017/11/22.
*/
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean timeFilter() {
// 过滤器注册
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
// 时间过滤器
TimeFilter timeFilter = new TimeFilter();
// 设置
filterRegistrationBean.setFilter(timeFilter);
List<String> urls = new ArrayList<String>();
// 设置拦截路径
urls.add("/*");
filterRegistrationBean.setUrlPatterns(urls);
return filterRegistrationBean;
}
}
过滤器来拦截REST API 这种方式一般会有一个问题,这个问题是它只能拿到HTTP 的请求和响应,只能从请求和响应中获取一些参数,这些发过来的请求实际上是由哪一个控制器的哪一个方法来处理的在Filter中是不知道的,因为Filter这个接口是J2EE规范来定义的 在J2EE中实际上是不能了解到和Spring相关的任何东西。而自定义的比如说UserController实际上是springmvc自己定义的一些东西。
如果需要知道这些信息的话 我们需要第二个机制 拦截器 ,拦截器这个东西本身是spring框架提供的
/**
* 时间拦截器
* Created by ZhuPengWei on 2017/11/22.
*/
@Component
public class TimeInterceptor implements HandlerInterceptor {
// 1调用前
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("preHandle!!");
System.out.println("拦截的类名称:"+ ((HandlerMethod)o).getBean().getClass().getName());
System.out.println("拦截的方法名称:"+((HandlerMethod)o).getMethod().getName());
// 设置拦截开始时间
httpServletRequest.setAttribute("time",new Date().getTime());
return true;
}
// 2调用后
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
Long nowTime = new Date().getTime();
long preTime = (long) httpServletRequest.getAttribute("time");
System.out.println("Interceptor耗时:" +(nowTime-preTime));
}
// 抛出异常 则 2不会被调用了 不管有没有抛出异常 3总是会被调用
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("afterCompletion");
Long nowTime = new Date().getTime();
long preTime = (long) httpServletRequest.getAttribute("time");
System.out.println("Interceptor耗时:" +(nowTime-preTime));
System.out.println(e);
System.out.println("拦截之后");
}
}
/**
* 自定义过滤器 拦截器
* 拦截器需要继承 WebMvcConfigurerAdapter
* Created by ZhuPengWei on 2017/11/22.
*/
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{
@Autowired
private TimeInterceptor timeInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(timeInterceptor);
}
@Bean
public FilterRegistrationBean timeFilter() {
// 过滤器注册
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
// 时间过滤器
TimeFilter timeFilter = new TimeFilter();
// 设置
filterRegistrationBean.setFilter(timeFilter);
List<String> urls = new ArrayList<String>();
// 设置拦截路径
urls.add("/*");
filterRegistrationBean.setUrlPatterns(urls);
return filterRegistrationBean;
}
}