频道栏目
首页 > 程序开发 > Web开发 > Jsp > 正文
Struts2 拦截器处理普通Http请求和Ajax请求时拦截配置
2013-11-28 10:37:29           
收藏   我要投稿
  近期发现以前的系统中存在一个如下的Bug Case:

      在Session过期时,执行页面的ajax请求时,无法正常跳转到session过期提示页面,系统直接hold在那里不动,只有点击左侧菜单时,系统才能跳转到session过期提示页面。

      经过调研,发现是拦截器的处理问题,拦截器只拦截了Http请求,而没有拦截Ajax请求,才导致出现上述Bug。

      下面是解决办法:

      首先,优化拦截器:

     

[java] 

/** 

 * 拦截器 

 * @author lyh 

 * @version 2013-11-1 

 * @see LoginFilter 

 * @since 

 */  

public class LoginFilter implements Interceptor  

{  

  

    /** 

     * 序列号 

     */  

    private static final long serialVersionUID = -4979037503367919375L;  

  

    /** 

     * 日志 

     */  

    private static final Logger LOG = Logger.getLogger(LoginFilter.class);  

  

    /** 

     * ajax session超时返回值 

     */  

    private static String AJAX_TIME_OUT = null;  

  

    /** 

     * ajax 请求无权限返回值 

     */  

    private static String AJAX_NO_LIMIT = null;  

  

    /** 

     * ajax 请求异常返回值 (在每个ajax请求中处理) 

     */  

    //private static String AJAX_EXCEPTION = null;  

  

    /** 

     * 放行url 

     */  

    private static List<String> awayUrls = null;  

  

    static  

    {  

        AJAX_TIME_OUT = "ajaxSessionTimeOut";  

        AJAX_NO_LIMIT = "ajaxNoLimit";  

        //AJAX_EXCEPTION = "ajaxException";  

  

        awayUrls = new LinkedList<String>();  

        //awayUrls.add("/login!userLogin.action");  

        //awayUrls.add("/custom!toLogin.action");  

        awayUrls.add("/equipment!upLoad.action");  

    }  

  

    @Override  

    public String intercept(ActionInvocation invocation)  

        throws Exception  

    {  

        //获取request域中信息  

        HttpServletRequest req = ServletActionContext.getRequest();  

  

        //获得当前请求url  

        String url = req.getServletPath();  

  

        //获得请求类型  

        String type = req.getHeader("X-Requested-With");  

  

        //Object object = (Object)invocation.getAction();  

  

        //如果当前url在放行url集合内 则直接放行   

        if (!awayUrls.contains(url))  

        {  

            UserInfoBean userinfo = (UserInfoBean)req.getSession().getAttribute(  

                CommonConstant.AUTH_SESSION_USER_KEY);  

  

            if (userinfo == null)  

            {  

                LOG.debug("用户登录会话已过期!");  

  

                //ajax请求 session过期时 返回字符串  

                if ("XMLHttpRequest".equalsIgnoreCase(type))  

                {  

                    PrintWriter printWriter = ServletActionContext.getResponse().getWriter();  

                    printWriter.print(AJAX_TIME_OUT);  

                    printWriter.flush();  

                    printWriter.close();  

  

                    return null;  

                }  

                //普通http请求 直接返回页面  

                else  

                {  

                    return "sessionTimeOut";  

                }  

            }  

            else  

            {  

                //鉴权结果  

                boolean authFlag = false;  

                try  

                {  

                    //执行鉴权  

                    authFlag = userManager_Service.isUrlInUserLimit(userinfo.getU_phone_num(),  

                        url);  

                }  

                catch (Exception e)  

                {  

                    LOG.error(" 鉴权出现异常!异常信息:" + e.toString() + ":" + e.getMessage());  

                }  

                //鉴权通过则放行  否则拦截  

                if (authFlag)  

                {  

                    return invocation.invoke();  

                }  

                //鉴权不通过  

                else  

                {  

                    //ajax请求 session过期时 返回字符串  

                    if ("XMLHttpRequest".equalsIgnoreCase(type))  

                    {  

                        PrintWriter printWriter = ServletActionContext.getResponse().getWriter();  

                        printWriter.print(AJAX_NO_LIMIT);  

                        printWriter.flush();  

                        printWriter.close();  

  

                        return null;  

                    }  

                    //其他Http请求 直接返回页面  

                    else  

                    {  

                        return "noLimit";  

                    }  

                }  

            }  

        }  

        else  

        {  

            return invocation.invoke();  

        }  

    }  

  

