美文网首页
SpringBoot+zk+dubbo架构实践(五):搭建微服务

SpringBoot+zk+dubbo架构实践(五):搭建微服务

作者: IT实战联盟Lin | 来源:发表于2018-06-08 14:46 被阅读614次

    往期回顾

    SpringBoot+zk+dubbo架构实践(一):本地部署zookeeper
    SpringBoot+zk+dubbo架构实践(二):SpringBoot 集成 zookeeper
    SpringBoot+zk+dubbo架构实践(三):部署Dubbo-admin管理平台
    SpringBoot+zk+dubbo架构实践(四):sb+zk+dubbo框架搭建(内附源码Git地址)

    先给大家看一个正在开发的一款小程序微商城项目:https://100boot.cn/interface/wxshop.html (有小程序源码可以下载哦!)

    前言

    我们的sb+zk+dubbo微服务架构实践就要完结了。最后完成2件事情。
    1、Spring boot + zk + dubbo 集成 mybatis 和 swagger 
    2、实现登录用户的 增删改查业务,附带一个pagehelpe实现的分页查询功能。 
    

    目的是让大家能够快速的使用起来,直接配置一下数据源就可以用喽~~~
    我们基于 SpringBoot+zk+dubbo架构实践(四) 来完成今天内容。

    user_info 数据库表脚本

    CREATE TABLE `user_info` (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
      `user_name` varchar(30) DEFAULT NULL COMMENT '用户名',
      `password` varchar(30) DEFAULT NULL COMMENT '密码',
      `sex` varchar(2) NOT NULL COMMENT '性别(0 未知,1 男 ,2 女)',
      `content` varchar(255) DEFAULT NULL COMMENT '简介',
      `create_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
      `update_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '更新时间',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户信息表'
    

    shop-api 子项目

    pom.xml 增加pagehelpe maven配置
    <dependency>
          <groupId>com.github.pagehelper</groupId>
          <artifactId>pagehelper</artifactId>
          <version>4.1.6</version>
    </dependency>
    
    UserInfoService.java 增加用户信息接口
    package com.itunion.shop.service;
    
    import com.github.pagehelper.PageInfo;
    import com.itunion.shop.dto.UserInfoDto;
    import com.itunion.shop.dto.UserInfoReqListDto;
    
    import java.util.List;
    
    /**
     * 用户数据服务
     * Created by lin on 2018年06月07日21:12:04
     */
    public interface UserInfoService {
        /**
         * 新增用户信息
         */
        int addUserInfo(UserInfoDto record);
    
        /**
         * 查询所有用户信息
         */
        List<UserInfoDto> getUserInfoList();
    
        /**
         * 根据用户ID删除用户信息
         */
        int delUserInfoById(Integer id);
    
        /**
         * 根据用户ID修改用户信息
         */
        int modifyUserInfoById(UserInfoDto record);
    
        /**
         * 分页查询
         */
        PageInfo getUserInfoListPage(UserInfoReqListDto userInfoReqListDto);
    
    }
    
    增加UserInfoDto.java 和 UserInfoReqListDto.java
    UserInfoDto : 用户信息封装 (具体可以GitHub下载源码)
    UserInfoReqListDto : 分页数据封装(具体可以GitHub下载源码)
    

    shop-ds 子项目 主要用来接口实现和读写数据库

    pom.xml 增加maven配置
    <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.0.27</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.2</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>1.3.1</version>
            </dependency>
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper</artifactId>
                <version>4.1.6</version>
            </dependency>
    
    mybatis-config.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <settings>
            <setting name="cacheEnabled" value="true"/>
            <setting name="lazyLoadingEnabled" value="true"/>
            <setting name="aggressiveLazyLoading" value="true"/>
            <setting name="useGeneratedKeys" value="true"/>
            <setting name="defaultExecutorType" value="SIMPLE"/>
            <setting name="defaultStatementTimeout" value="600"/>
            <setting name="callSettersOnNulls" value="true"/>
        </settings>
        <plugins>
            <plugin interceptor="com.github.pagehelper.PageHelper">
                <property name="dialect" value="mysql"/>
            </plugin>
        </plugins>
        <mappers>
            <mapper resource="mappers/UserInfoMapper.xml"/>
        </mappers>
    
    </configuration>
    
    DatasourceConfig.java 链接数据源
    package com.itunion.shop.config;
    
    import com.alibaba.druid.pool.DruidDataSource;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.annotation.MapperScan;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    
    import javax.annotation.PostConstruct;
    import java.sql.DataSource;
    
    @Configuration
    @MapperScan(basePackages = "com.itunion.shop.mapper")
    public class DatasourceConfig {
        private static Logger log = LoggerFactory.getLogger(DatasourceConfig.class);
        @Value("${druid.driver}")
        private String driverClassName;
        @Value("${druid.url}")
        private String url;
        @Value("${druid.username}")
        private String username;
        @Value("${druid.password}")
        private String password;
        @Value("${druid.init-size}")
        private int initSize;
        @Value("${druid.min-idel}")
        private int minIdel;
        @Value("${druid.max-active}")
        private int maxActive;
        @Value("${druid.login.timeout.seconds}")
        private int loginTimeoutSeconds;
        @Value("${druid.query.timeout.seconds}")
        private int queryTimeoutSeconds;
    
        @Bean
        public DataSource dataSource() {
            DruidDataSource ds = new DruidDataSource();
            ds.setDriverClassName(driverClassName);
            ds.setUrl(url);
            ds.setUsername(username);
            ds.setPassword(password);
            ds.setInitialSize(initSize);
            ds.setMinIdle(minIdel);
            ds.setMaxActive(maxActive);
            ds.setLoginTimeout(loginTimeoutSeconds);
            ds.setQueryTimeout(queryTimeoutSeconds);
            return ds;
        }
    
        @Bean
        public SqlSessionFactory sqlSessionFactory() throws Exception {
            final SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
            sqlSessionFactory.setDataSource(dataSource());
            sqlSessionFactory.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
            sqlSessionFactory.setFailFast(true);
            return sqlSessionFactory.getObject();
        }
    
        public DataSourceTransactionManager dataSourceTransactionManager() {
            log.debug("> transactionManager");
            return new DataSourceTransactionManager(dataSource());
        }
    
    
        @PostConstruct
        public void postConstruct() {
            log.info("jdbc settings={}", this);
        }
    }
    
    
    UserInfo.java 、UserInfoMapper.java 和 UserInfoMapper.xml 自己生成(GitHub 源码里有)
    UserInfoMapper.xml 增加 分页查询业务
     <select id="getUserInfoList" parameterType="com.itunion.shop.dto.UserInfoReqListDto" resultType="com.itunion.shop.dto.UserInfoDto">
            select
            id, user_name as userName, password, sex, content, create_date as createDate, update_date as updateDate
            from user_info
        </select>
    
    shop-ds-rovider.xml 注册服务配置
        <dubbo:service interface="com.itunion.shop.service.UserInfoService" ref="userInfoService"/>
    
    UserInfoMapper.xml 增加 查询用户信息集合业务
     /**
         * 获取用户信息集合
         * @return
         */
        List<UserInfoDto> getUserInfoList(UserInfoReqListDto userInfoReqListDto);
    
    UserInfoServiceImpl.java 增加用户业务实现服务类
    package com.itunion.shop.service.impl;
    
    
    import com.alibaba.dubbo.common.logger.Logger;
    import com.alibaba.dubbo.common.logger.LoggerFactory;
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    import com.itunion.shop.dto.UserInfoDto;
    import com.itunion.shop.dto.UserInfoReqListDto;
    import com.itunion.shop.mapper.UserInfoMapper;
    import com.itunion.shop.model.UserInfo;
    import com.itunion.shop.service.UserInfoService;
    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    
    /**
     * 用户信息-服务提供方
     * Created by lin on 2018年06月07日21:48:13
     */
    public class UserInfoServiceImpl implements UserInfoService {
        private final static Logger LOGGER = LoggerFactory.getLogger(UserInfoServiceImpl.class);
        @Autowired
        private UserInfoMapper userInfoMapper;
    
        @Override
        public int addUserInfo(UserInfoDto record) {
            LOGGER.info("进入用户信息-服务提供方-UserInfoServiceImpl.addUserInfo[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "]");
            UserInfo userInfo = new UserInfo();
            BeanUtils.copyProperties(record, userInfo);
            userInfo.setUpdateDate(new Date());
            return userInfoMapper.insertSelective(userInfo);
        }
    
        @Override
        public List<UserInfoDto> getUserInfoList() {
            LOGGER.info("进入用户信息-服务提供方-UserInfoServiceImpl.getUserInfoList[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "]");
            return userInfoMapper.getUserInfoList(null);
        }
    
        @Override
        public int delUserInfoById(Integer id) {
            LOGGER.info("进入用户信息-服务提供方-UserInfoServiceImpl.delUserInfoById[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "]");
            return userInfoMapper.deleteByPrimaryKey(id);
        }
    
        @Override
        public int modifyUserInfoById(UserInfoDto record) {
            LOGGER.info("进入用户信息-服务提供方-UserInfoServiceImpl.modifyUserInfoById[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "]");
            UserInfo userInfo = new UserInfo();
            BeanUtils.copyProperties(record, userInfo);
            userInfo.setUpdateDate(new Date());
            return userInfoMapper.updateByPrimaryKeySelective(userInfo);
        }
    
        @Override
        public PageInfo getUserInfoListPage(UserInfoReqListDto userInfoReqListDto) {
            LOGGER.info("进入用户信息-服务提供方-UserInfoServiceImpl.getUserInfoListPage[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "]");
            PageHelper.startPage(userInfoReqListDto.getPage(), userInfoReqListDto.getSize());
            List<UserInfoDto> userInfoDtos = userInfoMapper.getUserInfoList(userInfoReqListDto);
            PageInfo<UserInfoDto> userInfoDtoPageInfo = new PageInfo<>(userInfoDtos);
            return userInfoDtoPageInfo;
        }
    }
    
    
    ShopDSApplication.java 项目启动
    package com.itunion.shop;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.ImportResource;
    
    @SpringBootApplication
    // 使用 providers.xml 配置
    @ImportResource(value = {"classpath:shop-ds-rovider.xml"})
    public class ShopDSApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ShopDSApplication.class, args);
        }
    }
    
    

    好了, shop-ds 项目配置好了,接下来开始配是 移动端子项目和PC端子项目(我们文章只配置一下移动端的 PC端自己copy)

    shop-web 子项目

    pom.xml 增加 swagger 和 pagehelper maven配置
    <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>2.7.0</version>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>2.7.0</version>
            </dependency>
    
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper</artifactId>
                <version>4.1.6</version>
            </dependency>
    
    shop-web-consumer.xml 注册服务配置
            <dubbo:reference id="userInfoService" check="false" interface="com.itunion.shop.service.UserInfoService"/>
    
    

    UserInfoController.java 移动端业务入口

    package com.itunion.shop.web.controller;
    
    import com.github.pagehelper.PageInfo;
    import com.itunion.shop.common.UniformResultTemplate;
    import com.itunion.shop.dto.UserInfoDto;
    import com.itunion.shop.dto.UserInfoReqListDto;
    import com.itunion.shop.service.UserInfoService;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiOperation;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.MediaType;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.*;
    
    import javax.servlet.http.HttpServletRequest;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    
    /**
     * 用户信息-移动端消费方
     * Created by lin on 2018年06月07日22:02:07
     */
    @Controller
    @RequestMapping("userInfo")
    @Api(description = "测试移动")
    public class UserInfoController {
        private Logger LOGGER = LoggerFactory.getLogger(UserInfoController.class);
        @Autowired
        UserInfoService userInfoService;
    
        @ApiOperation(value = "getUserInfoList", notes = "查询所有用户信息")
        @RequestMapping(value = "getUserInfoList", method = RequestMethod.GET)
        @ResponseBody
        public UniformResultTemplate<List<UserInfoDto>> getUserInfoList() {
            LOGGER.info("进入用户信息-移动端消费方-UserInfoController.getUserInfoList[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "]");
            UniformResultTemplate<List<UserInfoDto>> uniformResultTemplate = new UniformResultTemplate<>();
            uniformResultTemplate.setCode(100);
            uniformResultTemplate.setMessage("查询所有用户信息成功!");
            uniformResultTemplate.setResult(userInfoService.getUserInfoList());
            return uniformResultTemplate;
        }
    
        @ApiOperation(value = "getUserInfoListPage", notes = "查询所有用户信息-分页")
        @ApiImplicitParam(name = "userInfoReqListDto", value = "{\"page\":\"1\",\"size\":\"2\"}")
        @RequestMapping(value = "getUserInfoListPage", method = RequestMethod.POST)
        @ResponseBody
        public UniformResultTemplate<PageInfo> getUserInfoList(@RequestBody UserInfoReqListDto userInfoReqListDto) {
            LOGGER.info("进入用户信息-移动端消费方-UserInfoController.getUserInfoListPage[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "]");
            UniformResultTemplate<PageInfo> uniformResultTemplate = new UniformResultTemplate<>();
            uniformResultTemplate.setCode(100);
            uniformResultTemplate.setMessage("查询所有用户信息成功分页!");
            uniformResultTemplate.setResult(userInfoService.getUserInfoListPage(userInfoReqListDto));
            return uniformResultTemplate;
        }
    
        @ApiOperation(value = "addUserInfo", notes = "新增用户信息")
        @ApiImplicitParam(name = "userInfoDto", value = "{\"userName\":\"测试用户名\",\"password\":\"000000\",\"sex\":1,\"content\":\"这里是IT实战联哦~~~\"}")
        @RequestMapping(value="addUserInfo", method = RequestMethod.POST)
        @ResponseBody
        public UniformResultTemplate<String> addUserInfo(@RequestBody UserInfoDto userInfoDto) {
    
        LOGGER.info("进入用户信息-移动端消费方-UserInfoController.addUserInfo[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "]");
            UniformResultTemplate<String> uniformResultTemplate = new UniformResultTemplate<>();
            Integer num = userInfoService.addUserInfo(userInfoDto);
            if(num > 0){
                uniformResultTemplate.setCode(100);
                uniformResultTemplate.setMessage("新增用户信息成功!");
                uniformResultTemplate.setResult(num+"");
            }else{
                uniformResultTemplate.setCode(400);
                uniformResultTemplate.setMessage("新增用户信息失败!");
                uniformResultTemplate.setResult(num+"");
            }
            return uniformResultTemplate;
        }
    
    
        @ApiOperation(value="delUserInfoById", notes="根据用户ID删除用户信息")
        @ApiImplicitParam(name = "id", value = "4" , paramType="path" , dataType="Integer")
        @RequestMapping(value="delUserInfoById/{id}", method = RequestMethod.POST)
        @ResponseBody
        public UniformResultTemplate<String> deleteKdgVipItem(@PathVariable Integer id) {
            LOGGER.info("进入用户信息-移动端消费方-UserInfoController.delUserInfoById[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "]");
            UniformResultTemplate<String> uniformResultTemplate = new UniformResultTemplate<>();
            Integer num = userInfoService.delUserInfoById(id);
            if(num > 0){
                uniformResultTemplate.setCode(100);
                uniformResultTemplate.setMessage("根据用户ID删除用户信息成功!");
                uniformResultTemplate.setResult(num+"");
            }else{
                uniformResultTemplate.setCode(400);
                uniformResultTemplate.setMessage("根据用户ID删除用户信息失败!");
                uniformResultTemplate.setResult(num+"");
            }
            return uniformResultTemplate;
        }
    
        @ApiOperation(value = "modifyUserInfo", notes = "修改用户信息")
        @ApiImplicitParam(name = "userInfoDto", value = "{\"id\":10,\"userName\":\"测试修改用户名\",\"password\":55555,\"sex\":1,\"content\":\"这里是最新的IT实战联哦~~~\"}")
        @RequestMapping(value="modifyUserInfo", method = RequestMethod.POST, produces= MediaType.APPLICATION_JSON_UTF8_VALUE)
        @ResponseBody
        public UniformResultTemplate<String> modifyUserInfo(@RequestBody UserInfoDto userInfoDto) {
            LOGGER.info("进入用户信息-移动端消费方-UserInfoController.modifyUserInfo[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "]");
            UniformResultTemplate<String> uniformResultTemplate = new UniformResultTemplate<>();
            Integer num = userInfoService.modifyUserInfoById(userInfoDto);
            if(num > 0){
                uniformResultTemplate.setCode(100);
                uniformResultTemplate.setMessage("修改用户信息成功!");
                uniformResultTemplate.setResult(num+"");
            }else{
                uniformResultTemplate.setCode(400);
                uniformResultTemplate.setMessage("修改用户信息失败!");
                uniformResultTemplate.setResult(num+"");
            }
            return uniformResultTemplate;
        }
    }
    

    备注:工具类 可以GitHub下载源码

    Application.java 项目启动
    package com.itunion.shop;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.support.SpringBootServletInitializer;
    import org.springframework.context.annotation.ImportResource;
    
    @SpringBootApplication
    @ImportResource(value = { "classpath:shop-web-consumer.xml" })
    public class Application extends SpringBootServletInitializer {
    
        public static void main(String[] args) throws Exception {
            SpringApplication.run(Application.class, args);
        }
    }
    
    application.properties
    server.port=8081  #端口
    server.context-path=/wxShop #项目名称
    swagger.enable=true
    swagger.protocol=http
    swagger.host=127.0.0.1:8081
    

    备注:shop-pc 子项目和 shop-web 配置都是一样的,不多做介绍

    项目启动

    访问地址
    http://127.0.0.1:8081/wxShop/swagger-ui.html
    
    效果
    swagger访问.png

    可以看到我们一共写了5个业务 用户的 增、删、改、查和分页查询。

    总结

    SpringBoot+zk+dubbo架构实践 分解为5篇文章写完,为了让大家能够最快入门微服务架构 并实现编码,没有做深入的剖析, 小编将源码上传GitHub:https://github.com/yundianzixun/weixin-shop。在具体工作中还会遇到更多复杂的问题,架构师之路就是不断解决问题的,一边解决问题一边进阶。希望该实践系列能够对大家有用,谢谢支持!

    关注我们

    更多精彩内容请关注“IT实战联盟”公众号,平台会提供更多技术实践内容,也可以加入交流群和作者互撩哦~~~

    IT实战联盟.jpg

    相关文章

      网友评论

          本文标题:SpringBoot+zk+dubbo架构实践(五):搭建微服务

          本文链接:https://www.haomeiwen.com/subject/uofasftx.html