springboot中的过滤器、拦截器、监听器整合使用
原创
©著作权归作者所有:来自51CTO博客作者TvT~的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
- controller层
- 过滤器
- 拦截器
controller层
用于测试
@RestController
public class TestController {
@GetMapping("/addSession")
public String addSession(HttpServletRequest request) {
HttpSession session = request.getSession();
session.setAttribute("name", "dalaoyang");
return "当前在线人数" + MyHttpSessionListener.online;
}
@GetMapping("/removeSession")
public String removeSession(HttpServletRequest request) {
HttpSession session = request.getSession();
session.invalidate();
return "当前在线人数" + MyHttpSessionListener.online;
}
@GetMapping("/online")
public String online() {
return "当前在线人数:" + MyHttpSessionListener.online + "人";
}
}
过滤器
过滤器的英文名称为Filter,是Servlet技术中最实用的技术。如同它的名字一样,过滤器是处于客户端与服务器资源文件之间的一道过滤网,帮助我们过滤一些不符合要求的请求。通常它被用作Session校验,判断用户权限,如果不符合设定条件,就会被拦截到特殊的地址或者给予特殊的响应。 2. 使用过滤器 使用过滤器很简单,只需要实现Filter类,然后重写它的3个方法即可。 · init方法:在容器中创建当前过滤器的时候自动调用这个方法。 · destory方法:在容器中销毁当前过滤器的时候自动调用这个方法。 · doFilter方法:这个方法有3个参数,分别是ServletRequest、ServletResponse和FilterChain。可以从参数中获取HttpServletRequest和HttpServletResponse对象进行相应的处理操作。 接下来,我们直接创建一个过滤器MyFilter。这里做一些URL的拦截,如果符合条件,就正常跳转,如果不符合条件,就拦截到/online请求中。
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("MyFilter被调用");
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper((HttpServletResponse) response);
//只有符合条件的可以直接请求,不符合的跳转到/online请求去
String requestUri = httpServletRequest.getRequestURI();
System.out.println("请求地址是:"+requestUri);
if (requestUri.indexOf("/addSession") != -1
|| requestUri.indexOf("/removeSession") != -1
|| requestUri.indexOf("/online") != -1
|| requestUri.indexOf("/favicon.ico") != -1) {
chain.doFilter(request, response);
} else {
wrapper.sendRedirect("/online");
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//在服务启动时初始化
System.out.println("初始化拦截器");
}
@Override
public void destroy() {
//在服务关闭是销毁
System.out.println("销毁拦截器");
}
}
拦截器
拦截器介绍
Java中的拦截器是动态拦截action调用的对象,然后提供了可以在action执行前后增加一些操作,也可以在action执行前停止操作。其实拦截器也可以做和过滤器同样的操作,以下是拦截器的常用场景。
登录认证:在一些简单应用中,可能会通过拦截器来验证用户的登录状态,如果没有登录或者登录失效,就会给用户一个友好的提示或者返回登录页面。
记录系统日志:在Web应用中,通常需要记录用户的请求信息,比如请求的IP、方法执行时常等,通过这些记录可以监控系统的状况,以便于对系统进行信息监控、信息统计、计算PV(Page View)和性能调优等。 ·
通用处理:在应用程序中可能存在所有方法都要返回的信息,这时可以使用拦截器来实现,省去每个方法冗余重复的代码实现。
使用拦截器
这里以使用Spring拦截器为例,在类上需要实现HandlerInterceptor类,并且重写类中的3个方法,分别是: ·
▶▶▶preHandle 在业务处理器处理请求之前被调用,返回值是boolean值,如果返回true,就进行下一步操作;若返回false,则证明不符合拦截条件。在失败的时候不会包含任何响应,此时需要调用对应的response返回对应响应。 ·
▶▶▶postHandle 在业务处理器处理请求执行完成后、生成视图前执行。这个方法可以通过方法参数ModelAndView对视图进行处理,当然ModelAndView也可以设置为null。 ·
▶▶▶afterCompletion 在DispatcherServlet完全处理请求后被调用,通常用于记录消耗时间,也可以进行一些资源处理操作。 接下来,创建一个自定义拦截器MyInterceptor,我们用这个拦截器打印请求的耗时,并且判断当前的浏览器是否存在Session。
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle被调用");
request.setAttribute("startTime", System.currentTimeMillis());
//request.setAttribute将值添加到了http请求头上
//request.getAttribute表示从request范围取得设置的属性,必须要先setAttribute设置属性,才能通过getAttribute来取得,设置与取得的为Object对象类型 。
//request.setAttribute (“curruser”, curruser)这个方法是将curruser这个对象保存在request作用域中,然后在转发进入的页面就可以获取到你的值,
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle被调用");
HttpSession session = request.getSession();
String name = (String) session.getAttribute("name");
if("dalao".equals(name)){
System.out.println("--------------------当前浏览器存在session");
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion被调用");
long startTime = (Long) request.getAttribute("startTime");
System.out.println("--------------------请求耗时:" + (System.currentTimeMillis() - startTime));
}
}
监听器
监听器介绍
▶▶▶ServletContextListener:用来监听ServletContext属性的操作,比如新增、修改、删除。 ·
▶▶▶HttpSessionListener:用来监听Web应用中的Session对象,通常用于统计在线情况。 ·
▶▶▶ServletRequestListener:用来监听Request对象的属性操作。
使用监听器
使用监听器的话,只需要在类中实现对应功能的监听器对象,如本文使用的HttpSessionListener。下面以监听Session信息为例统计在线人数。新建一个MyHttpSessionListener类,实现HttpSessionListener类,在类中定义一个全局变量online,当创建Session时,online的数量加1;当销毁Session时,online的数量减1
MyHttpSessionListener完整内容:
public class MyHttpSessionListener implements HttpSessionListener {
public volatile static int online = 0;
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("sessionCreated被调用");
online ++;
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("sessionDestroyed被调用");
online --;
}
}
修改启动类
过滤器、监听器和拦截器我们已经创建好了,但是还不能引用。接下来我们修改Spring Boot启动类,在类中通过注入Bean的方式引用三者。启动类完整内容如代码清单11-16所示(也可以使用其他方法引用,比如创建一个配置类统一管理)。
@SpringBootApplication
public class Chapter114Application implements WebMvcConfigurer {
public static void main(String[] args) {
SpringApplication.run(Chapter114Application.class, args);
}
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor);
}
@Bean
public FilterRegistrationBean filterRegist() {
FilterRegistrationBean frBean = new FilterRegistrationBean();
frBean.setFilter(new MyFilter());
frBean.addUrlPatterns("/*");
return frBean;
}
@Bean
public ServletListenerRegistrationBean listenerRegist() {
ServletListenerRegistrationBean srb = new ServletListenerRegistrationBean();
srb.setListener(new MyHttpSessionListener());
return srb;
}
}
测试:
换一个浏览器:
在浏览器输入非online addsession removesession等的其他地址,会自动跳转到online: