为什么当项目启动后执行两次过滤器 再进行访问资源时执行一次过滤器

为什么当项目启动后执行两次过滤器 再进行访问资源时执行一次过滤器

粗线的理解,启动项目后进行了两次请求,访问两次过滤器。访问资源时只进行一次请求,所以访问一次过滤器。
于是为了更加清楚地看清在启动项目后进行了哪两次请求,我特意将request信息进行展示。

 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse 		 servletResponse, FilterChain filterChain) throws IOException, 			ServletException {
        System.out.println("request"+servletRequest);
        System.out.println("filterDemo1被执行了");
        //放行
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("filterDemo1回来");
        System.out.println("response"+servletResponse);
    }

运行结果如下图所示,可以说符合假设,在启动服务器时对index.jsp资源请求了两次,并得到了两次响应。因为可以看到@后面的hash值是不一样的。
在这里插入图片描述
如果是在启动服务器后,通过浏览器访问,只会出现一次请求与一次响应。通过结果来看,你会看到一个请求一个响应,但是这个请求对象与响应对象和服务器最后一次请求与响应是一个对象。并且,之后再对index.jsp资源进行访问的时候,都是同一个对象。如下图所示。
在这里插入图片描述
于是我在想,是不是存在一种可能,就是服务器会将所有资源都会去请求一遍,类似于检测是否各个模块出现未检测出来的运行时异常呢?于是我添加了2个jsp文件,如果假设成立,那么我们会看到四组请求与响应。期待结果。如下图所示,结果表明,即使在有多个jsp资源的情况下,也不会预先地去访问其他jsp,这种假设是错误的。当然,还发现,其实浏览器用的是一个request和response对象对资源进行访问的。因此结论暂定为:服务器在启动时会对index.jsp产生两次请求及响应。
在这里插入图片描述

延伸但又相关

如果我们设置注解参数
dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST}
这样就说明如果浏览器直接请求和转发的方式都可以触发filter。如果我们在index.jsp中放入转发的代码,服务器第一次启动后,发现两次请求转发的request和response相同。这个结果和我们上文提到的对于没有转发代码,只是单纯访问index.jsp的结果是不一样的。所以有转发的index.jsp服务器可能存在“在第一次进行请求index.jsp页面的时候转发后将request和response对象记录了下来”的情况。所以第二次再请求的时候一样的现象。
另外的问题是,转发和直接访问触发过滤器的方式会触发几次过滤器,实验结果是一次。(在服务器启动后访问)如下图所示。
在这里插入图片描述

filter链的访问次数情况

与转发、浏览器访问组合方式的情况一样,request和response只创建一次。并且请求两次,但由于是链的缘故,所以它会按照递归方式进行请求与响应,如下图。
在这里插入图片描述

希望有其它想法的博主进行留言!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
可以通过自定义过滤器来实现限制每个用户访问接口的次数,以下是一个Java项目中使用过滤器限制每个用户一小内只能访问一次的示例代码: ```java import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.util.*; public class LimitFilter implements Filter { // 存储每个用户上次访问间的Map,key为用户ID,value为上次访问间 private Map<String, Long> lastVisitedTimeMap = new HashMap<>(); // 最大允许访问次数 private static final int MAX_VISIT_COUNT = 1; // 间限制(毫秒),这里设置为1小 private static final long TIME_LIMIT = 60 * 60 * 1000; public void init(FilterConfig config) throws ServletException { // 初始化操作 } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; String userId = getUserId(request); // 获取用户ID if (userId != null) { long currentTime = System.currentTimeMillis(); Long lastVisitedTime = lastVisitedTimeMap.get(userId); if (lastVisitedTime == null || currentTime - lastVisitedTime >= TIME_LIMIT) { // 如果用户从未访问过或者距离上次访问间超过了限制间 lastVisitedTimeMap.put(userId, currentTime); chain.doFilter(request, response); // 继续执行过滤器链 } else { // 如果用户访问次数超过了限制 response.getWriter().write("您的访问次数已达到上限,请一个小后再试!"); } } else { // 如果无法获取用户ID,直接继续执行过滤器链 chain.doFilter(request, response); } } public void destroy() { // 销毁操作 } private String getUserId(HttpServletRequest request) { // 获取用户ID的方法,可以根据实际情况自行编写 // 这里假设用户ID存储在请求头中的Authorization字段中 return request.getHeader("Authorization"); } } ``` 上述代码中,我们使用了一个HashMap来存储每个用户上次访问间,过滤器每次处理请求都会从请求中获取用户ID,然后根据用户ID在Map中查找上次访问间,如果上次访问间距离当前间超过了限制间,则更新Map中的访问间,并继续执行过滤器链;否则返回提示信息,不再继续执行过滤器链。注意,这里我们假设用户ID存储在请求头中的Authorization字段中,实际情况中可能需要根据具体的业务需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值