前提:我们完成了项目登录功能的开发,但是我们发现一个问题,正常情况下我们需要登陆成功才能进入首页面,而此时我们直接输入主页面地址也可以成功访问到主页面,不满足实际需求,因此,我们需要对这一点进行改进。可使用springmvc的拦截器和javaweb阶段的过滤器实现登录拦截,我们此处使用过滤器。
建立包filter
需要实现其中的一个方法,并将方法形参中的两个参数进行强转,以便后文中对Session的操作
@WebFilter
直接使用过滤器不会生效@WebFilter(urlPatterns=“(需要过滤的地址)”, filterName=“(过滤器名称)”)
需要在springboot启动类上加上@ServletComponentScan注解才会生效(推荐这种方式)
![](https://img-blog.csdnimg.cn/img_convert/0c5d613aaf70bf4277d90d98c5fff2fd.png)
FilterChain:接口,该接口只有一个方法doFilter(ServletRequest request ,ServletResponse response)使用该方法可以调用过滤器链中的下一个 Filter 的 doFilter() 方法,若该 Filter 是链中最后一个过滤器,则调用目标资源的 service() 方法。
2.启动类加入注解才会扫描过滤器相关的部件
@ServletComponentScan
![](https://img-blog.csdnimg.cn/img_convert/f8083c64509832235f330de4b78fb2d0.png)
![](https://img-blog.csdnimg.cn/img_convert/0cb73649380c3fb56738f5744b819295.png)
接下来我们需要进行业务的实现,首先我们梳理一下实现流程,对于访问路径中,有些需要我们进行过滤,而有些并不需要可以直接放行,对于那些可以直接放行的路径,我们可以定义一个String数组,将这些路径都放进去,后面的操作中就可以将前端请求地址与这个数组中存放的路径做对比,如果有一样的,证明不需要拦截,就可以直接放行
//1、获取本次请求的URI
String requestURI = request.getRequestURI();// /backend/index.html
log.info("拦截到请求:{}",requestURI);
//定义不需要处理的请求路径
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**"
};
3.可以进一步优化方法
// 进行路径比较 路径匹配器 支持通配符
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
//最后调用方法进行路径匹配
boolean match=PATH_MATCHER.match(url,requestURI);
package itheima.reggie.filter;
//自定义过滤器
//检查用户是否完成登录
import com.alibaba.fastjson.JSON;
import itheima.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.HandshakeResponse;
import java.io.IOException;
//通过日志输出
@Slf4j
//指定过滤器名称
//urlPatterns:拦截哪些路径
//此时拦截所有请求
@WebFilter(filterName = "loginCheckFilter",urlPatterns ="/*" )
//实现过滤器接口
public class LoginCheckFilter implements Filter {
// 进行路径比较 路径匹配器 支持通配符
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
// 实现doFilter方法
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 向下转型 才能实现request.getRequestURI()方法
HttpServletRequest request= (HttpServletRequest) servletRequest;
HttpServletResponse response= (HttpServletResponse) servletResponse;
// {}占位符
// log.info("拦截到请求:{}",request.getRequestURI());
doFilter放行
// filterChain.doFilter(request, response);
//1、获取本次请求的URI
String requestURI = request.getRequestURI();// /backend/index.html
log.info("拦截到请求:{}",requestURI);
//定义不需要处理的请求路径
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**"
};
//2、判断本次请求是否需要处理
boolean check = check(urls, requestURI);
//3、如果不需要处理,则直接放行
if(check){
log.info("本次请求{}不需要处理",requestURI);
filterChain.doFilter(request,response);
return;
}
//4、判断登录状态,如果已登录,则直接放行
if(request.getSession().getAttribute("employee") != null){
log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));
filterChain.doFilter(request,response);
return;
}
log.info("用户未登录");
//5、如果未登录则返回未登录结果,通过输出流方式向客户端页面响应数据
// 将R对象转化成json格式然后通过输出流显示到页面
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
return;
}
/**
* 路径匹配,检查本次请求是否需要放行
* @param urls
* @param requestURI
* @return
*/
public boolean check(String[] urls,String requestURI){
for (String url:urls){
boolean match=PATH_MATCHER.match(url,requestURI);
if(match){
return true;
}
}
return false;
}
}