基于Dubbo和Zookeeper的分布式服务框架

随着项目复杂度增加,分布式服务框架成为了解决业务分离的有效方案。本文介绍了如何利用Dubbo和Zookeeper搭建这样的框架。Dubbo作为服务提供者,Zookeeper作为注册中心,帮助不同服务间的调用。通过创建多个Maven模块,分别代表dao、service、以及web层,实现了服务的拆分和独立。最后,通过运行App.java和Tomcat服务器,展示了项目的正常运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     随着现在项目越来越大,业务也越来越多,如果还像以往一样写在service层中,那么将会有很多的代码,到时候如果命名不科学,要你去修改某个业务,可想而知,很不想从这么多的业务中去查找你想要寻找的业务。因此分布式服务框架诞生了。分布式服务框架强调的是业务分离,每个业务都是一个独立的模板,彼此之间的联系并不多。在需要某个模板时,只需用Maven引入即可。
     接着我们看看什么是Dubbo和Zookeeper。Zookeeper顾名思义,动物管理员,而dubbo就相当于动物。在分布式的项目中,server和service层被拆分开来,需要在server层中调用service层的接口,但是运行在不同Tomcat下的服务无法直接互调接口。所有我们需要通过dubbo建立service这个服务,然后到zookeeper上面注册,填写对应的zookeeper服务所在的IP及端口号。当server层需要调用service接口时,需使用dubbo再来引入注册进入的dubbo服务。下面是一个小的例子演示(不过在这里由于只有一个业务,因此我们把各个层当成一个独立的业务)。
     项目整体结构如下:

在这里插入图片描述
     1、新建一个Maven工程

在这里插入图片描述
     2、建立项目完成后,右键点击项目名,选择new->module,然后选择Maven项目,项目名ssm_bean(!如果代码报红,在pom.xml导入相应的依赖)
在这里插入图片描述
com.zhongruan.dao
Role.java

package com.zhongruan.bean;

import java.io.Serializable;

public class Role implements Serializable {
    private  int id;
    private String role;
    private String roleDes;

    @Override
    public String toString() {
        return "Role{" +
                "id=" + id +
                ", role='" + role + '\'' +
                ", roleDes='" + roleDes + '\'' +
                '}';
    }

    public void setRoleDes(String roleDes) {
        this.roleDes = roleDes;
    }

    public String getRoleDes() {
        return roleDes;
    }

    public int getId() {
        return id;
    }

    public String getRole() {
        return role;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setRole(String role) {
        this.role = role;
    }

}

UserInfo.java

package com.zhongruan.bean;

import java.io.Serializable;

public class UserInfo implements Serializable {
    private  int id;
    private  String username;
    private  String password;

    public int getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

     3、完成ssm_bean模板后,继续右键点击项目名(ssm_parent),选择new->module,然后选择Maven项目,项目名ssm_dao
com.zhongruan.dao
IRoleDao.java

package com.zhongruan.dao;
import com.zhongruan.bean.Role;
import java.util.List;
public interface IRoleDao {
    public List<Role> getRoleByUserId(int id);
}

IUserInfo.java

package com.zhongruan.dao;

import com.zhongruan.bean.UserInfo;
import java.util.List;
public interface IUserInfoDao {
    public List<UserInfo> findAll();
    public UserInfo login(UserInfo userInfo);
    public void  addUser(UserInfo userInfo);
    public UserInfo selectById(int id);
    public void updateUser(UserInfo userInfo);
    public void deleteUser(int id);
    public UserInfo selectByUsername(String name);
    public  void deleteAll(List<Integer> ids);
}

然后在Resources文件夹下新建mapper文件夹。里面主要有两个文件。
RoleMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.zhongruan.dao.IRoleDao">

