http接口取参方式 - getInputStream() 和 getReader()

承接上一篇,这篇来看 getInputStream() 和 getReader() 源码分析  

直接在 org.apache.catalina.connector.RequestFacade 中找到 getInputStream() 和 getReader()


	@Override
    public ServletInputStream getInputStream() throws IOException {

        if (request == null) {
            throw new IllegalStateException(
                            sm.getString("requestFacade.nullRequest"));
        }

        return request.getInputStream();
    }
	
	@Override
    public BufferedReader getReader() throws IOException {

        if (request == null) {
            throw new IllegalStateException(
                            sm.getString("requestFacade.nullRequest"));
        }

        return request.getReader();
    }

这里的 request 是 org.apache.catalina.connector.Request,直接来看看其中的getInputStream() 和 getReader()方法。

   /**
     * @return the servlet input stream for this Request.  The default
     * implementation returns a servlet input stream created by
     * <code>createInputStream()</code>.
     *
     * @exception IllegalStateException if <code>getReader()</code> has
     *  already been called for this request
     * @exception IOException if an input/output error occurs
     */
    @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;

    }
	
	
	
	/**
     * Read the Reader wrapping the input stream for this Request.  The
     * default implementation wraps a <code>BufferedReader</code> around the
     * servlet input stream returned by <code>createInputStream()</code>.
     *
     * @return a buffered reader for the request
     * @exception IllegalStateException if <code>getInputStream()</code>
     *  has already been called for this request
     * @exception IOException if an input/output error occurs
     */
    @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;

    }

    
其中 这两个方法利用 usingInputStream 和 usingReader 互斥
这里可以看到 关键缓冲区 inputBuffer   (接收到的请求内容)

   /**
     * The associated input buffer.
     */
    protected final InputBuffer inputBuffer = new InputBuffer();

在 org.apache.catalina.connector.Request 中还有一个setCoyoteRequest方法

    /**
     * Coyote request.
     */
    protected org.apache.coyote.Request coyoteRequest;

    /**
     * Set the Coyote request.
     *
     * @param coyoteRequest The Coyote request
     */
    public void setCoyoteRequest(org.apache.coyote.Request coyoteRequest) {
        this.coyoteRequest = coyoteRequest;
        inputBuffer.setRequest(coyoteRequest);
    }

在这个方法中 inputBuffer    set了一个org.apache.coyote.Request   , 这里说明请求信息实际上是从org.apache.coyote.Request中拿到的,那么问题来了, org.apache.coyote.Request 是有谁创建的呢?

我们直接找到 tomcat-coyote.jar包 下的 org.apache.coyote.http11.Http11Processor类其中有一个核心构造方法 Http11Processor

public Http11Processor(int maxHttpHeaderSize, boolean allowHostHeaderMismatch,
            boolean rejectIllegalHeaderName, AbstractEndpoint<?> endpoint, int maxTrailerSize,
            Set<String> allowedTrailerHeaders, int maxExtensionSize, int maxSwallowSize,
            Map<String,UpgradeProtocol> httpUpgradeProtocols, boolean sendReasonPhrase,
            String relaxedPathChars, String relaxedQueryChars) {

        super(endpoint);

        httpParser = new HttpParser(relaxedPathChars, relaxedQueryChars);

        inputBuffer = new Http11InputBuffer(request, maxHttpHeaderSize, rejectIllegalHeaderName, httpParser);
        request.setInputBuffer(inputBuffer);

        outputBuffer = new Http11OutputBuffer(response, maxHttpHeaderSize, sendReasonPhrase);
        response.setOutputBuffer(outputBuffer);

        // Create and add the identity filters.
        inputBuffer.addFilter(new IdentityInputFilter(maxSwallowSize));
        outputBuffer.addFilter(new IdentityOutputFilter());

        // Create and add the chunked filters.
        inputBuffer.addFilter(new ChunkedInputFilter(maxTrailerSize, allowedTrailerHeaders,
                maxExtensionSize, maxSwallowSize));
        outputBuffer.addFilter(new ChunkedOutputFilter());

        // Create and add the void filters.
        inputBuffer.addFilter(new VoidInputFilter());
        outputBuffer.addFilter(new VoidOutputFilter());

        // Create and add buffered input filter
        inputBuffer.addFilter(new BufferedInputFilter());

        // Create and add the chunked filters.
        //inputBuffer.addFilter(new GzipInputFilter());
        outputBuffer.addFilter(new GzipOutputFilter());

        pluggableFilterIndex = inputBuffer.getFilters().length;

        this.httpUpgradeProtocols = httpUpgradeProtocols;
        this.allowHostHeaderMismatch = allowHostHeaderMismatch;
    }

这里通过调用其继承抽象类 AbstractProcessor  super(endpoint) 明确的创建一个请求和一个响应,且分别注入 inputBuffer 和 outputBuffer 请求信息(这个信息是socket注入的信息)。不过

这里的请求和响应并不是 org.apache.catalina.connector.RequestFacade 中使用的是 org.apache.catalina.connector.Request 和 org.apache.catalina.connector.Response 类型,而是 org.apache.coyote.Request 和 org.apache.coyote.Response

 那org.apache.catalina.connector.Request 和 org.apache.catalina.connector.Response 有是有谁创建,并且又是由谁做了setCoyoteRequest()动作呢?

我们找到 org.apache.catalina.connector.Connector 类 其中的 createRequest() 和 createResponse() 方法

   /**
     * Create (or allocate) and return a Request object suitable for
     * specifying the contents of a Request to the responsible Container.
     *
     * @return a new Servlet request object
     */
    public Request createRequest() {

        Request request = new Request();
        request.setConnector(this);
        return (request);

    }


    /**
     * Create (or allocate) and return a Response object suitable for
     * receiving the contents of a Response from the responsible Container.
     *
     * @return a new Servlet response object
     */
    public Response createResponse() {

        Response response = new Response();
        response.setConnector(this);
        return (response);

    }


这里面都做了setConnector(this)操作,关联此connector,下面来看看 Connector 的构造方法

   /**
     * Coyote Protocol handler class name.
     * Defaults to the Coyote HTTP/1.1 protocolHandler.
     */
    protected String protocolHandlerClassName =
        "org.apache.coyote.http11.Http11NioProtocol";


    public Connector(String protocol) {
        setProtocol(protocol);
        // Instantiate protocol handler
        ProtocolHandler p = null;
        try {
            Class<?> clazz = Class.forName(protocolHandlerClassName);
            p = (ProtocolHandler) clazz.getConstructor().newInstance();
        } catch (Exception e) {
            log.error(sm.getString(
                    "coyoteConnector.protocolHandlerInstantiationFailed"), e);
        } finally {
            this.protocolHandler = p;
        }

        if (Globals.STRICT_SERVLET_COMPLIANCE) {
            uriCharset = StandardCharsets.ISO_8859_1;
        } else {
            uriCharset = StandardCharsets.UTF_8;
        }
    }

方法中主要实例了一个 ProtocolHandler 类    ,如果没有配置的话使用的是 org.apache.coyote.http11.Http11NioProtocol,
直接去查看 org.apache.coyote.http11.Http11NioProtocol 类 其中调用父类的 getEndpoint()方法,一自往父类溯源,最后可以找到
org.apache.coyote.http11.AbstractHttp11Protocol<S> 类 其中一个核心方法 createProcessor()  中创建了 org.apache.coyote.http11.Http11Processor实例

    @SuppressWarnings("deprecation")
    @Override
    protected Processor createProcessor() {
        Http11Processor processor = new Http11Processor(getMaxHttpHeaderSize(),
                getAllowHostHeaderMismatch(), getRejectIllegalHeaderName(), getEndpoint(),
                getMaxTrailerSize(), allowedTrailerHeaders, getMaxExtensionSize(),
                getMaxSwallowSize(), httpUpgradeProtocols, getSendReasonPhrase(),
                relaxedPathChars, relaxedQueryChars);
        processor.setAdapter(getAdapter());
        processor.setMaxKeepAliveRequests(getMaxKeepAliveRequests());
        processor.setConnectionUploadTimeout(getConnectionUploadTimeout());
        processor.setDisableUploadTimeout(getDisableUploadTimeout());
        processor.setCompressionMinSize(getCompressionMinSize());
        processor.setCompression(getCompression());
        processor.setNoCompressionUserAgents(getNoCompressionUserAgents());
        processor.setCompressibleMimeTypes(getCompressibleMimeTypes());
        processor.setRestrictedUserAgents(getRestrictedUserAgents());
        processor.setMaxSavePostSize(getMaxSavePostSize());
        processor.setServer(getServer());
        processor.setServerRemoveAppProvidedValues(getServerRemoveAppProvidedValues());
        return processor;
    }

 现在有了 Http11Processor  也就有了 org.apache.coyote.Request 和 org.apache.coyote.Response 方法。

现在我们需要找到是谁调用了 org.apache.catalina.connector.Request  setCoyoteRequest方法呢,将 org.apache.coyote.Request 转化为 org.apache.catalina.connector.Request?

直接去看 org.apache.catalina.connector.CoyoteAdapter 的 service()方法

    @Override
    public void service(org.apache.coyote.Request req, org.apache.coyote.Response res)
            throws Exception {

        Request request = (Request) req.getNote(ADAPTER_NOTES);
        Response response = (Response) res.getNote(ADAPTER_NOTES);

        if (request == null) {
            // Create objects
            request = connector.createRequest();  // 创建org.apache.catalina.connector.Request
            request.setCoyoteRequest(req);        //  转化
            response = connector.createResponse(); // 创建org.apache.catalina.connector.Response
            response.setCoyoteResponse(res);       //转化

            // Link objects
            request.setResponse(response);
            response.setRequest(request);

            // Set as notes
            req.setNote(ADAPTER_NOTES, request);
            res.setNote(ADAPTER_NOTES, response);

            // Set query string encoding
            req.getParameters().setQueryStringCharset(connector.getURICharset());
        }
		
		// ....  省略 ....
		
    }		

这这个方法里进行了转化调用。

通过 tomcat的源码,我们可以总结出:

     Tomcat 创建Connector连接器时,实例化了 ProtocolHandler类 (Tomcat协议接口),Connector使用ProtocolHandler来处理请求  。ProtocolHandler包含了三个部件:Endpoint、Processor、Adapter。 

  • Endpoint是通信端点,即通信监听的接口,是具体的Socket接收处理类,是对传输层的抽象 获取 scoket流
  • Processor是协议处理接口,负责构造Request和Response对象(这里是指org.apache.coyote.Request 和 org.apache.coyote.Response),并通过Adapter将其提交到Catalina容器处理,是对应用层协议的抽象。
  • Adapter是适配器,将Processor构造的Request对象转换为ServletRequest交给Container进行具体的处理。(转化)
发布了73 篇原创文章 · 获赞 78 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/SHIYUN123zw/article/details/89712069
今日推荐