目录
- 一、拦截器
- 1. 拦截器是什么?
- 2. 设置拦截器
- a. 定义拦截器
- b. 配置加载拦截器
- c. 新建页面
- 二、过滤器
- 1. 使用原因
- 2. Filter概念图
- 3. Filter编程
- 三、监听器
一、拦截器
拦截器:必须保证页面有访问controller的操作,否则拦截不了
1. 拦截器是什么?
- 概念:拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用。
- 作用:在指定的方法调用预先设定的代码(preHandle、postHandle、afterCompletion)
- 使用:拦截controller的请求
2. 设置拦截器
a. 定义拦截器
preHandle:原始方法调用前执行
- 参数:
- request:请求对象
- response:响应对象
- handler:被调用的处理器对象
- 返回值:
- 返回值为true,则执行
- 返回值为false,则不执行
postHandler:原始方法调用后执行
- 参数:
- request:请求对象
- response:响应对象
- handler:被调用的处理器对象
- modelAndView:如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行跳
afterCompletion:原始方法调用完成后执行
- 参数:
- request:请求对象
- response:响应对象
- handler:被调用的处理器对象
- ex:异常对象
@Component //注意当前类必须受Spring容器控制
//定义拦截器类,实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
@Override
// 原始方法调用前执行的内容
// 返回值类型可以拦截控制的执行,true放行,false终止
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle..." + contentType);
//获取session中的数据
Object employee = request.getSession().getAttribute("employee");
//若为空,不放行,且写回页面指定数据
if (employee == null) {
R r = R.error("NOTLOGIN");
response.getWriter().print(JSON.toJSON(r));
return false;
}
return true;
}
@Override
// 原始方法调用后执行的内容
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...");
}
@Override
// 原始方法调用完成后执行的内容
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
b. 配置加载拦截器
方式一:可以继承WebMvcConfigurationSupport,但是默认静态资源路径不好使,必须重新映射
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Autowired
private MyInterceptor myInterceptor;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
// 配置拦截器
registry.addInterceptor(myInterceptor)
.addPathPatterns("/**") // 需要拦截的路径(/** 拦截所有路径)
.excludePathPatterns("/employee/login","/backend/**","/front/**");//放行静态资源和登陆资源;
}
}
方式二:可以实现WebMvcConfigurer接口,默认静态资源路径好使.还可以重新映射
@Configuration
// 实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class MvcConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
@Override
// 拦截器 添加拦截器并设定拦截的访问路径, 路径可以通过可变参数设置多个
/**
* addInterceptor:需要一个实现HandlerInterceptor接口的拦截器实例
* addPathPatterns:用于设置拦截器的过滤路径规则;addPathPatterns("/**")对所有请求都拦截
* excludePathPatterns:用于设置不需要拦截的过滤规则
* 拦截器主要用途:进行用户登录状态的拦截,日志的拦截等。
*/
pulbic void addInterceptors(InterceptorRegistry registry) {
// 配置拦截器
registry.addInterceptor(myInterceptor)
.addPathPatterns("/**")// 需要拦截的路径(/** 拦截所有路径)
.excludePathPatterns("/employee/login","/backend/**","/front/**");//放行静态资源和登陆资源;
}
}
c. 新建页面
方式一:我们可以查看WebProperties类的源码,看到静态资源可以存在于以下类路径下的几个路径中任意一个
- /META-INF/resources/
- /resources/
- /static/
- /public/
方式二:我们也可以将路径放在类路径下,通过mvc的配置类放行静态资源
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
@Override
// 拦截器 添加拦截器并设定拦截的访问路径, 路径可以通过可变参数设置多个
/**
* addInterceptor:需要一个实现HandlerInterceptor接口的拦截器实例
* addPathPatterns:用于设置拦截器的过滤路径规则;addPathPatterns("/**")对所有请求都拦截
* excludePathPatterns:用于设置不需要拦截的过滤规则
* 拦截器主要用途:进行用户登录状态的拦截,日志的拦截等。
*/
pulbic void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/employee/login","/backend/**","/front/**");//放行静态资源和登陆资源;
}
@Override
// 设置静态资源访问过滤,当前类需要设置为配置类,并被扫描加载
/**
* addResoureHandler:指的是对外暴露的访问路径
* addResourceLocations:指的是内部文件放置的目录
*/
pulbic void addResourceHandlers(ResourceHandlerRegistry registry) {
// 当访问/XXX/????时候,从/xxx目录下查找内容
// 1、注册backend静态资源处理方式 **匹配多级路径
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
// 2、注册front静态资源处理方式
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
}
二、过滤器
1. 使用原因
- 在一个比较复杂的Web应用程序中,通常都有很多URL映射,对应的也会有多个Servlet来处理URL。现将各个Servlet设计功能如下:
- 其中,ProfileServlet、PostServlet和ReplyServlet都需要用户登录后才能操作,否则,应当直接跳转到登录页面。
- 我们可以直接把判断登录的逻辑写到这3个Servlet中,但是,同样的逻辑重复3次没有必要,并且,如果后续继续加Servlet并且也需要验证登录时,还需要继续重复这个检查逻辑。
- 为了把一些公用逻辑从各个Servlet中抽离出来,JavaEE的Servlet规范还提供了一种Filter组件,即过滤器,它的作用是,在HTTP请求到达Servlet之前,可以被一个或多个Filter预处理,类似打印日志、登录检查等逻辑,完全可以放到Filter中。
2. Filter概念图
3. Filter编程
1. pom.xml导包
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
2. web.xml文件配置过滤器映射
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.kuang.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!--只要是 /servlet的任何请求,会经过这个过滤器-->
<url-pattern>/servlet/*</url-pattern>
<!--<url-pattern>/*</url-pattern>-->
<!-- 别偷懒写个 /* -->
</filter-mapping>
3. 过滤器代码
public class CharacterEncodingFilter implements Filter {
//初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
//Chain : 链
/*
1. 过滤中的所有代码,在过滤特定请求的时候都会执行
2. 必须要让过滤器继续同行
chain.doFilter(request,response);
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
System.out.println("CharacterEncodingFilter执行前....");
chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
System.out.println("CharacterEncodingFilter执行后....");
}
//销毁:web服务器关闭的时候,过滤器会销毁
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}
运行结果:首先检测URL是符合过滤器的Servlet映射,如果符合就过滤,即执行过滤器代码。