org/apache/tomcat/embed/tomcat-embed-core/8.0.33/tomcat-embed-core-8.0.33-sources.jar!/org/apache/catalina/core/ApplicationDispatcher.javajava
private void doDispatch(ServletRequest request, ServletResponse response) throws ServletException, IOException private void doForward(ServletRequest request, ServletResponse response) throws ServletException, IOException private void doInclude(ServletRequest request, ServletResponse response) throws ServletException, IOException
这里看doDispatchapache
private void doDispatch(ServletRequest request, ServletResponse response) throws ServletException, IOException { // Set up to handle the specified request and response State state = new State(request, response, false); // Create a wrapped response to use for this request wrapResponse(state); ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest(state); if (queryString != null) { wrequest.setQueryParams(queryString); } wrequest.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ASYNC); wrequest.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, getCombinedPath()); wrequest.setContextPath(context.getPath()); wrequest.setRequestURI(requestURI); wrequest.setServletPath(servletPath); wrequest.setPathInfo(pathInfo); if (queryString != null) { wrequest.setQueryString(queryString); wrequest.setQueryParams(queryString); } invoke(state.outerRequest, state.outerResponse, state); }
ApplicationDispatcher.doDispatch-->ApplicationHttpRequest.setQueryString -->ApplicationHttpRequest.parseParameters -->mergeParameterstomcat
private void mergeParameters() { if ((queryParamString == null) || (queryParamString.length() < 1)) return; // Parse the query string from the dispatch target Parameters paramParser = new Parameters(); MessageBytes queryMB = MessageBytes.newInstance(); queryMB.setString(queryParamString); String encoding = getCharacterEncoding(); // No need to process null value, as ISO-8859-1 is the default encoding // in MessageBytes.toBytes(). if (encoding != null) { try { queryMB.setCharset(B2CConverter.getCharset(encoding)); } catch (UnsupportedEncodingException ignored) { // Fall-back to ISO-8859-1 } } paramParser.setQuery(queryMB); paramParser.setQueryStringEncoding(encoding); paramParser.handleQueryParameters(); // Insert the additional parameters from the dispatch target Enumeration<String> dispParamNames = paramParser.getParameterNames(); while (dispParamNames.hasMoreElements()) { String dispParamName = dispParamNames.nextElement(); String[] dispParamValues = paramParser.getParameterValues(dispParamName); String[] originalValues = parameters.get(dispParamName); if (originalValues == null) { parameters.put(dispParamName, dispParamValues); continue; } parameters.put(dispParamName, mergeValues(dispParamValues, originalValues)); } }
org/apache/tomcat/embed/tomcat-embed-core/8.0.33/tomcat-embed-core-8.0.33-sources.jar!/org/apache/catalina/connector/Request.java多线程
/** * Parse request parameters. */ protected void parseParameters() { parametersParsed = true; Parameters parameters = coyoteRequest.getParameters(); boolean success = false; try { // Set this every time in case limit has been changed via JMX parameters.setLimit(getConnector().getMaxParameterCount()); // getCharacterEncoding() may have been overridden to search for // hidden form field containing request encoding String enc = getCharacterEncoding(); boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI(); if (enc != null) { parameters.setEncoding(enc); if (useBodyEncodingForURI) { parameters.setQueryStringEncoding(enc); } } else { parameters.setEncoding (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING); if (useBodyEncodingForURI) { parameters.setQueryStringEncoding (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING); } } parameters.handleQueryParameters(); if (usingInputStream || usingReader) { success = true; return; } if( !getConnector().isParseBodyMethod(getMethod()) ) { success = true; return; } String contentType = getContentType(); if (contentType == null) { contentType = ""; } int semicolon = contentType.indexOf(';'); if (semicolon >= 0) { contentType = contentType.substring(0, semicolon).trim(); } else { contentType = contentType.trim(); } if ("multipart/form-data".equals(contentType)) { parseParts(false); success = true; return; } if (!("application/x-www-form-urlencoded".equals(contentType))) { success = true; return; } int len = getContentLength(); if (len > 0) { int maxPostSize = connector.getMaxPostSize(); if ((maxPostSize >= 0) && (len > maxPostSize)) { Context context = getContext(); if (context != null && context.getLogger().isDebugEnabled()) { context.getLogger().debug( sm.getString("coyoteRequest.postTooLarge")); } checkSwallowInput(); parameters.setParseFailedReason(FailReason.POST_TOO_LARGE); return; } byte[] formData = null; if (len < CACHED_POST_LEN) { if (postData == null) { postData = new byte[CACHED_POST_LEN]; } formData = postData; } else { formData = new byte[len]; } try { if (readPostBody(formData, len) != len) { parameters.setParseFailedReason(FailReason.REQUEST_BODY_INCOMPLETE); return; } } catch (IOException e) { // Client disconnect Context context = getContext(); if (context != null && context.getLogger().isDebugEnabled()) { context.getLogger().debug( sm.getString("coyoteRequest.parseParameters"), e); } parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT); return; } parameters.processParameters(formData, 0, len); } else if ("chunked".equalsIgnoreCase( coyoteRequest.getHeader("transfer-encoding"))) { byte[] formData = null; try { formData = readChunkedPostBody(); } catch (IllegalStateException ise) { // chunkedPostTooLarge error parameters.setParseFailedReason(FailReason.POST_TOO_LARGE); Context context = getContext(); if (context != null && context.getLogger().isDebugEnabled()) { context.getLogger().debug( sm.getString("coyoteRequest.parseParameters"), ise); } return; } catch (IOException e) { // Client disconnect parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT); Context context = getContext(); if (context != null && context.getLogger().isDebugEnabled()) { context.getLogger().debug( sm.getString("coyoteRequest.parseParameters"), e); } return; } if (formData != null) { parameters.processParameters(formData, 0, formData.length); } } success = true; } finally { if (!success) { parameters.setParseFailedReason(FailReason.UNKNOWN); } } }
/** * Read post body in an array. */ protected int readPostBody(byte body[], int len) throws IOException { int offset = 0; do { int inputLen = getStream().read(body, offset, len - offset); if (inputLen <= 0) { return offset; } offset += inputLen; } while ((len - offset) > 0); return len; }
/** * Read chunked post body. */ protected byte[] readChunkedPostBody() throws IOException { ByteChunk body = new ByteChunk(); byte[] buffer = new byte[CACHED_POST_LEN]; int len = 0; while (len > -1) { len = getStream().read(buffer, 0, CACHED_POST_LEN); if (connector.getMaxPostSize() >= 0 && (body.getLength() + len) > connector.getMaxPostSize()) { // Too much data checkSwallowInput(); throw new IllegalStateException( sm.getString("coyoteRequest.chunkedPostTooLarge")); } if (len > 0) { body.append(buffer, 0, len); } } if (body.getLength() == 0) { return null; } if (body.getLength() < body.getBuffer().length) { int length = body.getLength(); byte[] result = new byte[length]; System.arraycopy(body.getBuffer(), 0, result, 0, length); return result; } return body.getBuffer(); }
-->addParameterapp
public void addParameter( String key, String value ) throws IllegalStateException { if( key==null ) { return; } parameterCount ++; if (limit > -1 && parameterCount > limit) { // Processing this parameter will push us over the limit. ISE is // what Request.parseParts() uses for requests that are too big setParseFailedReason(FailReason.TOO_MANY_PARAMETERS); throw new IllegalStateException(sm.getString( "parameters.maxCountFail", Integer.valueOf(limit))); } ArrayList<String> values = paramHashValues.get(key); if (values == null) { values = new ArrayList<>(1); paramHashValues.put(key, values); } values.add(value); }
而后再这里调用ide
public Enumeration<String> getParameterNames() { handleQueryParameters(); return Collections.enumeration(paramHashValues.keySet()); }
而Request的getParameterNames则委托Parameters的getParameterNamespost
public Enumeration<String> getParameterNames() { if (!parametersParsed) { parseParameters(); } return coyoteRequest.getParameters().getParameterNames(); }
最后,有个统一的merge过程,见上头的mergeParameters。this
@Override public BufferedReader getReader() throws IOException { if (usingInputStream) { throw new IllegalStateException (sm.getString("coyoteRequest.getReader.ise")); } usingReader = true; inputBuffer.checkConverter(); if (reader == null) { reader = new CoyoteReader(inputBuffer); } return reader; }
@Override public ServletInputStream getInputStream() throws IOException { if (usingReader) { throw new IllegalStateException (sm.getString("coyoteRequest.getInputStream.ise")); } usingInputStream = true; if (inputStream == null) { inputStream = new CoyoteInputStream(inputBuffer); } return inputStream; }
Servlet Request的 getInputStream() getReader() getParameter(),在读取post方法的参数时,使用了任意一个,再调用其余两个方法是读取不到参数的。getParameter单线程上可重复使用,多线程的话可能会有异常,由于该方法依赖parametersParsed,这个boolean的参数不是原子的。url