Spring+Dubbo+Zookeeper框架搭建–<三>服务注册示例

SOA

一个基本的面向服务编程(soa)的分布式项目需要provider和consumer,也就是最基本的服务提供方和服务消费方,其中provider还可以细分为Interface和IService的实现关系进一步在业务上细分服务。本实例就不细分provider了,为了方便理解仅做最基本的provider和consumer划分。

注:本实例的一切注入方式均为注解扫描注入方式。

服务提供者Provider

一个已集成spring框架的项目,项目名为Provider,项目结构图如下。
这里写图片描述

本实例中,新建的项目类型为Maven Project->maven-archetype-webapp。

Dynamic Web Module为2.5
JDK为1.7

这里写图片描述
这里写图片描述

1、Pom.xml
除了基本的springframework以外,主要需要引入以下包:
Zookeeper

<!-- zookeeper -->
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.3.6</version>
    <exclusions>
        <exclusion>
            <artifactId>netty</artifactId>
            <groupId>io.netty</groupId>
        </exclusion>
    </exclusions>
</dependency>

Dubbo

<!-- dubbo -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.5.3</version>
    <exclusions>
        <exclusion>
            <artifactId>spring</artifactId>
            <groupId>org.springframework</groupId>
        </exclusion>
        <exclusion>
            <artifactId>netty</artifactId>
            <groupId>io.netty</groupId>
        </exclusion>
    </exclusions>
</dependency>

zkClient

<!-- zkclient -->
<dependency>
    <groupId>com.github.sgroschupf</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.1</version>
    <exclusions>
        <exclusion>
            <artifactId>netty</artifactId>
            <groupId>io.netty</groupId>
        </exclusion>
    </exclusions>
</dependency>

配置pom.xml的过程中可能会遇到很多编译上的报错,多是由包与包之间的依赖关系引起,也和开发环境有关,自行百度,具体问题具体解决。搭建过程中遇到太多问题了,有空会将常见问题做一个汇总,如配置过程中遇到瓶颈问题,请在本文下方留言联系我

2、Web.xml
做最基本的spring集成配置即可,配好ContextLoaderListener和DispatcherServlet,同时建立好applicationContext.xml和dubbo-provider.xml的上下文引用即可。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.xsd">

    <!-- 配置web.xml,使其具有springmvc特性,主要配置两处,一个是ContextLoaderListener,一个是DispatcherServlet -->
    <!-- ContextLoaderListener初始化Spring上下文时需要使用到的contextConfigLocation参数 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:applicationContext.xml,classpath*:dubbo-provider.xml</param-value>
    </context-param>

    <!-- spring mvc 配置 -->
    <!-- 配置DispatcherServlet表示,该工程将采用springmvc的方式。启动时也会默认在/WEB-INF目录下查找XXX-servlet.xml作为配置文件,
        XXX就是DispatcherServlet的名字,该文件中将配置两项重要的mvc特性:HandlerMapping,负责为DispatcherServlet这个前端控制器的请求查找Controller;
        ViewResolver,负责为DispatcherServlet查找ModelAndView的视图解析器。
         此处使用指定的配置文件spring-mvc.xml -->
    <!-- 优点:支持rest风格,Url美观
           缺点:会拦截静态资源 -->
    <servlet>
        <servlet-name>contacts</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>  
            <param-name>contextConfigLocation</param-name>  
            <!--<param-value>/WEB-INF/classes/spring-mvc-servlet.xml</param-value>-->
            <param-value>classpath*:/spring-mvc.xml</param-value>
        </init-param>  
        <load-on-startup>1</load-on-startup>  
    </servlet>
    <!-- url-pattern配置为/,不带文件后缀,会造成其它静态文件(js,css等)不能访问。如配为*.do,则不影响静态文件的访问 --> 
    <servlet-mapping>
        <servlet-name>contacts</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <welcome-file-list>  
        <welcome-file>index.jsp</welcome-file>  
    </welcome-file-list>  
</web-app>

3、applicationContext.xml
这里的applicationContext.xml配置很简单,只需要一个注解扫描的配置即可。

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd 
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

    <!-- 加入spring注解扫描-->
    <context:component-scan base-package="com.lhx."/>
</beans>

扫描com.lhx.路径下的所以class文件和jar包内的文件的注解,注册到beanFactory中。
注:这里的配置与后面的UserService的注解有一些联系,暂且记住这么一回事,后面会详细说明

4、dubbo-provider.xml
具体配置如下:

<?xml version="1.0" encoding="UTF-8"?>   
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
        http://www.springframework.org/schema/beans/spring-beans.xsd   
        http://www.springframework.org/schema/context   
        http://www.springframework.org/schema/context/spring-context-3.1.xsd  
        http://code.alibabatech.com/schema/dubbo   
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd   
        ">

    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="dubbo_provider" />

    <!-- 使用zookeeper注册中心暴露服务地址 端口是zookeeper 中配置的2181 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
    <!-- <dubbo:registry address="multicast://224.5.6.7:1234" /> -->

    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />

    <!-- 使用注解方式暴露接口 -->
    <dubbo:annotation package="com.lhx.user"/>

</beans>

配置项含义如代码行注释所示。

这里的有一点要说明的是,因为之前已经提过,本实例的一切注入方式均为注解注入,所以后面再配置注解的时候要十分注意注解的引用,也就是import的包是来自于spring还是dubbo。

5、UserServiceImpl
基于第3步的铺垫,这里要着重说明一下服务的实现类。
UserServiceImpl
这里写图片描述
如上图所示
@Service的引用是来自于com.alibaba.dubbo.config.annotation.Service
@Component的引用是来自于org.springframework.stereotype.Component
这里比较有意思了,一般我们使用注解方式注入bean的话,@Service是拿来专门注入Service服务层的注解,@Component是实例化普通POJO的,可以拿来注入Controller、Service、Repository等,只有当组件不好归类的时候,我们可以使用这个注解进行标注。

为什么我们在这里注入UserServiceImpl的服务实现类的时候要用@Component,是因为@Service要留给dubbo去暴露服务,因为注解重名的原因,我们只能用@Component去作为替代。所以引用@Service这个注解时一定要注意是不是import的com.alibaba.dubbo.config.annotation.Service,否则就会出现zookeeper无法捕捉dubbo暴露的服务,从而无法在zookeeper中注册这个服务。

6、UserService
就是一个接口,注解方式暴露服务依托于接口实现类,xml方式暴露的话配置依赖会涉及到接口,但是我认为xml方式暴露服务相比于注解暴露太麻烦,在这里就不多提了。

package com.lhx.user.service;

import org.springframework.stereotype.Service;

public interface UserService {
    public String sayHello();
}

服务消费者Consumer

1、pom.xml
插件引用于Provider一致,配置dubbo/zookeeper/zkClient即可,有一点不同就是消费者Consumer需要引用服务提供者Provider的Jar包。

右键Provider项目,Run As->Maven Install可将项目编译打包,打包的格式有jar、war、rar等,供外部程序引用自然是打包成Jar包,打包格式的设置在pom.xml中定义。
这里写图片描述

2、Web.xml
同服务提供者,做最基本的spring集成配置即可,配好ContextLoaderListener和DispatcherServlet,同时建立好applicationContext.xml和dubbo-provider.xml的上下文引用即可。

3、applicationContext.xml
同服务提供者,这里的applicationContext.xml配置很简单,只需要一个注解扫描的配置即可。

4、dubbo-consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://code.alibabatech.com/schema/dubbo
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        ">


    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="dubbo_consumer" />

    <!-- 使用zookeeper注册中心暴露服务地址 端口是zookeeper 中配置的2181 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
    <!-- <dubbo:registry address="multicast://224.5.6.7:1234" /> -->

    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />

    <!-- 使用注解方式注册消费者 -->
    <dubbo:annotation package="com.lhx.user.controller"/>
</beans>

5、UserController
除了spring的注解以外,就是消费者需要注册调用的服务,用dubbo的Reference注解即可。

package com.lhx.user.controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.dubbo.config.annotation.Reference;
import com.lhx.user.service.UserService;

@Controller
public class UserController {

    @Reference
    private UserService userService;

    @RequestMapping(value="/hello", method=RequestMethod.GET)
    public @ResponseBody String hello() {  
        return userService.sayHello();
    }  

}

运行效果

值得一提的是,dubbo将服务发布在zookeeper上这一步骤是无需依托于相应的消费者是否存在的,服务可以独立存在,即使没有消费者。
所以本实例建议在编写完Provider后即可运行查看dubbo-admin的管理页面是否已经注册到了我们新加的服务,只有在服务确认发布(暴露)成功后再编写相应的消费者才是有的放夭。

1、服务者(Provider)
这里写图片描述

2、消费者(Consumer)
这里写图片描述

结语

学会搭建dubbo+zookeeper只是摸到了分布式框架的门槛,真正入门还需要学习很多其他方面的知识,诸如分布式事务、分布式缓存、负载均衡等等。
博主由于工作上的需要,也正处于这样的一个学习阶段,希望能够凭借着自己的努力把一些个人心得在这里分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章