SpringBoot实现过滤器、拦截器与切片
Java技术精选
共 7799字,需浏览 16分钟
·
2021-12-13 08:12
过滤器Filter
过滤器概念
过滤器作用
Examples that have been identified for this design are
1) Authentication Filters, 即用户访问权限过滤
2) Logging and Auditing Filters, 日志过滤,可以记录特殊用户的特殊请求的记录等
3) Image conversion Filters
4) Data compression Filters
5) Encryption Filters
6) Tokenizing Filters
7) Filters that trigger resource access events
8) XSL/T filters
9) Mime-type chain Filter
过滤器实现方式
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
// 必须添加注解,springmvc通过web.xml配置
@Component
public class TimeFilter implements Filter {
private static final Logger LOG = LoggerFactory.getLogger(TimeFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
LOG.info("初始化过滤器:{}", filterConfig.getFilterName());
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
LOG.info("start to doFilter");
long startTime = System.currentTimeMillis();
chain.doFilter(request, response);
long endTime = System.currentTimeMillis();
LOG.info("the request of {} consumes {}ms.", getUrlFrom(request), (endTime - startTime));
LOG.info("end to doFilter");
}
@Override
public void destroy() {
LOG.info("销毁过滤器");
}
private String getUrlFrom(ServletRequest servletRequest){
if (servletRequest instanceof HttpServletRequest){
return ((HttpServletRequest) servletRequest).getRequestURL().toString();
}
return "";
}
}
在SpringBoot中注册第三方过滤器
@Configuration
public class WebConfig {
/**
* 注册第三方过滤器
* 功能与spring mvc中通过配置web.xml相同
* @return
*/
@Bean
public FilterRegistrationBean thirdFilter(){
ThirdPartFilter thirdPartFilter = new ThirdPartFilter();
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean() ;
filterRegistrationBean.setFilter(thirdPartFilter);
Listurls = new ArrayList<>();
// 匹配所有请求路径
urls.add("/*");
filterRegistrationBean.setUrlPatterns(urls);
return filterRegistrationBean;
}
}
拦截器Interceptor
拦截器概念
拦截器作用
日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等
权限检查:如登录检测,进入处理器检测检测是否登录
性能监控:通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间。(反向代理,如apache也可以自动记录);
通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。
拦截器实现
@Component
public class TimeInterceptor implements HandlerInterceptor {
private static final Logger LOG = LoggerFactory.getLogger(TimeInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
LOG.info("在请求处理之前进行调用(Controller方法调用之前)");
request.setAttribute("startTime", System.currentTimeMillis());
HandlerMethod handlerMethod = (HandlerMethod) handler;
LOG.info("controller object is {}", handlerMethod.getBean().getClass().getName());
LOG.info("controller method is {}", handlerMethod.getMethod());
// 需要返回true,否则请求不会被控制器处理
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
LOG.info("请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后),如果异常发生,则该方法不会被调用");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
LOG.info("在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
long startTime = (long) request.getAttribute("startTime");
LOG.info("time consume is {}", System.currentTimeMillis() - startTime);
}
// java配置类
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private TimeInterceptor timeInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(timeInterceptor);
}
}
节点信息。切片Aspect
切片概述
切片实现
docs.spring.io/spring/docs/5.0.12.RELEASE/spring-framework-reference/core.html#aop
@Aspect
@Component
public class TimeAspect {
private static final Logger LOG = LoggerFactory.getLogger(TimeAspect.class);
@Around("execution(* me.ifight.controller.*.*(..))")
public Object handleControllerMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
LOG.info("切片开始。。。");
long startTime = System.currentTimeMillis();
// 获取请求入参
Object[] args = proceedingJoinPoint.getArgs();
Arrays.stream(args).forEach(arg -> LOG.info("arg is {}", arg));
// 获取相应
Object response = proceedingJoinPoint.proceed();
long endTime = System.currentTimeMillis();
LOG.info("请求:{}, 耗时{}ms", proceedingJoinPoint.getSignature(), (endTime - startTime));
LOG.info("切片结束。。。");
return null;
}
}
过滤器、拦截器以及切片的调用顺序
过滤器和拦截器的区别
参考
评论