    @Override  

    public void destroy()  

    {  

        //do yourself  

    }  

  

    @Override  

    public void init()  

    {  

        //do yourself  

    }  

  

}  

 

       上述拦截器考虑了Ajax和Http两种情况,Http请求被拦截时,直接跳转到指定的全局页面,而Ajax请求被拦截时则采用Js方式提示用户。

[html] 

<package name="self-default" extends="json-default">  

          

        <interceptors>  

            <interceptor name="loginFilter" class="xx.xx.LoginFilter" />  

              

            <interceptor-stack name="mydefault">  

                <interceptor-ref name="defaultStack"/>  

                <interceptor-ref name="tokenSession">  

                    <param name="includeMethods">add*,update*,modify*,upload*</param>  

                </interceptor-ref>  

                <interceptor-ref name="loginFilter" />  

            </interceptor-stack>  

        </interceptors>  

          

        <!-- 拦截器应用到全部action -->  

        <default-interceptor-ref name="mydefault"/>  

           

        <global-results>  

            <!-- 普通http请求时  系统出现异常返回到错误页   -->  

            <result name="exception">/file/smartmanager/public/globalException.jsp</result>  

              

            <!-- 普通http请求时  无操作权限   -->  

            <result name="noLimit">/file/smartmanager/public/noLimit.jsp</result>  

              

            <!-- 普通http请求时  session过期  -->  

            <result name="sessionTimeOut">/file/smartmanager/public/sessionTimeOut.jsp</result>  

        </global-results>  

  

        <global-exception-mappings>  

            <!-- 全局异常返回exception字符串 -->  

            <exception-mapping exception="java.lang.Exception" result="exception" />  

        </global-exception-mappings>  

          

    </package>  

        下面是一个简单的Action例子:

[java]  

public class MyAction  

{  

  

    /** 

     * Http请求 

     * @return 

     * @throws Exception  

     * @see 

     */  

    public String httpReqMethod()  

        throws Exception  

    {  

        try  

        {  

            //do yourself  

        }  

        catch(Exception e)  

        {  

            //捕获异常时抛出  触发global-results中的exception 然后跳转到提示页面  

            throw e;  

        }  

          

        return "httpReqMethod";  

    }  

      

    /** 

     * Ajax请求 

     * @return 

     * @throws Exception  

     * @see 

     */  

    public String ajaxReqMethod()  

    {  

        try  

        {  

            //do yourself  

        }  

        catch(Exception e)  

        {  

            //no throw  

            //此处在捕获异常时 添加提示信息至json 方便在页面展示  

            //ajaxMap.put("success", false);  

            //ajaxMap.put("opMsg", ResultMsg.CHANGE_PWD_ERROR);  

        }  

  

        return "ajaxReqMethod";  

    }  

}  

      

       配置此Action的xml(此Action需要被拦截 故extends定义的拦截器self-default):

[html] 

<package name="willPackage" extends="self-default" namespace="/">  

    <action name="my_*" class="xx.xx.MyAction"  method="{1}">   

            <result name="httpReqMethod">/file/smartmanager/main/httpReqMethod.jsp</result>          

            <result name="ajaxReqMethod" type="json">  

            <param name="root">ajaxMap</param>  

            </result>  

    </action>  

</package>  

 

 

       全局提示页面,globalException.jsp:

[html] 

<%@ page language="java" contentType="text/html; charset=UTF-8"  

    pageEncoding="UTF-8"%>  

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">  

<html>  

<head>  