    <select id="getRoleByUserId" resultType="Role" parameterType="int">
        select * from role where id in (select rid from user_role where uid = #{id});
    </select>

</mapper>

UserInfoMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.zhongruan.dao.IUserInfoDao" >
    <select id="findAll" resultType="com.zhongruan.bean.UserInfo">
       select * from userinfo
   </select>
    <select id="login" resultType="com.zhongruan.bean.UserInfo"  parameterType="UserInfo">
       select * from userinfo where username =#{username}
       and password = #{password}
    </select>

    <insert id="addUser" parameterType="UserInfo">
        insert into userinfo (username,password) values (#{username},#{password})
    </insert>

    <select id="selectById" parameterType="int" resultType="UserInfo">
        select * from userinfo where id = #{id}
    </select>
    
    <update id="updateUser" parameterType="UserInfo">
        update userinfo set username = #{username} , password = #{password}
        where id = #{id}
    </update>

    <delete id="deleteUser" parameterType="int">
        delete  from userinfo where id = #{id}
    </delete>

    <select id="selectByUsername" parameterType="String" resultType="UserInfo">
        select * from userinfo where username = #{username}
    </select>

    <delete id="deleteAll" parameterType="int">
        delete  from userinfo where id in
        <foreach collection="list" item="id" open="("  close=")"  separator=",">
            #{id}
        </foreach>
    </delete>
</mapper>

     4、完成ssm_dao模板后,继续右键点击项目名(ssm_parent),选择new->module,然后选择Maven项目,项目名ssm_service
com.zhongruan.service
IUserInfoService.java

package com.zhongruan.service;
import com.zhongruan.bean.UserInfo;
import java.util.List;
public interface IUserInfoServer {
    public List<UserInfo> findAll(int page, int size);
    public boolean login(UserInfo userInfo);
    public void  addUser(UserInfo userInfo);
    public UserInfo selectById(int id);
    public void updateUser(UserInfo userInfo);
    public void deleteUser(int id);
    public void deleteAllUser(List<Integer> ids);
}

com.zhongruan.service.Impl
UserInfoServerImpl.java

package com.zhongruan.service.Impl;

import com.github.pagehelper.PageHelper;
import com.zhongruan.bean.UserInfo;
import com.zhongruan.dao.IRoleDao;
import com.zhongruan.dao.IUserInfoDao;
import com.zhongruan.service.IUserInfoServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("userInfoServer")
public class UserInfoServerImpl implements IUserInfoServer {
    @Autowired
    private  IUserInfoDao userInfoDao;

    @Autowired
    private IRoleDao roleDao;

    @Override
    public List<UserInfo> findAll(int page, int size) {
        PageHelper.startPage(page,size);
      return  userInfoDao.findAll();

    }

    @Override
    public boolean login(UserInfo userInfo) {
        if(userInfoDao.login(userInfo)==null){
            return false;
        }else{
            return true;
        }
    }

    @Override
    public void addUser(UserInfo userInfo) {
        userInfoDao.addUser(userInfo);
    }

    @Override
    public UserInfo selectById(int id) {
        return  userInfoDao.selectById(id);
    }

    @Override
    public void updateUser(UserInfo userInfo) {
        userInfoDao.updateUser(userInfo);
    }

    @Override
    public void deleteUser(int id) {
        userInfoDao.deleteUser(id);
    }

    @Override
    public void deleteAllUser(List<Integer> ids) {
      userInfoDao.deleteAll(ids);
    }

}

     5、完成ssm_service模板后,继续右键点击项目名(ssm_parent),选择new->module,然后选择Maven项目,项目名ssm_ex_service,这里面代码和ssm_service项目中 UserInfoServer(com.ex.service)代码一样。
     6、完成ssm_ex_service模板后,继续右键点击项目名(ssm_parent),选择new->module,然后选择Maven项目,项目名ssm_ex_service_impl,这里面代码和ssm_service项目中 UserInfoServerImpl(com.ex.serviceImpl)代码一样,还要加一个App.java
com.ex.serviceImpl
App.java

package com.ex.serviceImpl;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ) throws IOException {
            ClassPathXmlApplicationContext context =
                    new ClassPathXmlApplicationContext("classpath:spring-context.xml");
            context.start();
            System.in.read();
      /*  synchronized (App.class) {
            while (true) {
                try {
                    App.class.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }*/
    }
}

Resources中放入配置文件。
db.properties:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/user
jdbc.username=root
jdbc.password=xiaoming555

log4j.properties:

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

spring-context.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: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-4.2.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-4.2.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
      http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">

   <import resource="spring-dao.xml"></import>
   <import resource="spring-dubbo.xml"></import>
</beans>

spring-dao.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: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-4.2.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-4.2.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
      http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">

    <context:property-placeholder location="classpath:db.properties"/>

    <!-- 配置数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="2"/>
    </bean>

    <!-- 配置sessionFactory -->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 指定配置文件位置 -->
        <!--<property name="configLocation" value="classpath:mybatis.xml"/>-->
        <!--配置别名-->
        <property name="typeAliasesPackage" value="com.zhongruan.bean"></property>

        <!--配置加载映射文件 UserMapper.xml-->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>

    <!-- 自动生成dao,mapper-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.zhongruan.dao"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
    </bean>

    <!-- 配置事务-->
    <!-- 5.配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 6.开启事务注解-->
    <tx:annotation-driven></tx:annotation-driven>
</beans>

spring-dubbo.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-4.2.xsd
       http://code.alibabatech.com/schema/dubbo
       http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!--配置dubbo的应用名称-->
    <dubbo:application name="ssm_ex_service"/>

