filter:过滤器,是 Servlet 技术中最实用的技术。用于过滤掉一些不符合要求的请求。常见场景如session校验、url校验,若不符合条件,则会被过滤掉做出特殊的响应。
interceptor:拦截器,动态拦截 action 调用的对象,然后提供了可以在 action 执行前后增加一些操作。常见场景如登录认证,通过拦截器验证用户的登录状态,若没有登录就会返回一个友好提示;记录日志,记录请求ip、方法执行时间等。
listener:监听器,监听 Web 应用程序中对象的创建、销毁等动作的发送,同时对监听的情况作出相应的处理。常见场景如统计网站的在线人数、访问量等。
实例:
1、创建springboot工程
2、filter
实现过滤器首先需要实现Filter接口,然后重写三个方法,init、destroy、doFilter。
@Log4j2
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//在实例化时创建
log.info("初始化过滤器");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//HttpServletRequestWrapper,HttpServletResponseWrapper的使用往往配合过滤器Filter使用
HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper(response);
String requestUri = request.getRequestURI();
log.info("进入过滤器的请求地址是:{}", requestUri);
if (requestUri.contains("/addSession") || requestUri.contains("/removeSession") || requestUri.contains("/online") || requestUri.contains("/favicon.ico")) {
//放行
filterChain.doFilter(servletRequest, servletResponse);
} else {
//返回
ResponseUtil.returnResultAjax(response, requestUri + " is filtered", "UTF-8");
//wrapper.sendRedirect("/online");
}
}
@Override
public void destroy() {
//在服务关闭时销毁
log.info("销毁过滤器");
}
}
3、interceptor
实现拦截器首先需要实现HandlerInterceptor 接口,然后重写三个方法,preHandle、postHandle、afterCompletion。
@Log4j2
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("进入拦截器的请求地址是:{}", request.getRequestURI());
request.setAttribute("requestTime", System.currentTimeMillis());
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
if (!request.getRequestURI().contains("/online") && request.getSession(false) != null) {
HttpSession session = request.getSession();
String sessionName = (String) session.getAttribute("name");
if ("caocao".equals(sessionName)) {
log.info("当前浏览器存在 session:{}",sessionName);
}
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
long duration = System.currentTimeMillis() - Long.parseLong(request.getAttribute("requestTime").toString());
log.info("进入拦截器的请求地址是:{},耗时:{}ms",request.getRequestURI(), duration);
}
}
4、listener
实现监听器首先需要实现HttpSessionListener接口,然后重写两个方法。
@Log4j2
public class MyHttpSessionListener implements HttpSessionListener {
public static AtomicInteger userCount = new AtomicInteger(0);
@Override
public synchronized void sessionCreated(HttpSessionEvent sessionEvent) {
userCount.getAndIncrement();
sessionEvent.getSession().getServletContext().setAttribute("sessionCount", userCount.get());
log.info("在线人数人数增加为:{}",userCount.get());
}
@Override
public synchronized void sessionDestroyed(HttpSessionEvent sessionEvent) {
userCount.getAndDecrement();
sessionEvent.getSession().getServletContext().setAttribute("sessionCount", userCount.get());
log.info("在线人数人数减少为:{}",userCount.get());
}
}
@Log4j2
public class MyHttpRequestListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
String requestUri = request.getRequestURI();
log.info("进入监听器的请求地址是:{}", requestUri);
}
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
log.info("监听器被销毁");
}
}
5、实例化
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
/**
* 注册拦截器
* @return
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor);
}
/**
* 注册过滤器
* @return
*/
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new MyFilter());
filterRegistration.addUrlPatterns("/*");
return filterRegistration;
}
/**
* 注册监听器
* @return
*/
@Bean
public ServletListenerRegistrationBean registrationBean(){
ServletListenerRegistrationBean registrationBean = new ServletListenerRegistrationBean();
registrationBean.setListener(new MyHttpRequestListener());
registrationBean.setListener(new MyHttpSessionListener());
return registrationBean;
}
}
6、测试
@GetMapping("addSession")
public String addSession(HttpServletRequest request) {
HttpSession session = request.getSession();
session.setAttribute("name", "caocao");
return "当前在线人数:" + session.getServletContext().getAttribute("sessionCount") + "人";
}
@GetMapping("removeSession")
public String removeSession(HttpServletRequest request) {
HttpSession session = request.getSession();
session.invalidate();
return "当前在线人数:" + session.getServletContext().getAttribute("sessionCount") + "人";
}
@GetMapping("online")
public String online() {
return "当前在线人数:" + MyHttpSessionListener.userCount.get() + "人";
}
7、结果
filter、interceptor、listener的执行顺序为filter>interceptor>listener(HttpSessionListener),可以理解为从外到内,层层递进。