Tomcat8.x Servlet应用 req.getParameter("username")的内部机制


        // Tomcat支持 Content-Type    multipart/form-data; boundary=---------------------------312511929827998  文件上传
        // Tomcat支持 Content-Type    application/x-www-form-urlencoded; charset=UTF-8 普通post提交
        // Tomcat不支持: Content-Type    text/html; charset=utf-8
        
        // 提交类型为"multipart/form-data"的时候,要开启<multipart-config>,否则不能使用,req.getParameter("lname");取不到任何数据
        // 当有配置<multipart-config>文件上传功能是,这个字段parts会被填充
        
        // 提交类型是multipart/form-data,并且没配置<multipart-config>,在Servlet中使用了req.getInputStream() 或者 req.getReader()可以取到数据
        // 提交类型是multipart/form-data,并且没配置<multipart-config>,在Servlet中使用了req.getParameter("lname")取不到数据
        // 提交类型是multipart/form-data,有配置<multipart-config>,在Servlet中使用了req.getParameter("lname")取得到数据,req.getInputStream() 或者 req.getReader()取不到数据
        // 提交类型是application/x-www-form-urlencoded,如果在Servlet中使用了req.getInputStream() 或者 req.getReader(),那么req.getParameter("lname")取不到数据
        // 提交类型是application/x-www-form-urlencoded,如果在Servlet中使用了req.getParameter("lname"),那么req.getInputStream() 或者 req.getReader()取不到数据


