Issue #4861 - increase efficiency of ServletAttributes when going async
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
9f39fd1dd1
commit
629e106045
|
@ -26,28 +26,27 @@ import org.eclipse.jetty.util.Attributes;
|
|||
|
||||
class AsyncAttributes extends Attributes.Wrapper
|
||||
{
|
||||
/**
|
||||
* Async dispatch attribute name prefix.
|
||||
*/
|
||||
public static final String __ASYNC_PREFIX = "javax.servlet.async.";
|
||||
|
||||
private String _requestURI;
|
||||
private String _contextPath;
|
||||
private String _servletPath;
|
||||
private String _pathInfo;
|
||||
private String _query;
|
||||
private String _queryString;
|
||||
|
||||
AsyncAttributes(Attributes attributes)
|
||||
public AsyncAttributes(Attributes attributes, String requestUri, String contextPath, String servletPath, String pathInfo, String queryString)
|
||||
{
|
||||
super(attributes);
|
||||
|
||||
// TODO: make fields final in jetty-10 and NOOP when one of these attributes is set.
|
||||
_requestURI = requestUri;
|
||||
_contextPath = contextPath;
|
||||
_servletPath = servletPath;
|
||||
_pathInfo = pathInfo;
|
||||
_queryString = queryString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String key)
|
||||
{
|
||||
if (!key.startsWith(__ASYNC_PREFIX))
|
||||
return super.getAttribute(key);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case AsyncContext.ASYNC_REQUEST_URI:
|
||||
|
@ -59,7 +58,7 @@ class AsyncAttributes extends Attributes.Wrapper
|
|||
case AsyncContext.ASYNC_PATH_INFO:
|
||||
return _pathInfo;
|
||||
case AsyncContext.ASYNC_QUERY_STRING:
|
||||
return _query;
|
||||
return _queryString;
|
||||
default:
|
||||
return super.getAttribute(key);
|
||||
}
|
||||
|
@ -68,13 +67,7 @@ class AsyncAttributes extends Attributes.Wrapper
|
|||
@Override
|
||||
public Set<String> getAttributeNameSet()
|
||||
{
|
||||
HashSet<String> set = new HashSet<>();
|
||||
for (String name : _attributes.getAttributeNameSet())
|
||||
{
|
||||
if (!name.startsWith(__ASYNC_PREFIX))
|
||||
set.add(name);
|
||||
}
|
||||
|
||||
Set<String> set = new HashSet<>(super.getAttributeNameSet());
|
||||
if (_requestURI != null)
|
||||
set.add(AsyncContext.ASYNC_REQUEST_URI);
|
||||
if (_contextPath != null)
|
||||
|
@ -83,18 +76,14 @@ class AsyncAttributes extends Attributes.Wrapper
|
|||
set.add(AsyncContext.ASYNC_SERVLET_PATH);
|
||||
if (_pathInfo != null)
|
||||
set.add(AsyncContext.ASYNC_PATH_INFO);
|
||||
if (_query != null)
|
||||
if (_queryString != null)
|
||||
set.add(AsyncContext.ASYNC_QUERY_STRING);
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String key, Object value)
|
||||
{
|
||||
if (!key.startsWith(__ASYNC_PREFIX))
|
||||
super.setAttribute(key, value);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case AsyncContext.ASYNC_REQUEST_URI:
|
||||
|
@ -110,10 +99,11 @@ class AsyncAttributes extends Attributes.Wrapper
|
|||
_pathInfo = (String)value;
|
||||
break;
|
||||
case AsyncContext.ASYNC_QUERY_STRING:
|
||||
_query = (String)value;
|
||||
_queryString = (String)value;
|
||||
break;
|
||||
default:
|
||||
super.setAttribute(key, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +114,21 @@ class AsyncAttributes extends Attributes.Wrapper
|
|||
_contextPath = null;
|
||||
_servletPath = null;
|
||||
_pathInfo = null;
|
||||
_query = null;
|
||||
_queryString = null;
|
||||
super.clearAttributes();
|
||||
}
|
||||
|
||||
public void applyToAttributes(Attributes attributes)
|
||||
{
|
||||
if (_requestURI != null)
|
||||
attributes.setAttribute(AsyncContext.ASYNC_REQUEST_URI, _requestURI);
|
||||
if (_contextPath != null)
|
||||
attributes.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH, _contextPath);
|
||||
if (_servletPath != null)
|
||||
attributes.setAttribute(AsyncContext.ASYNC_SERVLET_PATH, _servletPath);
|
||||
if (_pathInfo != null)
|
||||
attributes.setAttribute(AsyncContext.ASYNC_PATH_INFO, _pathInfo);
|
||||
if (_queryString != null)
|
||||
attributes.setAttribute(AsyncContext.ASYNC_QUERY_STRING, _queryString);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.eclipse.jetty.server;
|
|||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.AsyncEvent;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
@ -32,7 +31,7 @@ public class AsyncContextEvent extends AsyncEvent implements Runnable
|
|||
{
|
||||
private final Context _context;
|
||||
private final AsyncContextState _asyncContext;
|
||||
private volatile HttpChannelState _state;
|
||||
private final HttpChannelState _state;
|
||||
private ServletContext _dispatchContext;
|
||||
private String _dispatchPath;
|
||||
private volatile Scheduler.Task _timeoutTask;
|
||||
|
@ -45,31 +44,9 @@ public class AsyncContextEvent extends AsyncEvent implements Runnable
|
|||
_asyncContext = asyncContext;
|
||||
_state = state;
|
||||
|
||||
// If we haven't been async dispatched before
|
||||
if (baseRequest.getAttribute(AsyncContext.ASYNC_REQUEST_URI) == null)
|
||||
{
|
||||
// We are setting these attributes during startAsync, when the spec implies that
|
||||
// they are only available after a call to AsyncContext.dispatch(...);
|
||||
|
||||
// have we been forwarded before?
|
||||
String uri = (String)baseRequest.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
|
||||
if (uri != null)
|
||||
{
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_REQUEST_URI, uri);
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH, baseRequest.getAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH));
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_SERVLET_PATH, baseRequest.getAttribute(RequestDispatcher.FORWARD_SERVLET_PATH));
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_PATH_INFO, baseRequest.getAttribute(RequestDispatcher.FORWARD_PATH_INFO));
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_QUERY_STRING, baseRequest.getAttribute(RequestDispatcher.FORWARD_QUERY_STRING));
|
||||
}
|
||||
else
|
||||
{
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_REQUEST_URI, baseRequest.getRequestURI());
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH, baseRequest.getContextPath());
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_SERVLET_PATH, baseRequest.getServletPath());
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_PATH_INFO, baseRequest.getPathInfo());
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_QUERY_STRING, baseRequest.getQueryString());
|
||||
}
|
||||
}
|
||||
// We are setting these attributes during startAsync, when the spec implies that
|
||||
// they are only available after a call to AsyncContext.dispatch(...);
|
||||
baseRequest.setAsyncAttributes();
|
||||
}
|
||||
|
||||
public ServletContext getSuspendedContext()
|
||||
|
|
|
@ -39,7 +39,6 @@ import java.util.EventListener;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.servlet.AsyncContext;
|
||||
|
@ -200,7 +199,7 @@ public class Request implements HttpServletRequest
|
|||
private boolean _handled = false;
|
||||
private boolean _contentParamsExtracted;
|
||||
private boolean _requestedSessionIdFromCookie = false;
|
||||
private Attributes _attributes = new ServletAttributes();
|
||||
private Attributes _attributes;
|
||||
private Authentication _authentication;
|
||||
private String _contentType;
|
||||
private String _characterEncoding;
|
||||
|
@ -627,7 +626,7 @@ public class Request implements HttpServletRequest
|
|||
_channel.getHttpTransport() instanceof HttpConnection)
|
||||
return _channel.getHttpTransport();
|
||||
}
|
||||
return _attributes.getAttribute(name);
|
||||
return (_attributes == null) ? null : _attributes.getAttribute(name);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -636,11 +635,16 @@ public class Request implements HttpServletRequest
|
|||
@Override
|
||||
public Enumeration<String> getAttributeNames()
|
||||
{
|
||||
if (_attributes == null)
|
||||
return Collections.enumeration(Collections.emptyList());
|
||||
|
||||
return AttributesMap.getAttributeNamesCopy(_attributes);
|
||||
}
|
||||
|
||||
public Attributes getAttributes()
|
||||
{
|
||||
if (_attributes == null)
|
||||
_attributes = new ServletAttributes();
|
||||
return _attributes;
|
||||
}
|
||||
|
||||
|
@ -1904,7 +1908,7 @@ public class Request implements HttpServletRequest
|
|||
@Override
|
||||
public void removeAttribute(String name)
|
||||
{
|
||||
Object oldValue = _attributes.getAttribute(name);
|
||||
Object oldValue = _attributes == null ? null : _attributes.getAttribute(name);
|
||||
|
||||
if (_attributes != null)
|
||||
_attributes.removeAttribute(name);
|
||||
|
@ -1938,13 +1942,15 @@ public class Request implements HttpServletRequest
|
|||
@Override
|
||||
public void setAttribute(String name, Object value)
|
||||
{
|
||||
Object oldValue = _attributes.getAttribute(name);
|
||||
Object oldValue = _attributes == null ? null : _attributes.getAttribute(name);
|
||||
|
||||
if ("org.eclipse.jetty.server.Request.queryEncoding".equals(name))
|
||||
setQueryEncoding(value == null ? null : value.toString());
|
||||
else if ("org.eclipse.jetty.server.sendContent".equals(name))
|
||||
LOG.warn("Deprecated: org.eclipse.jetty.server.sendContent");
|
||||
|
||||
if (_attributes == null)
|
||||
_attributes = new ServletAttributes();
|
||||
_attributes.setAttribute(name, value);
|
||||
|
||||
if (!_requestAttributeListeners.isEmpty())
|
||||
|
@ -1964,7 +1970,47 @@ public class Request implements HttpServletRequest
|
|||
|
||||
public void setAttributes(Attributes attributes)
|
||||
{
|
||||
_attributes = Objects.requireNonNull(attributes);
|
||||
_attributes = attributes;
|
||||
}
|
||||
|
||||
public void setAsyncAttributes()
|
||||
{
|
||||
// Return if we have been async dispatched before.
|
||||
if (getAttribute(AsyncContext.ASYNC_REQUEST_URI) != null)
|
||||
return;
|
||||
|
||||
// Unwrap the _attributes to get the base attributes instance.
|
||||
Attributes baseAttributes;
|
||||
if (_attributes == null)
|
||||
_attributes = baseAttributes = new ServletAttributes();
|
||||
else
|
||||
baseAttributes = Attributes.unwrap(_attributes);
|
||||
|
||||
AsyncAttributes asyncAttributes;
|
||||
// Have we been forwarded before?
|
||||
String uri = (String)getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
|
||||
if (uri != null)
|
||||
{
|
||||
String contextPath = (String)getAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH);
|
||||
String servletPath = (String)getAttribute(RequestDispatcher.FORWARD_SERVLET_PATH);
|
||||
String pathInfo = (String)getAttribute(RequestDispatcher.FORWARD_PATH_INFO);
|
||||
String queryString = (String)getAttribute(RequestDispatcher.FORWARD_QUERY_STRING);
|
||||
asyncAttributes = new AsyncAttributes(baseAttributes, uri, contextPath, servletPath, pathInfo, queryString);
|
||||
}
|
||||
else
|
||||
{
|
||||
String requestURI = getRequestURI();
|
||||
String contextPath = getContextPath();
|
||||
String servletPath = getServletPath();
|
||||
String pathInfo = getPathInfo();
|
||||
String queryString = getQueryString();
|
||||
asyncAttributes = new AsyncAttributes(baseAttributes, requestURI, contextPath, servletPath, pathInfo, queryString);
|
||||
}
|
||||
|
||||
if (baseAttributes instanceof ServletAttributes)
|
||||
((ServletAttributes)_attributes).setAsyncAttributes(asyncAttributes);
|
||||
else
|
||||
asyncAttributes.applyToAttributes(_attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,40 +25,59 @@ import org.eclipse.jetty.util.AttributesMap;
|
|||
|
||||
public class ServletAttributes implements Attributes
|
||||
{
|
||||
private final Attributes _attributes;
|
||||
private final Attributes _attributes = new AttributesMap();
|
||||
private AsyncAttributes _asyncAttributes;
|
||||
|
||||
public ServletAttributes()
|
||||
public void setAsyncAttributes(AsyncAttributes attributes)
|
||||
{
|
||||
_attributes = new AsyncAttributes(new AttributesMap());
|
||||
_asyncAttributes = attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name)
|
||||
{
|
||||
_attributes.removeAttribute(name);
|
||||
if (_asyncAttributes == null)
|
||||
_attributes.removeAttribute(name);
|
||||
else
|
||||
_asyncAttributes.removeAttribute(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, Object attribute)
|
||||
{
|
||||
_attributes.setAttribute(name, attribute);
|
||||
if (_asyncAttributes == null)
|
||||
_attributes.setAttribute(name, attribute);
|
||||
else
|
||||
_asyncAttributes.setAttribute(name, attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name)
|
||||
{
|
||||
return _attributes.getAttribute(name);
|
||||
if (_asyncAttributes == null)
|
||||
return _attributes.getAttribute(name);
|
||||
else
|
||||
return _asyncAttributes.getAttribute(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAttributeNameSet()
|
||||
{
|
||||
return _attributes.getAttributeNameSet();
|
||||
if (_asyncAttributes == null)
|
||||
return _attributes.getAttributeNameSet();
|
||||
else
|
||||
return _asyncAttributes.getAttributeNameSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAttributes()
|
||||
{
|
||||
_attributes.clearAttributes();
|
||||
if (_asyncAttributes == null)
|
||||
_attributes.clearAttributes();
|
||||
else
|
||||
{
|
||||
_asyncAttributes.clearAttributes();
|
||||
_asyncAttributes = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue