struts2重定向导致url中出现;jsessionid=

本文详细解析了Struts2中redirect-action重定向配置,解释了因encodeRedirectURL导致URL出现jsessionid的原因。当Session不是从Cookie中获取且URL追踪Session未关闭时,会自动添加jsessionid。提供了两种解决方案:关闭URL追踪Session机制或使用绝对路径。深入理解Struts2重定向机制对于优化Web应用性能至关重要。
摘要由CSDN通过智能技术生成

struts2重定向配置如下:

<result name="gotoLogin" type="redirect-action">
  <param name="namespace">/sso</param>
  <param name="actionName">${actionName}</param>
</result>

跳转后路径如下:

http://test.cn/sso/Login.action;jsessionid=5420210513725201D1AC11F779E7EC8C

出现;jsessionid=的原因:
struts2的redirect实现在ServletRedirectResult类中,关键代码如下:

protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
    ActionContext ctx = invocation.getInvocationContext();
    HttpServletRequest request = (HttpServletRequest)ctx.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");
    HttpServletResponse response = (HttpServletResponse)ctx.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse");
    if (isPathUrl(finalLocation)) {
        if (!finalLocation.startsWith("/")) {
            ActionMapping mapping = this.actionMapper.getMapping(request, Dispatcher.getInstance().getConfigurationManager());
            String namespace = null;
            if (mapping != null) {
                namespace = mapping.getNamespace();
            }

            if (namespace != null && namespace.length() > 0 && !"/".equals(namespace)) {
                finalLocation = namespace + "/" + finalLocation;
            } else {
                finalLocation = "/" + finalLocation;
            }
        }

        if (this.prependServletContext && request.getContextPath() != null && request.getContextPath().length() > 0) {
            finalLocation = request.getContextPath() + finalLocation;
        }

        finalLocation = response.encodeRedirectURL(finalLocation);
    }

    if (log.isDebugEnabled()) {
        log.debug("Redirecting to finalLocation " + finalLocation);
    }

    response.sendRedirect(finalLocation);
}

大概逻辑是:

  1. 通过isPathUrl方法判断路径是否是绝对路径,方法中就是判断一下路径中是否包含":",代码如下:
private static boolean isPathUrl(String url) {
    return url.indexOf(58) == -1;
}
  1. 如果是绝对路径直接response.sendRedirect(finalLocation);
  2. 如果不是绝对路径,会执行一个finalLocation = response.encodeRedirectURL(finalLocation);,出现jsessionid的关键就是这一行。

response.encodeRedirectURL的逻辑说明:

  • ResponseFacade.encodeRedirectURL
    • Response.encodeRedirectURL
      • this.isEncodeable(this.toAbsolute(url))
protected boolean isEncodeable(final String location) {
   if (location == null) {
        return false;
    } else if (location.startsWith("#")) {
        return false;
    } else {
        final Request hreq = this.request;
        final Session session = hreq.getSessionInternal(false);
        if (session == null) {
            return false;
        } else if (hreq.isRequestedSessionIdFromCookie()) {
            return false;
        } else if (!hreq.getServletContext().getEffectiveSessionTrackingModes().contains(SessionTrackingMode.URL)) {
            return false;
        } else {
            return SecurityUtil.isPackageProtectionEnabled() ? (Boolean)AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                public Boolean run() {
                    return Response.this.doIsEncodeable(hreq, session, location);
                }
            }) : this.doIsEncodeable(hreq, session, location);
        }
    }
}

如果Session不是从Cookie中获取的,而且当前没有关闭从url中追踪sessionId机制,就会执行到最后的else中。

解决方案

方法一:
所以我们想要不执行encodeRedirectURL,我们可以手动关闭从url中追踪sessionId的机制。
在任何一个Servlet的init(ServletConfig config)方法中加下面一行代码(在Filter中加也可以,只不过多代码会多次执行):

req.getServletContext().getEffectiveSessionTrackingModes().remove(SessionTrackingMode.URL);

方法二:
传递给struts进行redirect的url使用绝对路径。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值