    <!--注册中心 192.168.1.37- 10.28.231.165-->
    <dubbo:registry protocol="zookeeper" address="192.168.11.78:2181"></dubbo:registry>

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

    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.ex.service.IUserInfoServer" ref="userService" />
    <bean id="userService" class="com.ex.serviceImpl.UserInfoServerImpl"/>
</beans>

     7、完成ssm_ex_serviceimpl模板后,继续右键点击项目名(ssm_parent),选择new->module,然后选择Maven项目,项目名ssm_ex_web(这里的Maven项目为webApp)
com.ex.controller
UserInfoController

package com.ex.controller;

import com.ex.service.IUserInfoServer;
import com.github.pagehelper.PageInfo;
import com.zhongruan.bean.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;


@Controller
@RequestMapping("user")
public class UserInfoController {

   @Autowired
   private IUserInfoServer userInfoServer;

   @RequestMapping("findAll.do")
    public ModelAndView findAll(@RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "5") int size){
        ModelAndView mv = new ModelAndView();
        List<UserInfo> userInfos =userInfoServer.findAll(page,size);
        PageInfo pageInfo = new PageInfo(userInfos);
        mv.addObject("pageInfo",pageInfo);
        mv.setViewName("user-list");
        return mv;
    }


    @RequestMapping("login.do")
    public  ModelAndView login(String username, String password, HttpServletRequest httpServletRequest) {
       ModelAndView mv = new ModelAndView();
       if(username==null){
           mv.setViewName("../login");
       }else {
           UserInfo userInfo = new UserInfo();
           userInfo.setPassword(password);
           userInfo.setUsername(username);
           if (userInfoServer.login(userInfo)) {
               mv.setViewName("main");
           } else {
               mv.setViewName("../failer");
           }
       }
        return  mv;
    }


    @RequestMapping("addUser.do")
    public  String addUser(UserInfo userInfo){
       userInfoServer.addUser(userInfo);
       return "redirect:findAll.do";
    }


    @RequestMapping("toUpdate.do")
    public ModelAndView toUpdate(int id){
       UserInfo userInfo = userInfoServer.selectById(id);
       ModelAndView mv = new ModelAndView();
       mv.addObject("userinfo",userInfo);
       mv.setViewName("user-update");
       return mv;
    }

    @RequestMapping("upDate.do")
    public  String upDate(UserInfo userInfo){
       userInfoServer.updateUser(userInfo);
       return "redirect:findAll.do";
    }


    @RequestMapping("delete.do")
    public String delete(int id){
       userInfoServer.deleteUser(id);
       return "redirect:findAll.do";
    }

    @RequestMapping("deleteAll.do")
    @ResponseBody
    public String deleteAll(String userlist){
        String[] strs = userlist.split(",");
        List<Integer> ids = new ArrayList<>();
        for (int i=0;i<strs.length;i++){
            ids.add(Integer.parseInt(strs[i]));
        }
        userInfoServer.deleteAllUser(ids);
        return "";
    }
}

Resources中的配置文件
applicatonContext.xml

<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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
    <context:component-scan base-package="com.ex"></context:component-scan>

    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
    <dubbo:application name="ssm_ex_web"/>

    <!-- 使用zookeeper注册中心暴露服务地址 -->
    <!-- 注册中心地址 -->
    <dubbo:registry protocol="zookeeper" address="192.168.11.78:2181" />

    <!-- 用户服务接口 -->
    <dubbo:reference interface="com.ex.service.IUserInfoServer" id="userInfoServer" check="false" />
</beans>

log4j.xml

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

springmvc.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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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-4.2.xsd
      http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-4.2.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
      http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">

    <!-- 1.注解扫描位置-->
    <context:component-scan base-package="com.ex.controller" />

    <!-- 2.配置映射处理和适配器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

    <!-- 3.视图的解析器-->
    <bean
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/pages/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

webApp中的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- 配置加载类路径的配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:applicationContext.xml</param-value>
    </context-param>

    <!-- 配置监听器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    <!-- 解决中文乱码过滤器 -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

     <!--
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    -->

    <!-- 前端控制器(加载classpath:spring-mvc.xml 服务器启动创建servlet) -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置初始化参数,创建完DispatcherServlet对象,加载springmvc.xml配置文件 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:springmvc.xml</param-value>
        </init-param>
        <!-- 服务器启动的时候,让DispatcherServlet对象创建 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>


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

在这里没有展示前端代码
首先我们运行App.java(在打开zookeeper的情况下)出现下面的情况就运行正确了
在这里插入图片描述
接着运行Tomcat服务器,成功跳转到首页
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值