idea Cannot open URL.Please check this URL is correct

 

  需求:

测试经过Filter访问特定目录下资源时  需要会话域中存在登陆过的信息(已经成功登陆过)  否则不能直接访问该目录下资源 给浏览器重定向一个登陆页面

 

问题:

过滤器在服务器启动的阶段已经实例化,访问的Conroller  静态界面,都要经过过滤器的筛选,此时首次访问中 Filter 的会话域并没有匹配的数据  过滤器重定向的资源也在过滤器的过滤范围之内  导致死循环,就会出现该问题

 

 

 

单独写一个Filter 组成过滤器链, 并且该过滤器的<url-pattern>只能指定需要过滤的目录  即:  针对该需求过滤的路径只是所有请求路径中的一部分不能包含登录页面路径和过滤失败的重定向页面路径  否则线程无线循环在Filter中 启动项目时IDEA控制台 idea Cannot open URL.Please check this URL is correct报错

 

在过滤器链中登陆页面路径和过滤失败重定向页面路径在其他Filter中不能被拦截  或者  在一个Filter中编写业务时重定向的页面不参与过滤路径 避免死循环  

以下是一个死循环的例子:  

首次访问/pages/*  路径下页面需要session域中信息比对,  而session域中因为首次访问没有对应的信息 重定向到login.jsp  结果login.jsp也在过滤器拦截范围内

<url-pattern>/*</url-pattern>再次进入Filter死循环

java类:public class TestFilter implements Filter {


public void init(FilterConfig filterConfig) throws ServletException {
}

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;

String requestURI = request.getRequestURI();
HttpSession session = request.getSession();
String value = (String) session.getAttribute("username");
if (value == null) {
//因为是首次访问session域中没有该用户记录
response.sendRedirect(request.getContextPath()+"/login.jsp");
System.out.println("拦截非法请求");
} else {
//该用户曾登陆过
filterChain.doFilter(servletRequest, servletResponse);
}

//指定目录之外的请求放行
filterChain.doFilter(servletRequest, servletResponse);
}

public void destroy() {
}
}

web.xml:
<filter>
<filter-name>firstFilter</filter-name>
<filter-class>com.midea.filter.TestFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>firstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

 

 

 

 

解决办法 1:

通过业务逻辑添加一个if 判断  将目标资源路径单独拿出来作判断  满足条件放行  不满足重定向 并且该重定向页面不在 if 路径判断之内

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

System.out.println("进入Filter");
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;

String requestURI = request.getRequestURI();
//requestURI是否包含 /contextPath/pages/
if (requestURI.startsWith(request.getContextPath() + "/pages/", 0)) { //将目标目录下资源单独拿出来作 if 判断
HttpSession session = request.getSession();
String value = (String) session.getAttribute("username");
if (value == null) {
        //重定向的页面 login.jsp 不能在 /pages/* 下 否则又是死循环
response.sendRedirect(request.getContextPath()+"/login.jsp");
System.out.println("拦截非法请求");
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
//if 路径之外的请求放行 (失败后的重定向login.jsp 就是通过该渠道登录到项目)
filterChain.doFilter(servletRequest, servletResponse);
}

<filter>
<filter-name>firstFilter</filter-name>
<filter-class>com.midea.filter.TestFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>firstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


解决办法 2:
单独写一个Filter 组成过滤器链, 并且该过滤器的<url-pattern>只能指定需要过滤的目录  
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>com.midea.filter.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/pages/*</url-pattern>
</filter-mapping>

<filter>
<filter-name>secondFilter</filter-name>
<filter-class>com.midea.filter.secondFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>secondFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
TestFilter类: 解决办法 1 中的代码    secondFilter类:  直接全路径放行没有任何拦截  
这样就将 TestFilter 中的  response.sendRedirect(request.getContextPath()+"/login.jsp");
从<url-pattern>/pages/*</url-pattern>摘了出来
觉得有用的点个赞吧

posted @   __Ethan  阅读(1720)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程
点击右上角即可分享
微信分享提示