在Java Web开发中,Session为我们提供了很多方便,Session是由浏览器和服务器之间维护的。Session超时理解为:浏览器和服务器之间创建了一个Session,由于客户端长时间(休眠时间)没有与服务器交互,服务器将此Session销毁,客户端再一次与服务器交互时之前的Session就不存在了。
0.需求
需要对所有的/web/**请求进行登录拦截,Session超时时跳转到登录页面。
1.引入
一般来说,在项目使用中都会配置Session超时时间,如果不配置,则默认值为30分钟,即用户不操作30分钟以后,Session就会失效,此时用户就需要重新登录系统。
Session超时时间的配置主要的项目的web.xml中进行配置,如下:
1
|
< span style = "font-size: 14px;" > <!-- 设置Session超时时间 --> < br > < session-config > < br > <!-- 分钟 --> < br > < session-timeout >60</ session-timeout > < br > <!-- 去除URL上显示的jsessionid, 防止打开Tab页时出现JS错误 --> < br > < tracking-mode >COOKIE</ tracking-mode > < br > </ session-config ></ span >< span style = "font-size:24px;" > < br ></ span > |
2.请求的分类
现在的项目中请求主要分为两种:一种是普通请求,即发起请求返回视图和模型;另外一种是Ajax请求,主要返回模型数据。后端进行处理时就要根据不同的请求返回不同的内容。
对于普通请求,我们直接返回JavaScript脚本,脚本内容可以是将页面跳转到登录页面。
对于Ajax请求,则需要返回非200的状态码,这样ajax请求才会进入到error回调函数中以及全局的Ajax错误回调函数AjaxError中。
3.后端处理Session超时
后端采用SpringMVC的拦截器处理,这里为什么用拦截器呢?一方面,请求URL不能限制的太死,比如/*,这样对所有的请求都进行过滤是浪费资源的。另一方面,有些URL不需要进行拦截处理,比如到登录页面的请求肯定是不能拦截,要不然会循环重定向。再一方面,我们只需要拦截控制器请求,其它请求不拦截。
下面看一下拦截器的实现:
1
|
/** <br>* Web端登录拦截器<br>* 处理请求时Session失效的问题,包含Ajax请求和普通请求<br>* @ClassName WebLoginInterceptor <br>* @author zhangshun<br>* @date 2016年10月20日 上午11:14:52<br>*/ <br> public class WebLoginInterceptor extends HandlerInterceptorAdapter{<br> /**<br> * 日志对象<br> */ <br> private Logger logger = LoggerFactory.getLogger(WebLoginInterceptor. class );<br> /**<br> * 默认注销URL<br> * 即Session超时后,发起请求到此地址,只对普通请求有效<br> */ <br> private static final String DEFAULT_LOGOUT_URL = "/web/logout" ;<br> /**<br> * 注销URL<br> */ <br> private String logoutUrl;<br> @Override <br> public boolean preHandle(HttpServletRequest request, HttpServletResponse response,<br> Object handler) throws Exception {<br> User user = SessionUtils.getUserFromRequestAcrossCas(request);<br> String uri = request.getRequestURI(); <br> if (user == null ){<br> response.setContentType( "text/html;charset=UTF-8" );<br> if (request.getHeader( "x-requested-with" ) != null <br> && request.getHeader( "x-requested-with" ).equalsIgnoreCase( "XMLHttpRequest" )){ <br> // Ajax请求, 前段根据此header进行处理<br> response.setHeader("sessionTimeout", "Session time out, you need relogin !");<br> // 返回未认证的状态码(401)<br> response.setStatus(HttpStatus.UNAUTHORIZED.value());<br> logger.debug("请求路径:" + uri + ", 请求方式 :Ajax请求, Session超时, 需要重新登录!");<br> }else{<br> // 普通请求<br> String path = request.getContextPath();<br> StringBuffer basePath = new StringBuffer()<br> .append(request.getScheme())<br> .append("://")<br> .append(request.getServerName())<br> .append(":")<br> .append(request.getServerPort())<br> .append(path)<br> .append("/");<br> StringBuffer responseStr = new StringBuffer()<br> .append("<html><header><script type=\"text/javascript\">")<br> .append("window.location.href=\"")<br> .append(basePath).append(getLogoutUrl()).append("\";")<br> .append("</script></header></html>");<br> response.getWriter().write(responseStr.toString());<br> logger.debug("请求路径:" + uri + ",请求方式 :普通请求, Session超时, 需要重新登录!");<br> }<br> return false;<br> }<br> return true;<br> }<br> public String getLogoutUrl() {<br> // 使用默认值<br> if(StringUtils.isEmpty(logoutUrl)){<br> return DEFAULT_LOGOUT_URL;<br> }<br> return logoutUrl;<br> }<br> public void setLogoutUrl(String logoutUrl) {<br> this<br>}<br> |
通过获取Session中的User对象是否存在来判断Session是否超时,如果Session超时,则根据不同的请求方式进行返回。如果是普通请求,则直接返回JavaScript脚本,该脚本可以将页面跳转到其它URL。如果是Ajax请求,则返回401状态码,并且在返回的header中加入sessionTimeout,该数据将会在前端使用。
该拦截器在SpringMVC配置文件中的配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
< span style = "font-size:14px;" > <!-- MVC拦截器 --> < mvc:interceptors > <!-- Web登录拦截器 --> < mvc:interceptor > < mvc:mapping path = "/web/**" /> < mvc:exclude-mapping path = "/web/index" /> <!-- 防止循环重定向到首页 --> < mvc:exclude-mapping path = "/web/login" /> < mvc:exclude-mapping path = "/web/logout" /> < mvc:exclude-mapping path = "/web/doLogin" /> < bean class = "com.woyi.mhub.interceptor.WebLoginInterceptor" /> </ mvc:interceptor > </ mvc:interceptors ></ span >< span style = "font-size:24px;" > </ span > |
4.前端处理Session超时
对于普通请求,后端返回的是JavaScript脚本,会立刻执行,这里前端不需要任何处理。
对于Ajax请求,后端返回401状态码,并在header中设置的sessionTimeout。这里使用jQuery的ajaxComplete回调函数处理,具体如下:
1
2
3
4
5
6
7
|
// 实现ajax请求时判断Session是否失效 $(document).ajaxComplete( function (event, response, settings) { var sessionTimeout = response.getResponseHeader( "SessionTimeout" ); if (sessionTimeout != null && typeof sessionTimeout != "undefined" && sessionTimeout.length > 0){ // 这里写Session超时后的处理方法 } }); |
好了,可以了,Session超时的用户都会得到处理。
总结
关于Javaweb项目session超时解决方案就到这里,希望对大家有所帮助。
原文链接:https://www.2cto.com/kf/201612/577978.html