记一次HandlerInterceptor处理器拦截优化,解决preHandle()执行多次的问题

分享 未结 10 1425
你的瓦刀
你的瓦刀 站长 2020年3月28日 22:32 编辑
点击群号免费加入尼特社区交流群:813128395
<p id="descriptionP"><h2 id="e5adc384-9ba5-69c8-ec73-2a75dd0367f8"><span style="font-weight: bold;">1.简介</span></h2><div><p>preHandle方法是进行处理器拦截用的,顾名思义,该方法将在Controller处理之前进行调用。<br><br>SpringMVC中的Interceptor拦截器是链式的,可以同时存在多个Interceptor,然后SpringMVC会根据声明的前后顺序一个接一个的执行,而且所有的Interceptor中的preHandle方法都会在Controller方法调用之前调用。<br><br>(SpringMVC的这种Interceptor链式结构也是可以进行中断的,这种中断方式是令preHandle的返回值为false,当preHandle的返回值为false的时候整个请求就结束了。)<br><br><span style="color: rgb(255, 0, 0);">重写preHandle方法,在请求发生前执行。</span><br></p><p><span style="color: rgb(255, 0, 0);"><br></span></p><h2 id="fab69b9c-e929-b6c8-dcb7-7b18abe079fc"><span style="font-weight: bold;">2.问题</span></h2></div><div>我们先来看看尼特社区的原始代码:</div></p><pre><code>@Override<br> public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {<br> //设置广告<br> for (AdPosEnum adPos : AdPosEnum.values()) {<br> request.getServletContext().setAttribute(adPos.name(), adService.list(adPos.name()));<br> }<br><br> Cookie[] cookies = request.getCookies();<br> if(cookies!=null&amp;&amp;cookies.length!=0){<br> for (Cookie cookie : cookies) {<br> if(cookie.getName().equals("token")){<br> String token=cookie.getValue();<br> UserExample userExample = new UserExample();<br> userExample.createCriteria()<br> .andTokenEqualTo(token);<br> List&lt;User&gt; users = userMapper.selectByExample(userExample);<br> if(users.size()!=0){<br> User user = users.get(0);<br> UserAccountExample userAccountExample = new UserAccountExample();<br> userAccountExample.createCriteria().andUserIdEqualTo(user.getId());<br> List&lt;UserAccount&gt; userAccounts = userAccountMapper.selectByExample(userAccountExample);<br> UserAccount userAccount = userAccounts.get(0);<br> request.getSession().setAttribute("user",user);<br> request.getSession().setAttribute("userAccount",userAccount);<br> Long unreadCount = notificationService.unreadCount(users.get(0).getId());<br> request.getSession().setAttribute("unreadCount", unreadCount);<br> System.out.println("用户组ID:"+userAccount.getGroupId());<br> }<br> break;<br> }<br> }<br> }<br> return true;<br> }</code></pre><p><p>我们在调试中,打印登录用户的用户组ID,发现用户每次访问一个页面,preHandle()方法都会执行24次之多。<span style="color: rgb(255, 0, 0);">在大访问量下,这对服务器和数据库都会造成极大的压力,从而影响到性能。</span></p><p><img src="http://qcdn.niter.cn/upload/user/98/20200131194712_rcqeq.png" style="max-width:100%;"><br></p><p></p><p class="video"></p><p></p><p><br></p><h2 id="3f07b1a1-a91f-d444-ecf9-8f2b2b62bd1d"><span style="font-weight: bold;">3.解决方法</span></h2><p></p><p style="box-sizing: inherit; margin-top: 0px; margin-bottom: 0.5em; line-height: inherit; color: rgba(0, 0, 0, 0.87); font-family: &quot;PingFang SC&quot;, &quot;Helvetica Neue&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, &quot;Noto Sans CJK SC&quot;, Sathu, EucrosiaUPC, Arial, Helvetica, sans-serif;">我们发现拦截器会对页面用到的外部CSS,js,图片文件等静态资源也会进行拦截,所以我们只需要过滤掉队静态资源的拦截即可。我们在<span style="font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;PingFang SC&quot;, 微软雅黑, Tahoma, Arial, sans-serif;">preHandle()方法的最前部加入以下一行代码:</span></p><pre><code>if (handler instanceof ResourceHttpRequestHandler)<br> return true;</code></pre></p><p><p>再调试一次,发现只打印一次了。<span style="color: rgb(255, 0, 0);">问题解决!</span></p><p><img src="http://qcdn.niter.cn/upload/user/98/20200131195217_e6aca.png" style="max-width:100%;"><br></p></p>
收藏(0)  分享
相关标签: 讨论 java spring springmvc
注意:本文归作者所有,未经作者允许,不得转载
10个回复