From 4990572d2179410ff01e17962f7a636deaca79f7 Mon Sep 17 00:00:00 2001 From: "william.liangf" Date: Wed, 2 Nov 2011 08:45:17 +0000 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9HttpServer=E6=89=A9=E5=B1=95?= =?UTF-8?q?=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://code.alibabatech.com/svn/dubbo/trunk@174 1a56cb94-b969-4eaa-88fa-be21384802f2 --- dubbo-remoting-http/pom.xml | 2 +- .../dubbo/remoting/http/HttpBinder.java | 40 ++++++++ .../{HttpProcessor.java => HttpHandler.java} | 8 +- .../dubbo/remoting/http/HttpServer.java | 56 +++++++++-- .../dubbo/remoting/http/JettyHttpServer.java | 92 ------------------- .../remoting/http/jetty/JettyHttpBinder.java | 36 ++++++++ .../remoting/http/jetty/JettyHttpServer.java | 88 ++++++++++++++++++ .../DispatcherServlet.java} | 52 ++++------- .../http/servlet/ServletHttpBinder.java | 38 ++++++++ .../http/{ => servlet}/ServletHttpServer.java | 27 ++---- .../http/support/AbstractHttpServer.java | 79 ++++++++++++++++ ...com.alibaba.dubbo.remoting.http.HttpBinder | 2 + .../exchange/support/SimpleFuture.java | 51 ++++++++++ dubbo-rpc-hessian/pom.xml | 6 ++ .../rpc/protocol/hessian/HessianProtocol.java | 80 ++++++++-------- .../protocol/hessian/HessianRpcExporter.java | 8 +- .../protocol/hessian/HessianRpcInvoker.java | 47 +++++----- .../hessian/HttpClientConnection.java | 88 ++++++++++++++++++ .../hessian/HttpClientConnectionFactory.java | 47 ++++++++++ 19 files changed, 631 insertions(+), 216 deletions(-) create mode 100644 dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpBinder.java rename dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/{HttpProcessor.java => HttpHandler.java} (85%) delete mode 100644 dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/JettyHttpServer.java create mode 100644 dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpBinder.java create mode 100644 dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpServer.java rename dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/{ServiceDispatcherServlet.java => servlet/DispatcherServlet.java} (51%) create mode 100644 dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletHttpBinder.java rename dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/{ => servlet}/ServletHttpServer.java (57%) create mode 100644 dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/support/AbstractHttpServer.java create mode 100644 dubbo-remoting-http/src/main/resources/META-INF/services/com.alibaba.dubbo.remoting.http.HttpBinder create mode 100644 dubbo-remoting/src/main/java/com/alibaba/dubbo/remoting/exchange/support/SimpleFuture.java create mode 100644 dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnection.java create mode 100644 dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnectionFactory.java diff --git a/dubbo-remoting-http/pom.xml b/dubbo-remoting-http/pom.xml index 31fceaedd9..d3a45efc8e 100644 --- a/dubbo-remoting-http/pom.xml +++ b/dubbo-remoting-http/pom.xml @@ -41,6 +41,6 @@ org.mortbay.jetty jetty - + \ No newline at end of file diff --git a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpBinder.java b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpBinder.java new file mode 100644 index 0000000000..a7356bbb5c --- /dev/null +++ b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpBinder.java @@ -0,0 +1,40 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.dubbo.remoting.http; + +import com.alibaba.dubbo.common.Adaptive; +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.Extension; +import com.alibaba.dubbo.common.URL; + +/** + * HttpBinder + * + * @author william.liangf + */ +@Extension("jetty") +public interface HttpBinder { + + /** + * bind the server. + * + * @param url server url. + * @return server. + */ + @Adaptive({Constants.SERVER_KEY}) + HttpServer bind(URL url, HttpHandler handler); + +} \ No newline at end of file diff --git a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpProcessor.java b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpHandler.java similarity index 85% rename from dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpProcessor.java rename to dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpHandler.java index 4c9fd30cd7..6550a3b966 100644 --- a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpProcessor.java +++ b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpHandler.java @@ -26,8 +26,8 @@ import javax.servlet.http.HttpServletResponse; * * @author william.liangf */ -public interface HttpProcessor { - +public interface HttpHandler { + /** * invoke. * @@ -36,6 +36,6 @@ public interface HttpProcessor { * @throws IOException * @throws ServletException */ - public abstract void invoke(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; - + void handle(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; + } \ No newline at end of file diff --git a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpServer.java b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpServer.java index ae4826fb5b..37b9ae2782 100644 --- a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpServer.java +++ b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpServer.java @@ -15,12 +15,56 @@ */ package com.alibaba.dubbo.remoting.http; -public interface HttpServer { +import java.net.InetSocketAddress; - void start(); - - void stop(); - - int getPort(); +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.remoting.Resetable; +public interface HttpServer extends Resetable { + + /** + * get http handler. + * + * @return http handler. + */ + HttpHandler getHttpHandler(); + + /** + * get url. + * + * @return url + */ + URL getUrl(); + + /** + * get local address. + * + * @return local address. + */ + InetSocketAddress getLocalAddress(); + + /** + * close the channel. + */ + void close(); + + /** + * Graceful close the channel. + */ + void close(int timeout); + + /** + * is bound. + * + * @return bound + */ + boolean isBound(); + + /** + * is closed. + * + * @return closed + */ + boolean isClosed(); + } \ No newline at end of file diff --git a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/JettyHttpServer.java b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/JettyHttpServer.java deleted file mode 100644 index 7342b8aa61..0000000000 --- a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/JettyHttpServer.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 1999-2011 Alibaba Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.alibaba.dubbo.remoting.http; - -import org.mortbay.jetty.Server; -import org.mortbay.jetty.nio.SelectChannelConnector; -import org.mortbay.jetty.servlet.ServletHandler; -import org.mortbay.jetty.servlet.ServletHolder; -import org.mortbay.thread.QueuedThreadPool; - -import com.alibaba.dubbo.common.logger.Logger; -import com.alibaba.dubbo.common.logger.LoggerFactory; -import com.alibaba.dubbo.common.utils.NetUtils; - -public class JettyHttpServer implements HttpServer { - - private static final Logger logger = LoggerFactory.getLogger(JettyHttpServer.class); - - private String host; - - private int port; - - private int threads; - - private Server server; - - public JettyHttpServer(int port, int threads) { - this.port = port; - this.threads = threads; - } - - public JettyHttpServer(String host, int port, int threads) { - this.host = host; - this.port = port; - this.threads = threads; - } - - public void start() { - QueuedThreadPool threadPool = new QueuedThreadPool(); - threadPool.setDaemon(true); - threadPool.setMaxThreads(threads); - threadPool.setMinThreads(threads); - - SelectChannelConnector connector = new SelectChannelConnector(); - if (NetUtils.isValidLocalHost(host)) { - connector.setHost(host); - } - connector.setPort(port); - - ServletHandler handler = new ServletHandler(); - ServletHolder holder = handler.addServletWithMapping(ServiceDispatcherServlet.class, "/*"); - holder.setInitOrder(1); - - server = new Server(); - server.setThreadPool(threadPool); - server.addConnector(connector); - server.addHandler(handler); - try { - server.start(); - } catch (Exception e) { - throw new IllegalStateException("Failed to start jetty server on " + host + ":" + port + ", cause: " + e.getMessage(), e); - } - } - - public void stop() { - if (server != null) { - try { - server.stop(); - } catch (Exception e) { - logger.warn(e.getMessage(), e); - } - } - } - - public int getPort() { - return port; - } - -} \ No newline at end of file diff --git a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpBinder.java b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpBinder.java new file mode 100644 index 0000000000..dc67f11b18 --- /dev/null +++ b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpBinder.java @@ -0,0 +1,36 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.dubbo.remoting.http.jetty; + +import com.alibaba.dubbo.common.Extension; +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.remoting.http.HttpHandler; +import com.alibaba.dubbo.remoting.http.HttpServer; +import com.alibaba.dubbo.remoting.http.HttpBinder; + +/** + * JettyHttpTransporter + * + * @author william.liangf + */ +@Extension("jetty") +public class JettyHttpBinder implements HttpBinder { + + public HttpServer bind(URL url, HttpHandler handler) { + return new JettyHttpServer(url, handler); + } + +} \ No newline at end of file diff --git a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpServer.java b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpServer.java new file mode 100644 index 0000000000..cb30752fff --- /dev/null +++ b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpServer.java @@ -0,0 +1,88 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.dubbo.remoting.http.jetty; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.mortbay.jetty.Server; +import org.mortbay.jetty.handler.AbstractHandler; +import org.mortbay.jetty.nio.SelectChannelConnector; +import org.mortbay.thread.QueuedThreadPool; + +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.utils.NetUtils; +import com.alibaba.dubbo.remoting.http.HttpHandler; +import com.alibaba.dubbo.remoting.http.support.AbstractHttpServer; + +public class JettyHttpServer extends AbstractHttpServer { + + private static final Logger logger = LoggerFactory.getLogger(JettyHttpServer.class); + + private Server server; + + public JettyHttpServer(URL url, final HttpHandler handler){ + super(url, handler); + + int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS); + QueuedThreadPool threadPool = new QueuedThreadPool(); + threadPool.setDaemon(true); + threadPool.setMaxThreads(threads); + threadPool.setMinThreads(threads); + + SelectChannelConnector connector = new SelectChannelConnector(); + if (NetUtils.isValidLocalHost(url.getHost())) { + connector.setHost(url.getHost()); + } + connector.setPort(url.getPort()); + + server = new Server(); + server.setThreadPool(threadPool); + server.addConnector(connector); + server.addHandler(new AbstractHandler() { + public void handle(String target, HttpServletRequest request, + HttpServletResponse response, int dispatch) throws IOException, + ServletException { + handler.handle(request, response); + } + }); + + try { + server.start(); + } catch (Exception e) { + throw new IllegalStateException("Failed to start jetty server on " + url.getAddress() + ", cause: " + + e.getMessage(), e); + } + } + + public void close() { + super.close(); + if (server != null) { + try { + server.stop(); + } catch (Exception e) { + logger.warn(e.getMessage(), e); + } + } + } + +} \ No newline at end of file diff --git a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/ServiceDispatcherServlet.java b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/DispatcherServlet.java similarity index 51% rename from dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/ServiceDispatcherServlet.java rename to dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/DispatcherServlet.java index c65c2902d8..29e7a3455a 100644 --- a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/ServiceDispatcherServlet.java +++ b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/DispatcherServlet.java @@ -13,57 +13,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.dubbo.remoting.http; +package com.alibaba.dubbo.remoting.http.servlet; -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.alibaba.dubbo.remoting.http.HttpHandler; /** * Service dispatcher Servlet. * * @author qian.lei */ -public class ServiceDispatcherServlet extends HttpServlet { +public class DispatcherServlet extends HttpServlet { private static final long serialVersionUID = 5766349180380479888L; - private static final String FORM_CONTENT_TYPE = "application/x-www-form-urlencoded"; - - private static final Map processors = new ConcurrentHashMap(); + private static final Map handlers = new ConcurrentHashMap(); - public static void addProcessor(int port, String uri, HttpProcessor processor) { - processors.put(key(port, uri), processor); + static void addHttpInvoker(int port, HttpHandler processor) { + handlers.put(port, processor); } - public static void removeProcessor(int port, String uri) { - processors.remove(key(port, uri)); - } - - private static String key(int port, String uri) { - return port + ":" + (uri.startsWith("/") ? uri : "/" + uri); + static void removeHttpInvoker(int port) { + handlers.remove(port); } protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - String uri = request.getRequestURI(); - String contentType = request.getContentType(); - if (contentType == null || FORM_CONTENT_TYPE.equalsIgnoreCase(contentType)) { - int i = uri.lastIndexOf('/'); - if (i >= 0) { - uri = uri.substring(0, i); - } - } - HttpProcessor processor = processors.get(key(request.getLocalPort(), uri)); - if( processor == null ) {// service not found. + HttpHandler handler = handlers.get(request.getLocalPort()); + if( handler == null ) {// service not found. response.sendError(HttpServletResponse.SC_NOT_FOUND, "Service not found."); } else { - processor.invoke(request, response); + handler.handle(request, response); } } diff --git a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletHttpBinder.java b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletHttpBinder.java new file mode 100644 index 0000000000..ef459ee34a --- /dev/null +++ b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletHttpBinder.java @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.dubbo.remoting.http.servlet; + +import com.alibaba.dubbo.common.Adaptive; +import com.alibaba.dubbo.common.Extension; +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.remoting.http.HttpBinder; +import com.alibaba.dubbo.remoting.http.HttpHandler; +import com.alibaba.dubbo.remoting.http.HttpServer; + +/** + * ServletHttpTransporter + * + * @author william.liangf + */ +@Extension("servlet") +public class ServletHttpBinder implements HttpBinder { + + @Adaptive() + public HttpServer bind(URL url, HttpHandler handler) { + return new ServletHttpServer(url, handler); + } + +} \ No newline at end of file diff --git a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/ServletHttpServer.java b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletHttpServer.java similarity index 57% rename from dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/ServletHttpServer.java rename to dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletHttpServer.java index 93a0b6a9e2..0b9433a85e 100644 --- a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/ServletHttpServer.java +++ b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletHttpServer.java @@ -13,24 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.dubbo.remoting.http; +package com.alibaba.dubbo.remoting.http.servlet; -public class ServletHttpServer implements HttpServer { +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.remoting.http.HttpHandler; +import com.alibaba.dubbo.remoting.http.support.AbstractHttpServer; + +public class ServletHttpServer extends AbstractHttpServer { - private final int port; - - public ServletHttpServer(int port){ - this.port = port; + public ServletHttpServer(URL url, HttpHandler handler){ + super(url, handler); + DispatcherServlet.addHttpInvoker(url.getPort(), handler); } - - public void start() { - } - - public void stop() { - } - - public int getPort() { - return port; - } - + } \ No newline at end of file diff --git a/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/support/AbstractHttpServer.java b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/support/AbstractHttpServer.java new file mode 100644 index 0000000000..49febe9b95 --- /dev/null +++ b/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/support/AbstractHttpServer.java @@ -0,0 +1,79 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.dubbo.remoting.http.support; + +import java.net.InetSocketAddress; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.remoting.http.HttpHandler; +import com.alibaba.dubbo.remoting.http.HttpServer; + +/** + * AbstractHttpServer + * + * @author william.liangf + */ +public abstract class AbstractHttpServer implements HttpServer { + + private final URL url; + + private final HttpHandler handler; + + private volatile boolean closed; + + public AbstractHttpServer(URL url, HttpHandler handler){ + if (url == null) { + throw new IllegalArgumentException("url == null"); + } + if (handler == null) { + throw new IllegalArgumentException("handler == null"); + } + this.url = url; + this.handler = handler; + } + + public HttpHandler getHttpHandler() { + return handler; + } + + public URL getUrl() { + return url; + } + + public void reset(URL url) { + } + + public boolean isBound() { + return true; + } + + public InetSocketAddress getLocalAddress() { + return url.toInetSocketAddress(); + } + + public void close() { + closed = true; + } + + public void close(int timeout) { + close(); + } + + public boolean isClosed() { + return closed; + } + +} \ No newline at end of file diff --git a/dubbo-remoting-http/src/main/resources/META-INF/services/com.alibaba.dubbo.remoting.http.HttpBinder b/dubbo-remoting-http/src/main/resources/META-INF/services/com.alibaba.dubbo.remoting.http.HttpBinder new file mode 100644 index 0000000000..46f65c42ed --- /dev/null +++ b/dubbo-remoting-http/src/main/resources/META-INF/services/com.alibaba.dubbo.remoting.http.HttpBinder @@ -0,0 +1,2 @@ +com.alibaba.dubbo.remoting.http.servlet.ServletHttpBinder +com.alibaba.dubbo.remoting.http.jetty.JettyHttpBinder \ No newline at end of file diff --git a/dubbo-remoting/src/main/java/com/alibaba/dubbo/remoting/exchange/support/SimpleFuture.java b/dubbo-remoting/src/main/java/com/alibaba/dubbo/remoting/exchange/support/SimpleFuture.java new file mode 100644 index 0000000000..c09a0f04c7 --- /dev/null +++ b/dubbo-remoting/src/main/java/com/alibaba/dubbo/remoting/exchange/support/SimpleFuture.java @@ -0,0 +1,51 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.dubbo.remoting.exchange.support; + +import com.alibaba.dubbo.remoting.RemotingException; +import com.alibaba.dubbo.remoting.exchange.ResponseCallback; +import com.alibaba.dubbo.remoting.exchange.ResponseFuture; + +/** + * SimpleFuture + * + * @author william.liangf + */ +public class SimpleFuture implements ResponseFuture { + + private final Object value; + + public SimpleFuture(Object value){ + this.value = value; + } + + public Object get() throws RemotingException { + return value; + } + + public Object get(int timeoutInMillis) throws RemotingException { + return value; + } + + public void setCallback(ResponseCallback callback) { + callback.done(value); + } + + public boolean isDone() { + return true; + } + +} \ No newline at end of file diff --git a/dubbo-rpc-hessian/pom.xml b/dubbo-rpc-hessian/pom.xml index 5ff8ae46dd..891c06128e 100644 --- a/dubbo-rpc-hessian/pom.xml +++ b/dubbo-rpc-hessian/pom.xml @@ -42,6 +42,12 @@ com.caucho hessian + + + org.apache.httpcomponents + httpclient + provided + true \ No newline at end of file diff --git a/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocol.java b/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocol.java index 41cf0d8a17..ff6e317e82 100644 --- a/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocol.java +++ b/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocol.java @@ -15,22 +15,25 @@ */ package com.alibaba.dubbo.rpc.protocol.hessian; -import java.util.ArrayList; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import com.alibaba.dubbo.common.Constants; -import com.alibaba.dubbo.common.Extension; -import com.alibaba.dubbo.common.URL; -import com.alibaba.dubbo.remoting.http.HttpServer; -import com.alibaba.dubbo.remoting.http.JettyHttpServer; -import com.alibaba.dubbo.remoting.http.ServiceDispatcherServlet; -import com.alibaba.dubbo.remoting.http.ServletHttpServer; -import com.alibaba.dubbo.rpc.Exporter; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.ProxyFactory; -import com.alibaba.dubbo.rpc.RpcException; -import com.alibaba.dubbo.rpc.protocol.AbstractProtocol; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.alibaba.dubbo.common.Extension; +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.remoting.http.HttpBinder; +import com.alibaba.dubbo.remoting.http.HttpHandler; +import com.alibaba.dubbo.remoting.http.HttpServer; +import com.alibaba.dubbo.rpc.Exporter; +import com.alibaba.dubbo.rpc.Invoker; +import com.alibaba.dubbo.rpc.ProxyFactory; +import com.alibaba.dubbo.rpc.RpcException; +import com.alibaba.dubbo.rpc.protocol.AbstractProtocol; /** * http rpc support. @@ -42,7 +45,13 @@ public class HessianProtocol extends AbstractProtocol { private final Map serverMap = new ConcurrentHashMap(); - private ProxyFactory proxyFactory; + private HttpBinder httpTransporter; + + private ProxyFactory proxyFactory; + + public void setHttpTransporter(HttpBinder httpTransporter) { + this.httpTransporter = httpTransporter; + } public void setProxyFactory(ProxyFactory proxyFactory) { this.proxyFactory = proxyFactory; @@ -50,40 +59,37 @@ public class HessianProtocol extends AbstractProtocol { public int getDefaultPort() { return 80; + } + + private class HessianHandler implements HttpHandler { + + public void handle(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + String uri = request.getRequestURI(); + HessianRpcExporter exporter = (HessianRpcExporter) exporterMap.get(uri); + exporter.handle(request, response); + } + } public Exporter export(Invoker invoker) throws RpcException { - URL url = invoker.getUrl(); - - final String uri = url.getPath(); // service uri also exporter cache key. - - int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS); + final URL url = invoker.getUrl(); + final String uri = url.getAbsolutePath(); // service uri also exporter cache key. String addr = url.getHost() + ":" + url.getPort(); HttpServer server = serverMap.get(addr); if (server == null) { - String type = url.getParameter(Constants.SERVER_KEY, "jetty"); - if ("servlet".equals(type)) { - server = new ServletHttpServer(url.getPort()); - } else if ("jetty".equals(type)) { - // 和Dubbo协议一样,总是绑定到0.0.0.0上 - server = new JettyHttpServer(url.getPort(), threads); - } else { - throw new IllegalArgumentException("Unsupported http server " + type - + ", only support servlet, jetty!"); - } - server.start(); + server = httpTransporter.bind(url, new HessianHandler()); serverMap.put(addr, server); } HessianRpcExporter exporter = new HessianRpcExporter(invoker, proxyFactory) { public void unexport() { super.unexport(); - exporterMap.remove(uri); + exporterMap.remove(uri); } }; exporterMap.put(uri, exporter); - ServiceDispatcherServlet.addProcessor(url.getPort(), uri, exporter); return exporter; } @@ -100,9 +106,9 @@ public class HessianProtocol extends AbstractProtocol { if (server != null) { try { if (logger.isInfoEnabled()) { - logger.info("Close hessian server 0.0.0.0:" + server.getPort()); + logger.info("Close hessian server " + server.getUrl()); } - server.stop(); + server.close(); } catch (Throwable t) { logger.warn(t.getMessage(), t); } diff --git a/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianRpcExporter.java b/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianRpcExporter.java index 71d7395ad6..6994d2ee06 100644 --- a/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianRpcExporter.java +++ b/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianRpcExporter.java @@ -21,7 +21,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.alibaba.dubbo.remoting.http.HttpProcessor; +import com.alibaba.dubbo.remoting.http.HttpHandler; import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.ProxyFactory; import com.alibaba.dubbo.rpc.RpcContext; @@ -33,7 +33,7 @@ import com.caucho.hessian.server.HessianSkeleton; * * @author qian.lei */ -public class HessianRpcExporter extends AbstractExporter implements HttpProcessor { +public class HessianRpcExporter extends AbstractExporter implements HttpHandler { private HessianSkeleton skeleton; @@ -42,9 +42,9 @@ public class HessianRpcExporter extends AbstractExporter implements HttpPr skeleton = new HessianSkeleton(proxyFactory.getProxy(invoker), invoker.getInterface()); } - public void invoke(HttpServletRequest request, HttpServletResponse response) + public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - if (request.getMethod().equalsIgnoreCase("POST") == false) { + if (! request.getMethod().equalsIgnoreCase("POST")) { response.setStatus(500); } else { RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), diff --git a/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianRpcInvoker.java b/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianRpcInvoker.java index 29548ad03e..d3bd05a116 100644 --- a/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianRpcInvoker.java +++ b/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianRpcInvoker.java @@ -15,17 +15,18 @@ */ package com.alibaba.dubbo.rpc.protocol.hessian; -import com.alibaba.dubbo.common.Constants; -import com.alibaba.dubbo.common.URL; -import com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.ProxyFactory; -import com.alibaba.dubbo.rpc.Result; -import com.alibaba.dubbo.rpc.RpcException; -import com.alibaba.dubbo.rpc.RpcResult; -import com.alibaba.dubbo.rpc.protocol.AbstractInvoker; -import com.caucho.hessian.HessianException; -import com.caucho.hessian.client.HessianProxyFactory; +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.rpc.Invocation; +import com.alibaba.dubbo.rpc.Invoker; +import com.alibaba.dubbo.rpc.ProxyFactory; +import com.alibaba.dubbo.rpc.Result; +import com.alibaba.dubbo.rpc.RpcException; +import com.alibaba.dubbo.rpc.RpcResult; +import com.alibaba.dubbo.rpc.protocol.AbstractInvoker; +import com.caucho.hessian.HessianException; +import com.caucho.hessian.client.HessianConnectionFactory; +import com.caucho.hessian.client.HessianProxyFactory; /** * hessian rpc invoker. @@ -36,24 +37,24 @@ public class HessianRpcInvoker extends AbstractInvoker { protected static final String HESSIAN_EXCEPTION_PREFIX = HessianException.class.getPackage().getName() + "."; //fix by tony.chenl - protected Invoker invoker; + protected Invoker invoker; + + protected HessianConnectionFactory hessianConnectionFactory = new HttpClientConnectionFactory(); @SuppressWarnings("unchecked") public HessianRpcInvoker(Class serviceType, URL url, ProxyFactory proxyFactory){ super(serviceType, url); - int timeout; - String t = url.getParameter(Constants.TIMEOUT_KEY); - if (t != null && t.length() > 0) { - timeout = Integer.parseInt(t); - } else { - timeout = Constants.DEFAULT_TIMEOUT; - } - - java.net.URL httpUrl = url.setProtocol("http").toJavaURL(); - HessianProxyFactory hessianProxyFactory = new HessianProxyFactory(); + HessianProxyFactory hessianProxyFactory = new HessianProxyFactory(); + String client = url.getParameter(Constants.CLIENT_KEY, Constants.DEFAULT_HTTP_CLIENT); + if ("httpclient".equals(client)) { + hessianProxyFactory.setConnectionFactory(hessianConnectionFactory); + } else if (client != null && client.length() > 0 && ! Constants.DEFAULT_HTTP_CLIENT.equals(client)) { + throw new IllegalStateException("Unsupported http protocol client=\"" + client + "\"!"); + } + int timeout = url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT); hessianProxyFactory.setConnectTimeout(timeout); hessianProxyFactory.setReadTimeout(timeout); - invoker = proxyFactory.getInvoker((T)hessianProxyFactory.create(serviceType, httpUrl, Thread.currentThread().getContextClassLoader()), serviceType, url); + invoker = proxyFactory.getInvoker((T)hessianProxyFactory.create(serviceType, url.setProtocol("http").toJavaURL(), Thread.currentThread().getContextClassLoader()), serviceType, url); } @Override diff --git a/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnection.java b/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnection.java new file mode 100644 index 0000000000..a0576836d2 --- /dev/null +++ b/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnection.java @@ -0,0 +1,88 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.dubbo.rpc.protocol.hessian; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.message.BasicHeader; + +import com.caucho.hessian.client.HessianConnection; + +/** + * HttpClientConnection + * + * @author william.liangf + */ +public class HttpClientConnection implements HessianConnection { + + private final HttpClient httpClient; + + private final ByteArrayOutputStream output; + + private final HttpPost request; + + private volatile HttpResponse response; + + public HttpClientConnection(HttpClient httpClient, URL url) { + this.httpClient = httpClient; + this.output = new ByteArrayOutputStream(); + this.request = new HttpPost(url.toString()); + } + + public void addHeader(String key, String value) { + request.addHeader(new BasicHeader(key, value)); + } + + public OutputStream getOutputStream() throws IOException { + return output; + } + + public void sendRequest() throws IOException { + request.setEntity(new ByteArrayEntity(output.toByteArray())); + this.response = httpClient.execute(request); + } + + public int getStatusCode() { + return response == null || response.getStatusLine() == null ? 0 : response.getStatusLine().getStatusCode(); + } + + public String getStatusMessage() { + return response == null || response.getStatusLine() == null ? null : response.getStatusLine().getReasonPhrase(); + } + + public InputStream getInputStream() throws IOException { + return response == null || response.getEntity() == null ? null : response.getEntity().getContent(); + } + + public void close() throws IOException { + HttpPost request = this.request; + if (request != null) { + request.abort(); + } + } + + public void destroy() throws IOException { + } + +} diff --git a/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnectionFactory.java b/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnectionFactory.java new file mode 100644 index 0000000000..b9f6247f15 --- /dev/null +++ b/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnectionFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright 1999-2011 Alibaba Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.dubbo.rpc.protocol.hessian; + +import java.io.IOException; +import java.net.URL; + +import org.apache.http.client.HttpClient; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.params.HttpConnectionParams; + +import com.caucho.hessian.client.HessianConnection; +import com.caucho.hessian.client.HessianConnectionFactory; +import com.caucho.hessian.client.HessianProxyFactory; + +/** + * HttpClientConnectionFactory + * + * @author william.liangf + */ +public class HttpClientConnectionFactory implements HessianConnectionFactory { + + private final HttpClient httpClient = new DefaultHttpClient(); + + public void setHessianProxyFactory(HessianProxyFactory factory) { + HttpConnectionParams.setConnectionTimeout(httpClient.getParams(), (int) factory.getConnectTimeout()); + HttpConnectionParams.setSoTimeout(httpClient.getParams(), (int) factory.getReadTimeout()); + } + + public HessianConnection open(URL url) throws IOException { + return new HttpClientConnection(httpClient, url); + } + +}