目录
- 一,过滤器
- 1.1,自定义Filter
- 1.2,启动类代码
- 1.2,创建filter类和LoginFilter包
- 1.2.1,编写loginFilter类 过滤器代码
- 1.2.2,创建二个Controller类
- 二,监听器
- 2.1,自定义监听器
- 2.2,创建listenter包和MyListenter类
- 2.2.1,编写MyListenter类 监听器代码
- 三,拦截器
- 3.1,创建自定义拦截器配置类
- 3.2,创建配置包config和配置类MyWebMvcConfigurer
- 3.3,创建拦截器包interceptor和Logininterceptor类
- 四,按顺序进行拦截,先注册,先被拦截
一,过滤器
1.1,自定义Filter
- 使用Servlet3.0的注解进行配置
- 启动类里面增加 @ServletComponentScan ,进行扫描
- 新建一个Filter类,implements Filter ,并实现对应接口
- @WebFilter 标记一个类为Filter,被spring进行扫描
- urlPatterns:拦截规则,支持正则
- 控制chain.doFilter的方法的调用,来实现是否通过放行,
不放行的话,web应用resp.sendRedirect(“/index.html”)
场景:权限控制,用户登录(非前端后端分离场景)等
1.2,启动类代码
package com.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;@SpringBootApplication
@ServletComponentScan // 扫描select的注解
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class,args);}}
1.2,创建filter类和LoginFilter包
1.2.1,编写loginFilter类 过滤器代码
package com.demo.filter;import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;@WebFilter(urlPatterns = {"/*"})
@Order(Ordered.HIGHEST_PRECEDENCE) // 设置过滤器的排序,int类型
public class LoginFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("初始化过滤器");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("doFilter");
// servletResponse.setCharacterEncoding("UTF-8");// 设置响应的字符编码为UTF-8servletResponse.setCharacterEncoding("UTF-8");// 设置响应的内容类型为text/plain;charset=UTF-8servletResponse.setContentType("text/plain;charset=UTF-8");// 登录过滤器 有两种情况,需要放行// 1,登录请求要放行// 2. 不是登录请求,但是有登录tokenString uri = ((HttpServletRequest)servletRequest).getRequestURI();System.out.println(uri);if (uri.startsWith("/login/")){ // 判断是否以 /login/ 开头// 放行filterChain.doFilter(servletRequest,servletResponse);}else {// 从请求中获取tokenString token = ((HttpServletRequest)servletRequest).getParameter("token");if (token != null && !"".equals(token)){// 其实还需要进行解码,现在是只要有token就放行filterChain.doFilter(servletRequest,servletResponse);}else {PrintWriter pw = servletResponse.getWriter();pw.flush();pw.write("请先登录");pw.close();}}}@Overridepublic void destroy() {System.out.println("销毁过滤器");}
}
1.2.2,创建二个Controller类
看看是不是以login开头的放行
第一个controller类为LoginController
package com.demo.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/login")
public class LoginController {@RequestMapping("/doLogin")public Object doLogin(){return "登录接口";}
}
第二个controller类为HelloController
看看不是以login会不会过滤
package com.demo.controller;import com.demo.bean.Person;
import com.demo.config.BootProperties;
import com.demo.config.SysProperties;
import com.demo.util.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;
import javax.xml.crypto.Data;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.UUID;@RestController
public class HelloController {@Autowiredprivate BootProperties bootProperties;@RequestMapping("/test6")public Object test6(){return sysProperties.getParam1()+sysProperties.getParam2();}
}
// 整个之前的代码试试
证明过滤了,试试登录后
二,监听器
2.1,自定义监听器
- 自定义Listenter(常用监听器
servletContextListenter,
httpSessionListenter,
HTTPSessionAttributeListenter,
servletRequestListenter)
2.2,创建listenter包和MyListenter类
2.2.1,编写MyListenter类 监听器代码
package com.demo.listener;import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;@WebListener
public class MyListener implements ServletRequestListener {@Overridepublic void requestDestroyed(ServletRequestEvent servletRequestEvent) {System.out.println("请求被销毁");}@Overridepublic void requestInitialized(ServletRequestEvent servletRequestEvent) {System.out.println("请求被初始化创建");}
}
三,拦截器
3.1,创建自定义拦截器配置类
@Configuration
继承WebMvcConfigurationAdapter(SpringBoot2.X之前旧版本)
SpringBoot2.X新版本配置拦截器 implements WebMvcConfigurer
3.2,创建配置包config和配置类MyWebMvcConfigurer
package com.demo.config;import com.demo.interceptor.Logininterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration // 添加了Configuration的类,我们称之为配置类
public class MyWebMvcConfigurer implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new Logininterceptor()).addPathPatterns("/login/**");WebMvcConfigurer.super.addInterceptors(registry);}
}
3.3,创建拦截器包interceptor和Logininterceptor类
Logininterceptor类代码
package com.demo.interceptor;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class Logininterceptor implements HandlerInterceptor {// 调用Controller某个方法之前,判断是否要不要处理@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return false; // false是拦截, true是不拦截}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion");}
}
四,按顺序进行拦截,先注册,先被拦截
拦截器不生效的常见问题:
- 是否有加@Configuration
- 拦截器是否有路径问题 ** 和 *
- 拦截器最后路径一定要 " /** " ,如果是目录的话则是 /*/
Filter
是基于函数回调 doFilter(),而lnterceptor则是基于AOP思想
Filter在只在Servlet前后起作用,而lnterceptor够深入到方法前后,异常抛出前后等
依赖于Servlet容器即web应用中,而lnterceptor不依赖于Servlet容器所以可以运行在多种环境。
在接口调用的声明周期里,lnterceptor可以被多次调用,而Filter只能在容器中初始化调用一次。
Filter和lnterceptor的执行顺序
过滤前 --> 拦截前 --> action(handler) --> 执行 --> 拦截后 --> 过滤后