1.什么是过滤器?
过滤器的英文名称为Filter,是Servlet技术中最实用的技术。如同它的名字一样,过滤器是处于客户端与服务器资源文件之间的一道过滤网,帮助我们过滤一些不符合要求的请求。通常它被用作Session校验,判断用户权限,如果不符合设定条件,就会被拦截到特殊的地址或者给予特殊的响应。
2.如何使用过滤器?
使用过滤器很简单,只需要实现Filter接口即可,然后重写它的三个方法,方法描述如下:
void init(FilterConfig filterConfig):过滤器的初始化方法,在容器中创建过滤器的时候会自动调用此方法
boolean doFilter(ServletRequest request, ServletResponse response, FilterChain chain):当一个 Filter 对象能够拦截访问请求时,Servlet 容器将调用 Filter 对象的 doFilter 方法
void destroy:在容器中销毁当前过滤器时自动调用此方法
package com.fly.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* 自定义过滤器
*/
public class TestFilter implements Filter {
/**
* 过滤器的初始化方法,在容器中创建过滤器的时候会自动调用此方法
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化过滤器");
}
/**
* 当一个 Filter 对象能够拦截访问请求时,Servlet 容器将调用 Filter 对象的 doFilter 方法。
* ServletRequest:servlet请求对象,可以通过ServletRequest获取到HttpServletRequest
* ServletResponse:servlet响应对象,可以通过ServletResponse获取HttpServletResponse
* FilterChain:该接口用于定义一个 Filter 链的对象应该对外提供的方法,这个接口只定义了一个 doFilter 方法
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("请求被过滤器拦截");
//获取HttpServletRequest对象
HttpServletRequest httpServletRequest=(HttpServletRequest) request;
//获取请求地址
String url=httpServletRequest.getRequestURI();
System.out.println("请求地址是:"+url);
}
/**
* 在容器中销毁当前过滤器时自动调用此方法
*/
@Override
public void destroy() {
System.out.println("过滤器销毁");
}
}
3.什么是拦截器?
拦截器英文是Interceptor,用于拦截请求、权限校验、资源控制等等功能,实现拦截器有2种方式,第一种是实现HandlerInterceptor接口,第二种是继承实现了HandlerInterceptor接口的子类,例如HandlerInterceptorAdapter类
HandlerInterceptor接口三个重要方法说明:
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler):截处理程序的执行。在HandlerMapping确定适当的处理程序对象之后但在HandlerAdapter调用处理程序之前调用,preHandle方法是进行处理器拦截用的,表示是否允许通过拦截,为true则允许通过,该方法为true时才会执行postHandle方法,该方法将在Controller处理之前进行调用,该方法进行请求的预处理,可以进行编码、安全控制、权限校验等处理,Object handler表示拦截的对象
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception:postHandle是进行处理器拦截用的,它的执行时间是在处理器进行处理之后,也就是在Controller的方法调用之后执行,但是它会在DispatcherServlet进行视图的渲染之前执行,也就是说在这个方法中你可以对ModelAndView进行操作
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面),Exception可以获取DispatcherServlet处理请求后抛出的异常
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Des:自定义拦截器
* @Author:z乘风
* @Date:2020/5/6
*/
public class TestInterceptor implements HandlerInterceptor {
/**
* 作用:拦截处理程序的执行。在HandlerMapping确定适当的处理程序对象之后但在HandlerAdapter调用处理程序之前调用
* preHandle方法是进行处理器拦截用的,表示是否允许通过拦截,为true则允许通过,该方法为true时才会执行postHandle方法
* ,该方法将在Controller处理之前进行调用,
* 预处理,可以进行编码、安全控制、权限校验等处理
* Object handler表示拦截的对象
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
/**
* postHandle是进行处理器拦截用的,它的执行时间是在处理器进行处理之后,也就是在Controller的方法调用之后执行,
* 但是它会在DispatcherServlet进行视图的渲染之前执行,也就是说在这个方法中你可以对ModelAndView进行操作
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("处理器处理完毕后执行");
}
/**
* 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面)
* Exception可以获取DispatcherServlet处理请求后抛出的异常
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("DispatcherServlet处理完毕后调用");
}
}
4.什么是监听器?
监听器的英文是Listener,监听器liju就是监听某个对象的的状态变化的组件。
5.监听器的相关概念
事件源:被监听的对象 ——- 三个域对象 request session servletContext
监听器:监听事件源对象 事件源对象的状态的变化都会触发监听器 ——
注册监听器:将监听器与事件源进行绑定
响应行为:监听器监听到事件源的状态变化时 所涉及的功能代码 —— 程序员编写代码
6.监听器有哪些(下面列举的都是接口)?
根据被监听的对象来分:
ServletRequestListener:用于监听Request对象的操作
HttpSessionListener:用于监听web应用中的session对象,通常用于在线统计
ServletContextListener:用于监听ServletContext对象的操作,比如ServletContext对象的创建和销毁
根据被监听的内容来分:
ServletRequestAttributeListener:用于监听Request对象属性的操作
HttpSessionAttributeListener:用于监听web应用中session对象的属性操作
ServletContextAttributeListener:用于监听ServletContext对象的属性操作
实现在线统计人数案例:
package com.fly.listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* @Des:自定义监听器,实现在线人数统计
* @Author:z乘风
* @Date:2020/5/6
*/
public class TestListener implements HttpSessionListener {
private static int count=0;
/**
* session创建时调用
*/
@Override
public void sessionCreated(HttpSessionEvent se) {
count++;
System.out.println("当前在线人数为:"+count+"人");
}
/**
* session销毁时调用
*/
@Override
public void sessionDestroyed(HttpSessionEvent se) {
count--;
System.out.println("当前在线人数为:"+count+"人");
}
}
7.创建一个全局SpringBoot mvc 配置类
WebMvcConfigurer接口是用来全局制定 Spring Boot 的 mvc 特性。开发者通过实现 WebMvcConfigurer 接口来配置应用的 MVC 全局特性
首先我先把刚刚自定义的过滤器、拦截器、监听器代码摆上
TestFilter.class
package com.fly.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* 自定义过滤器
*/
public class TestFilter implements Filter {
/**
* 过滤器的初始化方法,在容器中创建过滤器的时候会自动调用此方法
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化过滤器");
}
/**
* 当一个 Filter 对象能够拦截访问请求时,Servlet 容器将调用 Filter 对象的 doFilter 方法。
* ServletRequest:servlet请求对象,可以通过ServletRequest获取到HttpServletRequest
* ServletResponse:servlet响应对象,可以通过ServletResponse获取HttpServletResponse
* FilterChain:该接口用于定义一个 Filter 链的对象应该对外提供的方法,这个接口只定义了一个 doFilter 方法
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("请求被过滤器拦截");
//获取HttpServletRequest对象
HttpServletRequest httpServletRequest=(HttpServletRequest) request;
//获取请求地址
String url=httpServletRequest.getRequestURI();
System.out.println("请求地址是:"+url);
}
/**
* 在容器中销毁当前过滤器时自动调用此方法
*/
@Override
public void destroy() {
System.out.println("过滤器销毁");
}
}
TestInterceptor.class
package com.fly.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Des:自定义拦截器
* @Author:z乘风
* @Date:2020/5/6
*/
public class TestInterceptor implements HandlerInterceptor {
/**
* 作用:拦截处理程序的执行。在HandlerMapping确定适当的处理程序对象之后但在HandlerAdapter调用处理程序之前调用
* preHandle方法是进行处理器拦截用的,表示是否允许通过拦截,为true则允许通过,该方法为true时才会执行postHandle方法
* ,该方法将在Controller处理之前进行调用,
* 预处理,可以进行编码、安全控制、权限校验等处理
* Object handler表示拦截的对象
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器允许通过!");
return true;
}
/**
* postHandle是进行处理器拦截用的,它的执行时间是在处理器进行处理之后,也就是在Controller的方法调用之后执行,
* 但是它会在DispatcherServlet进行视图的渲染之前执行,也就是说在这个方法中你可以对ModelAndView进行操作
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("处理器处理完毕后执行");
}
/**
* 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面)
* Exception可以获取DispatcherServlet处理请求后抛出的异常
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("DispatcherServlet处理完毕后调用");
}
}
TestListener.class
package com.fly.listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* @Des:自定义监听器,实现在线人数统计
* @Author:z乘风
* @Date:2020/5/6
*/
public class TestListener implements HttpSessionListener {
public static Integer count=0;
/**
* session创建时调用
*/
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("当前在线人数为:"+count+"人");
count++;
}
/**
* session销毁时调用
*/
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("当前在线人数为:"+count+"人");
count--;
}
}
创建SpringBoot mvc配置类,WebConfig.class:
package com.fly.config;
import com.fly.filter.TestFilter;
import com.fly.interceptor.TestInterceptor;
import com.fly.listener.TestListener;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.*;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 注入过滤器注册bean
*/
@Bean
FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean registrationBean=new FilterRegistrationBean();
registrationBean.setFilter(new TestFilter());
//过滤以/开头的请求
registrationBean.addUrlPatterns("/**");
return registrationBean;
}
/**
* 注入监听器注册bean
*/
@Bean
ServletListenerRegistrationBean listenerRegistrationBean(){
ServletListenerRegistrationBean registrationBean=new ServletListenerRegistrationBean();
registrationBean.setListener(new TestListener());
return registrationBean;
}
/**
* 注入拦截器注册器
* @return
*/
@Bean
InterceptorRegistration interceptorRegistration(){
InterceptorRegistration registration = new InterceptorRegistration(new TestInterceptor());
/**
* registration.addPathPatterns():添加拦截路径
* registration.excludePathPatterns():排除监听路径
*/
registration.addPathPatterns("/**");
return registration;
}
/**
* 添加拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加拦截器
registry.addInterceptor(new TestInterceptor());
}
/**
* 添加跨域处理
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
//允许以/**开头的url请求跨域
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("POST","GET")
.allowedOrigins("*");
}
/**
* 添加静态资源处理
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
/**
* 页面跳转处理
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
}
/**
* 默认静态资源处理器
*/
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
}
/**
* 视图解析器
* @param registry
*/
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
}
/**
* 信息转换器
* @param converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
}
TestController.class:
package com.fly.controller;
import com.fly.listener.TestListener;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@RestController
public class TestController {
@RequestMapping("/test")
public String test(){return "123";}
@RequestMapping("/addSession")
public String addSession(HttpServletRequest request){
HttpSession session = request.getSession();
session.setAttribute("name","zxp");
return "当前人数为:"+ TestListener.count+"人";
}
@RequestMapping("/removeSession")
public String removeSession(HttpServletRequest request){
HttpSession session = request.getSession();
//使session无效
session.invalidate();
return "当前人数为:"+ TestListener.count+"人";
}
@RequestMapping("/getCount")
public String getCount(){
return "当前人数为:"+ TestListener.count+"人";
}
}
测试过滤器、拦截器效果。浏览器访问localhost:8080/test 结果如下图:
测试在线人数统计案例。首先用谷歌浏览器访问localhost:8080/addSession ,然后在用其他浏览器访问此接口