class org.apache.catalina.connector.RequestFacade{
			public String getParameter(String name) {
	            return request.getParameter(name);//!!!
		    }
		}

		class org.apache.catalina.connector.Request{
			public String getParameter(String name) { // 读取参数

		        if (!parametersParsed) {
		        	// Tomcat支持 Content-Type	multipart/form-data; boundary=---------------------------312511929827998  文件上传
		            // Tomcat支持 Content-Type	application/x-www-form-urlencoded; charset=UTF-8 普通post提交
		            // Tomcat不支持: Content-Type	text/html; charset=utf-8
		        	
		        	// 提交类型为"multipart/form-data"的时候,要开启<multipart-config>,否则不能使用,req.getParameter("lname");取不到任何数据
		        	// 当有配置<multipart-config>文件上传功能是,这个字段parts会被填充
		        	// 把值设置进入: coyoteRequest.getParameters().addParameter(name, value); 
		            parseParameters(); // 走这边,解析参数
		        }

		        return coyoteRequest.getParameters().getParameter(name);

		    }
			
			// 解析参数
			protected void parseParameters() {
				parametersParsed = true;
				Parameters parameters = coyoteRequest.getParameters();//!!!!
				parameters.setLimit(getConnector().getMaxParameterCount()); // 限制参数最多数量
				String enc = getCharacterEncoding(); // 取得编码类型 如: utf-8
				parameters.setEncoding("ISO-8859-1");
				if (useBodyEncodingForURI) {
				     parameters.setQueryStringEncoding("ISO-8859-1");
				}
				parameters.handleQueryParameters(); // 处理URL查询参数,如:a=value1&b=value2
				
				//  如果在Servlet中使用了req.getInputStream() 或者 req.getReader(),就解析不到数据了
	            if (usingInputStream || usingReader) { 
	                success = true;
	                return;
	            }

	            if( !getConnector().isParseBodyMethod(getMethod()) ) { // 本请求方式,是否需要解析body部分,默认是POST要解析body
	                success = true;
	                return;
	            }

	            // Content-Type	multipart/form-data; boundary=---------------------------312511929827998  文件上传
	            // Content-Type	application/x-www-form-urlencoded; charset=UTF-8 普通post提交
	            // 不支持: Content-Type	text/html; charset=utf-8
	            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)) { // multipart/form-data; charset=utf-8
	                parseParts(false); // !!! 解析multipart/form-data类型的各个part
	                success = true;
	                return;
	            }

	            // 不支持: Content-Type	text/html; charset=utf-8
	            if (!("application/x-www-form-urlencoded".equals(contentType))) { // 普通post提交 application/x-www-form-urlencoded; charset=utf-8
	                success = true;
	                return;
	            }

	            int len = getContentLength(); // 内容的长度
	            byte[] formData = null;
	            if (readPostBody(formData, len) != len) { // 读取body的内容,放入formData
                    parameters.setParseFailedReason(FailReason.REQUEST_BODY_INCOMPLETE);
                    return;
                }
	            // 解析body的内容  formData === "a=value1&b=value2"
                parameters.processParameters(formData, 0, len);
                success = true;
			}
			
			// 解析multipart/form-data类型的各个part
			private void parseParts(boolean explicit) {

		        // Return immediately if the parts have already been parsed
		        if (parts != null || partsParseException != null) {
		            return;
		        }

		        // org.apache.catalina.core.StandardContext
		        Context context = getContext(); 
//		        <web-app>
//			    	<servlet>
//			    		<multipart-config>
//			            <!-- 50MB max -->
//			            <max-file-size>52428800</max-file-size>
//			            <max-request-size>52428800</max-request-size>
//			            <file-size-threshold>0</file-size-threshold>
//			          </multipart-config>
//			    	</servlet>
//			    </web-app>
		        // org.apache.catalina.core.StandardWrapper.getMultipartConfigElement()
		        MultipartConfigElement mce = getWrapper().getMultipartConfigElement(); //如果有配置<multipart-config>标签,就不为null

		        if (mce == null) { // 当有配置<multipart-config>标签时,这个条件为false
		            if(context.getAllowCasualMultipartParsing()) { // false
		                mce = new MultipartConfigElement(null,
		                                                 connector.getMaxPostSize(),
		                                                 connector.getMaxPostSize(),
		                                                 connector.getMaxPostSize());
		            } else {
		                if (explicit) { // false
		                    partsParseException = new IllegalStateException(
		                            sm.getString("coyoteRequest.noMultipartConfig"));
		                    return;
		                } else { // 默认走这里
		                    parts = Collections.emptyList();
		                    return;
		                }
		            }
		        }

		        Parameters parameters = coyoteRequest.getParameters();
		        parameters.setLimit(getConnector().getMaxParameterCount()); // 最大参数数量

		        boolean success = false;
		        try {
		            File location;
		            String locationStr = mce.getLocation();
	                location = ((File) context.getServletContext().getAttribute(
		                        ServletContext.TEMPDIR)); // 使用临时目录

		            // 上传处理器
		            // Create a new file upload handler
		            DiskFileItemFactory factory = new DiskFileItemFactory();
	                factory.setRepository(location.getCanonicalFile()); // 设置文件存放位置
		            factory.setSizeThreshold(mce.getFileSizeThreshold()); // 设置请求大小阈值

		            // 文件上传
		            ServletFileUpload upload = new ServletFileUpload();
		            upload.setFileItemFactory(factory);
		            upload.setFileSizeMax(mce.getMaxFileSize());
		            upload.setSizeMax(mce.getMaxRequestSize()); // 允许的body大小

		            parts = new ArrayList<>();
	                List<FileItem> items =
	                        upload.parseRequest(new ServletRequestContext(this)); // 解析所有表单项
	                int maxPostSize = getConnector().getMaxPostSize();
	                int postSize = 0;
	                String enc = getCharacterEncoding(); // 编码类型
	                Charset charset = null;
	                if (enc != null) {
	                    try {
	                        charset = B2CConverter.getCharset(enc);
	                    } catch (UnsupportedEncodingException e) {
	                        // Ignore
	                    }
	                }
	                // item === org.apache.tomcat.util.http.fileupload.disk.DiskFileItem
	                for (FileItem item : items) { // 迭代所有表单项
	                    ApplicationPart part = new ApplicationPart(item, location);
	                    parts.add(part);
	                    if (part.getSubmittedFileName() == null) { //  不是文件上传字段
	                        String name = part.getName(); // 字段名称  如: file1 如:username
	                        String value = null;
                            String encoding = parameters.getEncoding();
                            if (encoding == null) {
                                if (enc == null) {
                                    encoding = Parameters.DEFAULT_ENCODING;
                                } else {
                                    encoding = enc;
                                }
                            }
                            value = part.getString(encoding);
	                        parameters.addParameter(name, value); // 不是文件上传字段
	                    }
	                }
	                success = true;
		    }
			// 读取body的内容,放入body	
			protected int readPostBody(byte[] body, int len)
			        throws IOException {

		        int offset = 0;
		        do {
		        	// inputStream
		            int inputLen = getStream().read(body, offset, len - offset);
		            if (inputLen <= 0) {
		                return offset;
		            }
		            offset += inputLen;
		        } while ((len - offset) > 0);
		        return len;

		    }
		}
		
		class  org.apache.tomcat.util.http.Parameters{
			public void setQuery( MessageBytes queryMB ) {
		        this.queryMB=queryMB;
		    }
			public void handleQueryParameters() {
				if( didQueryParameters ) {
		            return;
		        }
				didQueryParameters=true;
				// queryMB存放的是URL的查询参数,如:a=value1&b=value2
	        	// 设置查询字符串到decodedQuery.byteC、 decodedQuery.charC
	        	// 如:a=value1&b=value2
	            decodedQuery.duplicate( queryMB ); // 
	            processParameters( decodedQuery, queryStringEncoding ); //解析查询字符串
			}
			
			public void processParameters( MessageBytes data, String encoding ) {
		        // 取得查询字符串 如:a=value1&b=value2
		        ByteChunk bc=data.getByteChunk(); 
		        processParameters( bc.getBytes(), bc.getOffset(),
		                           bc.getLength(), getCharset(encoding));
		    }
			
			private void processParameters(byte bytes[], int start, int len,
                    Charset charset) {
					// 如:bytes == "a=value1&b=value2"
				 addParameter(name, value); // 添加参数----------
			}
			
			// 添加参数
			public void addParameter( String key, String value )
		            throws IllegalStateException {
				// 设置key,value值
			        ArrayList<String> values = paramHashValues.get(key);
			        if (values == null) {
			            values = new ArrayList<>(1);
			            paramHashValues.put(key, values);
			        }
			        values.add(value);
			 }
				
			public String getParameter(String name ) {
		        handleQueryParameters();
		        ArrayList<String> values = paramHashValues.get(name);
		        if (values != null) {
		            if(values.size() == 0) {
		                return "";
		            }
		            return values.get(0);
		        } else {
		            return null;
		        }
		    }
		}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值