程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> JSP編程 >> 關於JSP >> Struts2 攔截器處理普通Http請求和Ajax請求時攔截配置

Struts2 攔截器處理普通Http請求和Ajax請求時攔截配置

編輯:關於JSP

  近期發現以前的系統中存在一個如下的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" "http://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" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">   <html xmlns="http://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那樣更美觀)。  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved