Dubbo融合Web Service教程

Web Service是一种传统的远程过程调用方式,它通过XML来定义服务信息和传输数据。Dubbo是一种分布式服务治理框架,它提供了服务注册与发现,负载均衡,远程调用等。Dubbo在进行服务调用时,默认使用Dubbo 自定义的协议,但也支持各种第三方协议,如rest,grpc,web service等。
Dubbo提供了对Web Service的整合能力,主要是指可以将Web Service包装成Dubbo服务,因此提供了服务注册与发现,同时在提供者端可以让开发者像发布Dubbo服务那样,很简便地发布Web Service服务,在消费者端则可以像调用Dubbo服务那样,调用Web Service服务。

定义服务接口

public interface DemoService {
    String hello(String word);
}

提供者整合

因为Web Service需要使用HTTP协议,所以提供者必须使用Web容器(不管是外置的还是嵌入式的)

Web容器配置

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <display-name>dubbo-webservicedisplay-name>

    <welcome-file-list>
        <welcome-file>index.jspwelcome-file>
    welcome-file-list>

    <context-param>
        <param-name>contextConfigLocationparam-name>
        <param-value>classpath:spring/*.xmlparam-value>
    context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
    listener>

    <servlet>
        <servlet-name>dubboservlet-name>
        <servlet-class>org.apache.dubbo.remoting.http.servlet.DispatcherServletservlet-class>
        <load-on-startup>1load-on-startup>
    servlet>
    <servlet-mapping>
        <servlet-name>dubboservlet-name>
        <url-pattern>/services/*url-pattern>
    servlet-mapping>

web-app>

这里配置跟使用Spring MVC的配置比较类似,只是把DispatcherServlet替换为Dubbo自己的实现,用来分发请求。
这个servlet的url-pattern需要注意,所有Web Service的请求都会跟在这个pattern后面。

提供者的整合有两种方式,第一种是将Protocol的server设置为servlet,第二种是设置为jetty。

servlet方式

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                        http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">



    <dubbo:application name="dubbo-webservice-app" />

    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <dubbo:protocol name="webservice" port="8083" server="servlet" contextpath="dubbo_samples_webservice_provider_war/services"
                    service-path-prefix="dubbo_samples_webservice_provider_war/services"/>

    <dubbo:service interface="org.apache.dubbo.samples.webservice.DemoService" ref="demoService" />

    <bean id="demoService" class="org.apache.dubbo.samples.webservice.provider.impl.DemoServiceImpl" />
beans>

配置和普通的Dubbo应用差不多,只是protocol的类型指定为webservice,同时指定了port,因为使用servlet来分发请求,所以port必须和容器对外的端口相同。这里的contextpath不是容器的contextpath,而是Dubbo定义的web service的contextPath。service-path-prefix则是容器的contextPath加上DispatchServlet的url-pattern,因为容器的contextPath和servlet的url-pattern消费者无法自动获取到,但是访问的时候必须在端口后面跟上,所以这里需要配置,这样消费者可以从这个属性拿到。比如,如果使用Tomcat,应用的目录是dubbo_samples_webservice_provider_war,那容器的contextPath就是dubbo_samples_webservice_provider_war。

jetty方式

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                        http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">



    <dubbo:application name="dubbo-webservice-app" />

    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <dubbo:protocol name="webservice" port="8084" server="jetty" contextpath="dubbo_samples_webservice_provider_war/services"/>

    <dubbo:service interface="org.apache.dubbo.samples.webservice.DemoService" ref="demoService" />

    <bean id="demoService" class="org.apache.dubbo.samples.webservice.provider.impl.DemoServiceImpl" />
beans>

注意这里jetty和Servlet的区别在于,这里的jetty是嵌入式的,相当于单独起了一个Web容器,所以这里的端口必须和外层的容器的端口不一样,否则会端口冲突。同时jetty设置service-path-prefix是没有意义的,原因大家可以想一下。

实现接口

import org.apache.dubbo.samples.webservice.DemoService;

public class DemoServiceImpl implements DemoService {
    @Override
    public String hello(String word) {
        return "Time: " + System.currentTimeMillis() + ", word: " + word;
    }
}

启动外层容器,如果成功,可以在浏览器中查看wsdl文件。

这个图是servlet方式。

消费者融合

消费者比较简单,首先配置spring应用上下文

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <dubbo:application name="demo-consumer"/>

    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.samples.webservice.DemoService"/>
beans>

消费者代码

public class Application {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-samples-webservice-consumer.xml");
        context.start();
        DemoService demoService = context.getBean("demoService", DemoService.class);
        String result = demoService.hello("world");
        System.out.println("输出: " + result);

    }
}

调用结果截图
在这里插入图片描述

注意

目前service-path-prefix还没有正式合并到dubbo中,只是提交了PR。所以,目前如果使用servlet,而且容器的contextPath或者DispatcherServlet的url-pattern不为空的话,在Dubbo中使用Web Service是会失败的。

后续会把本文中的代码贡献给dubbo-samples项目。

你可能感兴趣的:(技术,Dubbo,微服务)