📄 requestdispatcherimpl.java
字号:
}
// Here the spec is very special, pay attention
// We need to pass the original request, with all the paths -
// and the new paths in special attributes.
// We still need to find out where do we want to go ( today )
// That means we create a subRequest with the new paths ( since
// the mapping and aliasing is done on Requests), and run it
// through prepare.
// That also means that some special cases ( like the invoker !! )
// will have to pay attention to the attributes, or we'll get a loop
Request subRequest=context.getContextManager().
createRequest( context, path );
subRequest.setParent( realRequest );
subRequest.getTop(); // control inclusion depth
// I hope no interceptor (or code) in processRequest use any
// of the original request info ( like Auth headers )
//
// XXX We need to clone the request, so that processRequest can
// make an informed mapping ( Auth, Authorization, etc)
//
// This will never work corectly unless we do a full clone - but
// for simple cases ( no auth, etc) it does
// note that we also need a dummy response - SessionInterceptors may
// change something !
subRequest.setResponse( realResponse );
context.getContextManager().processRequest(subRequest);
// Now subRequest containse the processed and aliased paths, plus
// the wrapper that will handle the request.
// We will use the stack a bit - save all path attributes, set the
// new values, and after return from wrapper revert to the original
Object old_request_uri=realRequest.
getAttribute("javax.servlet.include.request_uri");
realRequest.setAttribute("javax.servlet.include.request_uri",
// path);
context.getPath() + path );
Object old_context_path=realRequest.
getAttribute("javax.servlet.include.context_path");
realRequest.setAttribute("javax.servlet.include.context_path",
context.getPath());
// never change anyway - RD can't get out
Object old_servlet_path=realRequest.
getAttribute("javax.servlet.include.servlet_path");
realRequest.setAttribute("javax.servlet.include.servlet_path",
subRequest.getServletPath());
Object old_path_info=realRequest.
getAttribute("javax.servlet.include.path_info");
realRequest.setAttribute("javax.servlet.include.path_info",
subRequest.getPathInfo());
Object old_query_string=realRequest.
getAttribute("javax.servlet.include.query_string");
realRequest.setAttribute("javax.servlet.include.query_string",
queryString);
// Not explicitely stated, but we need to save the old parameters
// before adding the new ones
realRequest.getParameterNames();
// force reading of parameters from POST
Hashtable old_parameters=(Hashtable)realRequest.getParameters().clone();
// NOTE: it has a side effect of _reading_ the form data - which
// is against the specs ( you can't read the post until asked for
// parameters). I see no way of dealing with that -
// if we don't do it and the included request need a parameter,
// the form will be read and we'll have no way to know that.
// IMHO the spec should do something about that - or smarter
// people should implement the spec. ( costin )
addQueryString( realRequest, queryString );
Request old_child = realRequest.getChild();
realRequest.setChild( subRequest );
// now it's really strange: we call the wrapper on the subrequest
// for the realRequest ( since the real request will still have the
// original handler/wrapper )
ServletWrapper wr=subRequest.getWrapper();
Throwable t = null;
if( wr!=null ) {
try {
wr.service(realRequest, realResponse);
} catch (Throwable t1) {
t = t1;
}
}
// After request, we want to restore the include attributes - for
// chained includes.
realRequest.setChild( old_child );
realRequest.setParameters( old_parameters);
replaceAttribute( realRequest, "javax.servlet.include.request_uri",
old_request_uri);
replaceAttribute( realRequest, "javax.servlet.include.context_path",
old_context_path);
replaceAttribute( realRequest, "javax.servlet.include.servlet_path",
old_servlet_path);
replaceAttribute( realRequest, "javax.servlet.include.path_info",
old_path_info);
replaceAttribute( realRequest, "javax.servlet.include.query_string",
old_query_string);
// revert to the response behavior
if( ! old_included ) {
realResponse.setIncluded( false );
}
// Rethrow any exception thrown by the included servlet
if (t != null) {
if (t instanceof IOException)
throw (IOException) t;
else if (t instanceof ServletException)
throw (ServletException) t;
else
throw new ServletException
(sm.getString("dispatcher.includeException", t));
}
}
/** Named dispatcher include
* Separate from normal include - which is still too messy
*/
public void includeNamed(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
// We got here if name!=null, so assert it
ServletWrapper wrapper = context.getServletByName( name );
// Use the original request - as in specification !
Request realRequest = ((HttpServletRequestFacade)request).
getRealRequest();
Response realResponse = realRequest.getResponse();
// Set the "included" flag so that things like header setting in the
// included servlet will be correctly ignored
boolean old_included=realResponse.isIncluded();
if( ! old_included ) {
realResponse.setIncluded( true );
}
// Call the included servlet
Throwable t = null;
if( wrapper!=null) {
try {
wrapper.service( realRequest, realRequest.getResponse());
} catch (Throwable t1) {
t = t1;
}
}
// Clean up the request and response as needed
if( ! old_included ) {
realResponse.setIncluded( false );
}
// Rethrow any exception thrown by the included servlet
if (t != null) {
if (t instanceof IOException)
throw (IOException) t;
else if (t instanceof ServletException)
throw (ServletException) t;
else
throw new ServletException
(sm.getString("dispatcher.includeException", t));
}
}
/** Named forward
*/
public void forwardNamed(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
// We got here if name!=null, so assert it
ServletWrapper wrapper = context.getServletByName( name );
// Use the original request - as in specification !
Request realRequest = ((HttpServletRequestFacade)request).
getRealRequest();
Response realResponse = realRequest.getResponse();
// Call the forwarded-to servlet
Throwable t = null;
if( wrapper!=null) {
try {
wrapper.service( realRequest, realRequest.getResponse());
} catch (Throwable t1) {
t = t1;
}
}
// Clean up the request and response as needed
; // No action required
// Rethrow any exception thrown by the forwarded-to servlet
if (t != null) {
if (t instanceof IOException)
throw (IOException) t;
else if (t instanceof ServletException)
throw (ServletException) t;
else
throw new ServletException
(sm.getString("dispatcher.forwardException", t));
}
}
/**
* Adds a query string to the existing set of parameters.
* The additional parameters represented by the query string will be
* merged with the existing parameters.
* Used by the RequestDispatcherImpl to add query string parameters
* to the request.
*
* @param inQueryString URLEncoded parameters to add
*/
void addQueryString(Request req, String inQueryString) {
// if query string is null, do nothing
if ((inQueryString == null) || (inQueryString.trim().length() <= 0))
return;
Hashtable newParams = HttpUtils.parseQueryString(queryString);
Hashtable parameters= req.getParameters();
// add new to old ( it alters the original hashtable in request)
Enumeration e=newParams.keys();
while(e.hasMoreElements() ) {
String key=(String)e.nextElement();
Object oldValue = parameters.get(key);
Object newValue = newParams.get(key);
// The simple case -- no existing parameters with this name
if (oldValue == null) {
parameters.put( key, newValue);
continue;
}
// Construct arrays of the old and new values
String oldValues[] = null;
if (oldValue instanceof String[]) {
oldValues = (String[]) oldValue;
} else if (oldValue instanceof String) {
oldValues = new String[1];
oldValues[0] = (String) oldValue;
} else {
// Can not happen?
oldValues = new String[1];
oldValues[0] = oldValue.toString();
}
String newValues[] = null;
if (newValue instanceof String[]) {
newValues = (String[]) newValue;
} else if (newValue instanceof String) {
newValues = new String[1];
newValues[0] = (String) newValue;
} else {
// Can not happen?
newValues = new String[1];
newValues[0] = newValue.toString();
}
// Merge the two sets of values into a new array
String mergedValues[] =
new String[newValues.length + oldValues.length];
for (int i = 0; i < newValues.length; i++)
mergedValues[i] = newValues[i]; // New values first per spec
for (int i = newValues.length; i < mergedValues.length; i++)
mergedValues[i] = oldValues[i - newValues.length];
// Save the merged values list in the original request
parameters.put(key, mergedValues);
}
}
/** Restore attribute - if value is null, remove the attribute.
* X Maybe it should be the befavior of setAttribute() - it is not
* specified what to do with null.
* ( or it is - null means no value in getAttribute, so setting to
* null should mean setting to no value. ?)
*/
private void replaceAttribute( Request realRequest, String name, Object value) {
if( value == null )
realRequest.removeAttribute( name );
else
realRequest.setAttribute( name, value );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -