1.过滤器
过滤器
package com.cnooc.dictionary.utils.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//计算请求时间案例
//实现了过滤特定url请求的拦截器,并配置到spring中
@Component
@Slf4j
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//启动的时候初始化
log.info("初始化过滤器: " + filterConfig.getFilterName());
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//对请求进行预处理
log.info("过滤器开始对请求进行预处理:");
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String requestUri = request.getRequestURI();
System.out.println("请求的接口为:" + requestUri);
long startTime = System.currentTimeMillis();
//通过 doFilter 方法实现过滤功能
filterChain.doFilter(servletRequest, servletResponse);
// 上面的 doFilter 方法执行结束后用户的请求已经返回
long endTime = System.currentTimeMillis();
System.out.println("该用户的请求已经处理完毕,请求花费的时间为:" + (endTime - startTime));
}
@Override
public void destroy() {
//停止的时候销毁
log.info("销毁过滤器");
}
}
配置过滤器
package com.cnooc.dictionary.utils.filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class MyFilterConfig {
@Bean
public FilterRegistrationBean<MyFilter> thirdFilter() {
FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new MyFilter());
List<String> urls = new ArrayList<>();
//配置需要过滤的url
urls.add("/classifyApi/*");
urls.add("/entryApi/*");
//拦截url
filterRegistrationBean.setUrlPatterns(urls);
//多个过滤器配设置执行顺序
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
}
2.拦截器
下面实现了3个拦截器,并分别配置到spring中
拦截器1
package com.cnooc.dictionary.utils.Interceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LogInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
long startTime = System.currentTimeMillis();
System.out.println("\n-------- LogInterception.preHandle --- ");
System.out.println("请求路径: " + request.getRequestURL());
System.out.println("开始时间: " + System.currentTimeMillis());
request.setAttribute("startTime", startTime);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("\n-------- LogInterception.postHandle --- ");
System.out.println("请求路径: " + request.getRequestURL());
// You can add attributes in the modelAndView
// and use that in the view page
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("\n-------- LogInterception.afterCompletion --- ");
long startTime = (Long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
System.out.println("请求路径: " + request.getRequestURL());
System.out.println("结束时间: " + endTime);
System.out.println("耗时: " + (endTime - startTime));
}
}
拦截器2
package com.cnooc.dictionary.utils.Interceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class OldLoginInterceptor extends HandlerInterceptorAdapter {
/**
* 在这儿从定向到/admin/login
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("\n-------- OldLoginInterceptor.preHandle --- ");
System.out.println("Request URL: " + request.getRequestURL());
System.out.println("Sorry! 这个借口被弃用了, 重定向到 /admin/login");
response.sendRedirect(request.getContextPath() + "/admin/login");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
//因为重定向了,这段代码永远不会运行
System.out.println("\n-------- OldLoginInterceptor.postHandle --- ");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
//这段代码永远不会运行
System.out.println("\n-------- QueryStringInterceptor.afterCompletion --- ");
}
}
拦截器3
package com.cnooc.dictionary.utils.Interceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AdminInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("\n-------- AdminInterceptor.preHandle --- ");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("\n-------- AdminInterceptor.postHandle --- ");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("\n-------- AdminInterceptor.afterCompletion --- ");
}
}
配置3个拦截器
package com.cnooc.dictionary.utils.Interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//loginteceptor 允许通过所有的url
registry.addInterceptor(new LogInterceptor());
//老的登录被弃用,重定向到新的url
registry.addInterceptor(new OldLoginInterceptor())
.addPathPatterns("/admin/oldLogin");
//此拦截器适用于 /admin/* 包括 /admin/oldLogin 这样的URL
registry.addInterceptor(new AdminInterceptor())
.addPathPatterns("/admin/*")
//排除/admin/oldLogin
.excludePathPatterns("/admin/oldLogin");
}
}
3.监听器
使用场景
比如监听 Servlet 上下文用来初始化一些数据、监听 HTTP Session 用来获取当前在线的人数、监听客户端请求的ServletRequest 对象来获取用户的访问信息等等。
监听 Servlet 上下文对象
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
@Component
public class MyServletContextListener implements ApplicationListener<ContextRefreshedEvent> {
/**
* 在spring容器初始化(启动后)完成之后执行。
* @param contextRefreshedEvent --上下文刷新事件
*/
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
System.out.println("Spring容器加载完成触发,可用于初始化环境,准备测试数据、加载一些数据到内存");
//此处可以开启一个线程,用于查询首页数据,并缓存在内容或redis中,供所有的首页进行查询
//代码省略
}
}
监听 HTTP Session 对象
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* 获取实时用户数量
*/
@Component
@Slf4j
public class MyHttpSessionListener implements HttpSessionListener {
public static Integer count = 0; //记录在线的用户数量
@Override
public synchronized void sessionCreated(HttpSessionEvent httpSessionEvent) {
log.info("新用户上线了");
count++;
httpSessionEvent.getSession().getServletContext().setAttribute("count", count);
}
@Override
public synchronized void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
log.info("用户下线了");
count--;
httpSessionEvent.getSession().getServletContext().setAttribute("count", count);
}
}
监听请求Request对象
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
/**
* 实现request访问前后的方法
*/
@Component
@Slf4j
public class MyServletRequestListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
log.info("session id为:{}", request.getRequestedSessionId());
log.info("request url为:{}", request.getRequestURL());
request.setAttribute("name", "zyd");
}
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
log.info("request end");
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
log.info("request域中保存的name值为:{}", request.getAttribute("name"));
}
}
自定义监听器
自定义监听器步骤
创建自定义事件,继承ApplicationEvent。
发布我们的自定义事件,一般通过实现ApplicationEventPublisherAware 接口来完成。
定义事件监听器,一般是实现ApplicationListener接口或者使用@EventListener注解。
1.创建自定义事件
import org.springframework.context.ApplicationEvent;
/**
* 创建自定义事件,继承ApplicationEvent
*/
public class MyApplicationEvent extends ApplicationEvent {
private static final long serialVersionUID = -9110297575225719030L;
private final String address;
public final String test;
public MyApplicationEvent(Object source, String address, String test) {
super(source);
this.address = address;
this.test = test;
}
@Override
public String toString() {
return "MyApplicationEvent [address=" + address + ", test=" + test + "]";
}
// accessor and other methods...
}
2.发布自定义事件
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* 一调用MyApplicationEventService类的sendEmail()或testListener()方法,监听器就会触发。
*/
@Component
public class MyApplicationEventService implements ApplicationEventPublisherAware {
private List<String> blackList;
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
//自己的方法1
public void sendEmail(String address, String text) {
blackList = new ArrayList<>();
blackList.add("known.spammer@example.org");
blackList.add("known.hacker@example.org");
blackList.add("john.doe@example.org");
if (blackList.contains(address)) {
publisher.publishEvent(new MyApplicationEvent(this, address, text));
return;
}
// send email...
}
//自己的方法2
public void testListener(String address, String text) {
MyApplicationEvent event = new MyApplicationEvent(this, address, text);
publisher.publishEvent(event);
}
}
3.定义事件监听器
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* 自己的业务代码可以写到监听器中
* 事件监听器方式1: 实现接口
*/
@Component
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {
@Override
public void onApplicationEvent(MyApplicationEvent event) {
//监听到了
//操作此处的event中的数据
System.out.println("my listener start");
System.out.println(event.toString());
System.out.println("my listener end");
}
}
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
/**
* 自己的业务代码可以写到监听器中
* 事件监听器2 使用注解
*/
@Component
public class MyApplicationListener2 {
@EventListener
//使用注解还可以监听多个事件,如下
// @EventListener({ContextRefreshedEvent.class, MyApplicationEvent .class})
public void onApplicationEvent(MyApplicationEvent event) {
//监听到了
//操作此处的event中的数据
System.out.println("my listener start");
System.out.println(event.toString());
System.out.println("my listener end");
}
}
4.测试调用监听
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("listener")
public class ListenerController {
@Autowired
private MyApplicationEventService myApplicationEventService;
@GetMapping("/listener")
public String testMyListener() {
/*myApplicationEventService.sendEmail("john.doe@example.org", "123123"); */
myApplicationEventService.testListener("john.doe@example.org", "123");
return "SUCCESS";
}
}