<title>xxx管理系统</title>  

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  

    <link rel="icon" href="file/img/rhy.ico" type="image/x-icon" />  

    <link rel="shortcut icon" href="file/img/rhy.ico" type="image/x-icon" />  

    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/file/css/easyui.css" ></link>  

    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/file/css/icon.css" ></link>  

    <script type="text/javascript" src="${pageContext.request.contextPath}/file/scripts/jquery-1.8.3.min.js"></script>  

    <script type="text/javascript" src="${pageContext.request.contextPath}/file/scripts/jquery.easyui.min.js"></script>  

    <script type="text/javascript" src="${pageContext.request.contextPath}/file/scripts/easyui-lang-zh_CN.js"></script>  

  

<body>  

    <script type="text/javascript">  

        $(function(){  

            $.messager.alert('操作提示','系统内部异常!请联系系统管理员!','warning');  

        });  

    </script>  

</body>  

      

      

全局ajax配置publicSetup.js:

[javascript]  

//全局ajax控制,用于session超时 无权限时 提示  

$.ajaxSetup({  

    cache: false, //close AJAX cache  

    contentType:"application/x-www-form-urlencoded;charset=utf-8",   

    complete:function(XHR,textStatus){     

        var resText = XHR.responseText;  

        if(resText=='ajaxSessionTimeOut'){     

            sessionTimeOut();  

        }  

        else if(resText=='ajaxNoLimit'){     

            noLimit();  

        }          

    }   

});  

  

function sessionTimeOut(){  

    $.messager.alert('操作提示','用户登录会话已过期,请重新登录!','warning');  

    setTimeout('window.top.location.href = "login!exit.action"', 15);  

}  

  

function noLimit(){  

    $.messager.alert('操作提示','无相应操作权限,请联系系统管理员!','warning');  

}  

 

       在ajax请求页面,引入上述的publicSetup.js,在ajax请求时会触发上述js,如果session过期则会触发全局提示。

[html]  

<%@ page contentType="text/html; charset=UTF-8" isELIgnored="false"%>  

<%@ taglib uri="/struts-tags" prefix="s"%>  

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  

<html xmlns="https://www.w3.org/1999/xhtml">  

<head>  

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>  

<title>xx管理系统</title>  

    <link rel="icon" href="${contextPath}/file/img/rhy.ico" type="image/x-icon" />  

    <link rel="shortcut icon" href="${contextPath}/file/img/rhy.ico" type="image/x-icon" />     

    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/file/css/easyui.css" ></link>     

    <script type="text/javascript" src="${pageContext.request.contextPath}/file/scripts/jquery-1.8.3.min.js"></script>    

    <script type="text/javascript" src="${pageContext.request.contextPath}/file/scripts/jquery.easyui.min.js"></script>       

    <script type="text/javascript" src="${pageContext.request.contextPath}/file/scripts/easyui-lang-zh_CN.js"></script>  

          

        <!-- 引入ajax配置 -->  

    <script type="text/javascript" src="${pageContext.request.contextPath}/file/scripts/publicSetup.js"></script>  

  

<script type="text/javascript">  

      

      

    function ajaxPost() {         

        $.post('my_ajaxReqMethod.action', params, function (data) {  

            if (data.success) {  

                  

            }  

            $.messager.alert('操作提示', data.opMsg, data.success?'info':'warning');  

        });  

    }  

      

  </script>  

</head>  

  

<body>  

      

</body>  

</html>  

 

      综上,在Http请求时,会拦截到session过期、无操作权限,然后跳转到制定的全局提示页面,全局的exception配置是通过在用户自定义action方法中抛出Exception,然后触发跳转到全局提示页面。

 

      而Ajax请求时,拦截到session过期、无操作权限时,会通过全局设置的ajax.js进行控制,如果不满足,则Alert提示语,ajax的Exception配置在ajax方法中捕获,然后拼装异常提示语至返回页面Json,在页面进行Exception提示。

     

      二者的提示区别,Http请求拦截时跳转到页面进行提示,而Ajax请求拦截时采用的是Alert提示方式(当然你可以用EasyUI、ExtJS的Alert那样更美观)。

 

点击复制链接 与好友分享!回本站首页
相关TAG标签 拦截器
上一篇:jsp根据参数默认选中radio
下一篇:Struts2中实现自定义分页标签2
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站