diff --git a/dubbo-rpc/dubbo-rpc-http/pom.xml b/dubbo-rpc/dubbo-rpc-http/pom.xml index dc7518cf36657c6aa31567ad75226b0a1e77c0ab..69f377bdd8558ecdf6786197940046237131f30a 100644 --- a/dubbo-rpc/dubbo-rpc-http/pom.xml +++ b/dubbo-rpc/dubbo-rpc-http/pom.xml @@ -34,11 +34,14 @@ dubbo-rpc-api ${project.parent.version} + + com.alibaba + dubbo-remoting-http + ${project.parent.version} + org.springframework spring - provided - true \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpProtocol.java b/dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpProtocol.java new file mode 100644 index 0000000000000000000000000000000000000000..59cb0a3f279109a813cb28b887c9cfb92db15b7c --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpProtocol.java @@ -0,0 +1,137 @@ +/* + * Copyright 1999-2012 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 pehttpssions and + * limitations under the License. + */ +package com.alibaba.dubbo.rpc.protocol.http; + +import java.io.IOException; +import java.net.SocketTimeoutException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.remoting.RemoteAccessException; +import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean; +import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter; + +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.RpcContext; +import com.alibaba.dubbo.rpc.RpcException; +import com.alibaba.dubbo.rpc.protocol.AbstractProxyProtocol; + +/** + * HttpProtocol + * + * @author william.liangf + */ +public class HttpProtocol extends AbstractProxyProtocol { + + public static final int DEFAULT_PORT = 80; + + private final Map serverMap = new ConcurrentHashMap(); + + private final Map skeletonMap = new ConcurrentHashMap(); + + private HttpBinder httpBinder; + + public HttpProtocol() { + super(IOException.class); + } + + public void setHttpBinder(HttpBinder httpBinder) { + this.httpBinder = httpBinder; + } + + public int getDefaultPort() { + return DEFAULT_PORT; + } + + private class InternalHandler implements HttpHandler { + + public void handle(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + String uri = request.getRequestURI(); + HttpInvokerServiceExporter skeleton = skeletonMap.get(uri); + if (! request.getMethod().equalsIgnoreCase("POST")) { + response.setStatus(500); + } else { + RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort()); + try { + skeleton.handleRequest(request, response); + } catch (Throwable e) { + throw new ServletException(e); + } + } + } + + } + + protected Runnable doExport(final T impl, Class type, URL url) throws RpcException { + String addr = url.getIp() + ":" + url.getPort(); + HttpServer server = serverMap.get(addr); + if (server == null) { + server = httpBinder.bind(url, new InternalHandler()); + serverMap.put(addr, server); + } + final HttpInvokerServiceExporter httpServiceExporter = new HttpInvokerServiceExporter(); + httpServiceExporter.setServiceInterface(type); + httpServiceExporter.setService(impl); + try { + httpServiceExporter.afterPropertiesSet(); + } catch (Exception e) { + throw new RpcException(e.getMessage(), e); + } + final String path = url.getAbsolutePath(); + skeletonMap.put(path, httpServiceExporter); + return new Runnable() { + public void run() { + skeletonMap.remove(path); + } + }; + } + + @SuppressWarnings("unchecked") + protected T doRefer(final Class serviceType, final URL url) throws RpcException { + final HttpInvokerProxyFactoryBean httpProxyFactoryBean = new HttpInvokerProxyFactoryBean(); + httpProxyFactoryBean.setServiceUrl(url.toIdentityString()); + httpProxyFactoryBean.setServiceInterface(serviceType); + httpProxyFactoryBean.afterPropertiesSet(); + return (T) httpProxyFactoryBean.getObject(); + } + + protected int getErrorCode(Throwable e) { + if (e instanceof RemoteAccessException) { + e = e.getCause(); + } + if (e != null && e.getCause() != null) { + Class cls = e.getCause().getClass(); + // 是根据测试Case发现的问题,对RpcException.setCode进行设置 + if (SocketTimeoutException.class.equals(cls)) { + return RpcException.TIMEOUT_EXCEPTION; + } else if (IOException.class.isAssignableFrom(cls)) { + return RpcException.NETWORK_EXCEPTION; + } else if (ClassNotFoundException.class.isAssignableFrom(cls)) { + return RpcException.SERIALIZATION_EXCEPTION; + } + } + return super.getErrorCode(e); + } + +} \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-http/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Protocol b/dubbo-rpc/dubbo-rpc-http/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Protocol new file mode 100644 index 0000000000000000000000000000000000000000..4f8e312f9faad943470b295a18607eb95d445db1 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-http/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Protocol @@ -0,0 +1 @@ +com.alibaba.dubbo.rpc.protocol.http.HttpProtocol \ No newline at end of file