SpringBoot中应用Web Filter
最近要给自己的项目里面加个filter,结果折腾了好几天终于弄好了,记录一下。
web的逻辑是这样的,首先给前台控件写好click或者change方法,点击控件的时候,用ajax向后台请求数据,然后封装请求的数据成json返回前台,ajax拿到json数据进行更新操作。
Filter过程中遇到过无限请求,无限过滤,死循环等等一系列的问题,目前只是把Filter这一种方案做成了,Springboot自带的Interceptor仍然没有调试成功。
总结如下:
1.如果遇到控件不生效的问题:
- 检查id选择器应该用#id,class选择器应该用.Class,且没有重名。
- 是否使用的是a标签中的onclick方法,不知道为啥笔者用的时候Filter死活不生效,因此在外面直接用jquery写click方法就可以了,如果有谁知道原因,还请不吝赐教。
2.如果遇到无限循环的问题请依此检查:
- 检查是不是没有设置跳出白名单。
- 是否所有例外请求都被加入过滤白名单了,如果有一个少加死循环的概率会很大
- 是否每一个condition都有处理逻辑,该放过的用
chain.doFilter(request, response)放过,该重定向的用res.sendRedirect(REDIRECT_URL)重定向。 - 是否有额外的
chain.doFilter(request, response)语句导致了无限请求。
贴代码
package com.lenovo.integration.filter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Component;
@Component
@WebFilter(urlPatterns = "/**", filterName = "loginFilter")
public class LoginFilter implements Filter {
private static final String[] excludePathPatterns = { "/login", "/login/loginPost", "/login/accountCheck","/login/logout",
"/ex/register", "/consultant/addConsultant", "/teams/getTeams", "/company/getCompanies" };/*设置循环跳出的例外请求(白名单)*/
private static String REDIRECT_URL = "/login";
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//System.out.println("开始拦截了................");
HttpServletRequest req = (HttpServletRequest) request; /*拿到请求*/
HttpServletResponse res = (HttpServletResponse) response; /*拿到回复*/
String requestUri = req.getRequestURI(); /*获取当前的request uri*/
String goURL = req.getServletPath(); /*获取当前的servlet路径,也包含文件名,可以用这种办法放过静态资源,用"/static/**"这样的写法不太好用*/
if (Arrays.asList(excludePathPatterns).contains(requestUri)) {
//碰见白名单放过
chain.doFilter(request, response);
} else if (goURL.endsWith(".js") || goURL.endsWith(".css") || goURL.endsWith(".svg") || goURL.endsWith(".png")
|| goURL.endsWith(".map") || goURL.endsWith(".ico")) {
//碰见静态资源放过
chain.doFilter(request, response);
} else {
//其他,开始执行拦截逻辑
HttpSession session = req.getSession();
if (null == session.getAttribute("sessionAccount")) {
res.sendRedirect(REDIRECT_URL);
} else {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date=df.format(new Date());
System.out.println("["+date+"]");
System.out.println("session is NOT null:" + req.getContextPath() + requestUri);
chain.doFilter(request, response);
}
}
}
//chain.doFilter(request, response); 笔者测试的时候这里写了一个放过语句结果忘了删了,于是陷入了无限请求和无限过滤的尴尬境地
}工作流
Filter的工作流如下:
- 开始第一次拦截,判断是否是白名单?是:放过,开始下一次请求;
- 否:是否是静态资源?是:放过,开始下一次请求;
- 否:获取session,判断是否session有合法的信息?是:放过,执行程序逻辑发给前台显示。
- 否:发给重定向的请求,并对这个重定向进行拦截。
从这里就能看出来,如果跳出条件没有设置好,很容易陷入死循环,无限重定向直到最大值,浏览器报错网页无法响应。
Created with Raphaël 2.2.0 开始 Request URI 拦截(filter) 白名单? static ? session存在? 放过(chain.doFilter(req,res)) 前台显示,结束循环 重定向 yes no yes no yes no
















