- 使用Servlet3.0的注解进行配置
- 启动类里面增加 @ServletComponentScan ,进行扫描
- 新建一个Filter类,implements Filter ,并实现对应接口
- @WebFilter 标记一个类为Filter,被spring进行扫描
- urlPatterns:拦截规则,支持正则
- 控制chain.doFilter的方法的调用,来实现是否通过放行,
不放行的话,web应用resp.sendRedirect(“/index.html”)
场景:权限控制,用户登录(非前端后端分离场景)等
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);
}
}
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 {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化过滤器");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("doFilter");
// servletResponse.setCharacterEncoding("UTF-8");
// 设置响应的字符编码为UTF-8
servletResponse.setCharacterEncoding("UTF-8");
// 设置响应的内容类型为text/plain;charset=UTF-8
servletResponse.setContentType("text/plain;charset=UTF-8");
// 登录过滤器 有两种情况,需要放行
// 1,登录请求要放行
// 2. 不是登录请求,但是有登录token
String uri = ((HttpServletRequest)servletRequest).getRequestURI();
System.out.println(uri);
if (uri.startsWith("/login/")){ // 判断是否以 /login/ 开头
// 放行
filterChain.doFilter(servletRequest,servletResponse);
}else {
// 从请求中获取token
String 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();
}
}
}
@Override
public void destroy() {
System.out.println("销毁过滤器");
}
}
看看是不是以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 {
@Autowired
private BootProperties bootProperties;
@RequestMapping("/test6")
public Object test6(){
return sysProperties.getParam1()+sysProperties.getParam2();
}
}
// 整个之前的代码试试
- 自定义Listenter(常用监听器
servletContextListenter,
httpSessionListenter,
HTTPSessionAttributeListenter,
servletRequestListenter)
package com.demo.listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
System.out.println("请求被销毁");
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
System.out.println("请求被初始化创建");
}
}
@Configuration
继承WebMvcConfigurationAdapter(SpringBoot2.X之前旧版本)
SpringBoot2.X新版本配置拦截器 implements WebMvcConfigurer
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 {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new Logininterceptor()).addPathPatterns("/login/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
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某个方法之前,判断是否要不要处理
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return false; // false是拦截, 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");
}
}
拦截器不生效的常见问题:
- 是否有加@Configuration
- 拦截器是否有路径问题 ** 和 *
- 拦截器最后路径一定要 " /** " ,如果是目录的话则是 /*/
Filter
是基于函数回调 doFilter(),而lnterceptor则是基于AOP思想
Filter在只在Servlet前后起作用,而lnterceptor够深入到方法前后,异常抛出前后等
依赖于Servlet容器即web应用中,而lnterceptor不依赖于Servlet容器所以可以运行在多种环境。
在接口调用的声明周期里,lnterceptor可以被多次调用,而Filter只能在容器中初始化调用一次。
Filter和lnterceptor的执行顺序
过滤前 --> 拦截前 --> action(handler) --> 执行 --> 拦截后 --> 过滤后