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);
}
大概逻辑是:
- 通过
isPathUrl
方法判断路径是否是绝对路径,方法中就是判断一下路径中是否包含":",代码如下:
private static boolean isPathUrl(String url) {
return url.indexOf(58) == -1;
}
- 如果是绝对路径直接
response.sendRedirect(finalLocation);
- 如果不是绝对路径,会执行一个
finalLocation = response.encodeRedirectURL(finalLocation);
,出现jsessionid的关键就是这一行。
response.encodeRedirectURL的逻辑说明:
- ResponseFacade.encodeRedirectURL
- Response.encodeRedirectURL
- this.isEncodeable(this.toAbsolute(url))
- Response.encodeRedirectURL
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使用绝对路径。