SpringCloud入门篇一

/ MybatisSpringCloudJava技术 / 没有评论 / 428浏览

alt

SpringCloud是什么?

SpringCloud是一个基于SpringBoot实现的微服务架构开发工具。 它为微服务架构中涉及的配置管理、 服务治理、 断路器、 智能路由、 微代理、 控制总线、 全局锁、 决策竞选、 分布式会话和集群状态管理等操作提供了一 种简单的开发方式。总结为以下两点:

  1. SpringCloud是分布式一站式的解决方案。
  2. SpringCloud是微服务技术的一种落地的体现和实现。

SpringCloud和SpringBoot的区别和关系?

  1. SpringBoot专注于快速方便的开发单个个体微服务。
  2. SpringCloud是关注全局的微服务协调整理治理框架以及一整套的落地解决方案,它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供:配置管理,服务发现,断路器,路由,微代理,事件总线等的集成服务。
  3. SpringBoot可以离开SpringCloud独立使用,但是SpringCloud离不开SpringBoot,属于依赖的关系。

总结:SpringBoot专注于快速,方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。

SpringCloud和Dubbo区别和对比

alt

  1. SpringCloud功能比Dubbo更加强大,涵盖面更广,并且作为Spring的拳头项目,它能够与Spring Framework,SpringBoot,Spring Data等其他Spring项目完美整合,这些对于微服务而言是至关重要的。
  2. 而使用Dubbo构建的微服务架构就像组装电脑,各环节我们的选择自由度很高,但是最终很可能因为一条内存质量不行就点不亮了,而SpringCloud就像品牌机,在Spring Source的整合下,做了大量的兼容性测试,保证了机器拥有更高的稳定性,但是如果要在使用非原装组件外的东西,就需要对其基础有足够的了解。
  3. 那么最大的区别在于:SpringCloud抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式。

Rest微服务项目实战

就简单做一个用户管理的服务吧,Consumer消费者(Client)通过REST调用Provider提供者(Server)提供的服务

创建Maven项目作为父项目

  1. POM.xml配置如下,注意父项目打包类型<packaging>pom</packaging>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zealzhangz</groupId>
    <artifactId>user-management</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>dto</module>
        <module>microservice-cloud-provider-user-8001</module>
        <module>microservice-cloud-consumer-user-8002</module>
    </modules>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.10.RELEASE</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.0.4</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.0.31</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.0</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.2.3</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <inherited>true</inherited>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

创建第一个子模块

  1. DTO数据传输对象模块,该模块定义PO VO等,POM文件如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>user-management</artifactId>
        <groupId>com.zealzhangz</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>dto</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>
  1. 该模块的目录结构如下
.
├── main
│   ├── java
│   │   └── com
│   │       └── zealzhangz
│   │           └── dto
│   │               ├── po
│   │               │   └── User.java
│   │               └── vo
│   └── resources
└── test
    └── java
  1. User.java
package com.zealzhangz.dto.po;

import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author Created by xxxx.<br/>
 * @version Version: 1.0
 */
//set设置值/get获取值注解
@Data
//无参数构造注解
@NoArgsConstructor
public class User {
    private Integer id;

    private String name;

    private Short age;

    private Byte gender;

    /**
     * 来自那个数据库,因为微服务架构可以一个服务对应一个数据库,同一个信息被存储到不同数据库。
     */
    private String dbSource;
}

创建第二个模块--用户服务提供者

主要提供用户信息的CRUD

  1. POM文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>user-management</artifactId>
        <groupId>com.zealzhangz</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>microservicecloud-provider-user-8001</artifactId>

    <dependencies>
        <!-- 引入自己定义的api通用包,可以使用User用户Entity -->
        <dependency>
            <groupId>com.zealzhangz</groupId>
            <artifactId>dto</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- actuator监控信息完善 -->
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-actuator</artifactId>
                </dependency>
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </dependency>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                </dependency>
                <dependency>
                    <groupId>com.alibaba</groupId>
                    <artifactId>druid</artifactId>
                </dependency>
                <dependency>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-core</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.mybatis.spring.boot</groupId>
                    <artifactId>mybatis-spring-boot-starter</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-jetty</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-web</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-test</artifactId>
                </dependency>
                <!-- 修改后立即生效,热部署 -->
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>springloaded</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-devtools</artifactId>
                </dependency>
    </dependencies>
</project>
  1. 代码结构
.
├── main
│   ├── java
│   │   └── com
│   │       └── zealzhangz
│   │           ├── UserProvider8001App.java
│   │           ├── controller
│   │           │   └── UserController.java
│   │           ├── dao
│   │           │   └── UserDao.java
│   │           └── service
│   │               ├── UserService.java
│   │               └── impl
│   │                   └── UserServiceImpl.java
│   └── resources
│       ├── application.yml
│       └── mybatis
│           ├── mapper
│           │   └── UserMapper.xml
│           └── mybatis.cfg.xml
└── test
    └── java
  1. 创建配置文件 主要配置服务端口,数据源,数据库连接池等信息
server:
  port: 8001
mybatis:
  config-location: classpath:mybatis/mybatis.cfg.xml        # mybatis配置文件所在路径
  type-aliases-package:
  mapper-locations:
  - classpath:mybatis/mapper/**/*.xml                       # mapper映射文件
spring:
  application:
    name: microservicecloud-user
  datasource:
    driver-class-name: org.gjt.mm.mysql.Driver              # mysql驱动包
    url: jdbc:mysql://localhost:3306/user_db                # 数据库名称
    username: root
    password: root
    druid:
      initial-size: 1                                       # 数据库连接池的最小维持连接数
      max-active: 3
      min-idle: 1                                           # 初始化连接数
      max-wait: 10
      test-while-idle: true
      validation-query: SELECT 1 FROM DUAL
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: microservicecloud-user-8001
    prefer-ip-address: true         #访问路径可以显示IP地址
    ip-address:  127.0.0.1
    metadata-map:
      fixed-s1: "value_1"
info:
  app.name: zhanga-micro-service-cloud
  company.name: www.zhangaoo.com                           #我的博客地址
  build.artifactId: @project.artifactId@
  build.version: @project.version@
  1. mybatis.cfg.xml mybatis配置文件
<?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" /><!-- 二级缓存开启 -->
    </settings>
</configuration>
  1. UserMapper对应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.zealzhangz.dao.UserDao">
    <resultMap id="user" type="com.zealzhangz.dto.po.User">
        <result column="db_source" jdbcType="VARCHAR" property="dbSource" />
    </resultMap>
    <select id="findUserByName" resultMap="user" parameterType="com.zealzhangz.dto.po.User">
        select id,name,age,gender,db_source from user where name=#{name};
    </select>
    <select id="getAll" resultMap="user">
        select id,name,age,gender,db_source from user;
    </select>
    <insert id="addUser" parameterType="com.zealzhangz.dto.po.User">
        INSERT INTO user(name,age,gender,db_source) VALUES(#{name},#{age},#{gender},#{dbSource});
    </insert>
</mapper>
  1. mysql数据库脚本
DROP DATABASE IF EXISTS user_db;
CREATE DATABASE user_db CHARACTER SET UTF8;
USE user_db;

CREATE TABLE user
(
  id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(60) NOT NULL  DEFAULT '' COMMENT '姓名',
  age TINYINT NOT NULL DEFAULT 0 COMMENT '年龄',
  gender TINYINT NOT NULL DEFAULT 0  COMMENT '男:1,女:0',
  db_source VARCHAR(60) NOT NULL DEFAULT 'db1' COMMENT '来自那个数据库,因为微服务架构可以一个服务对应一个数据库'
 );

INSERT INTO user(name,age,gender,db_source) VALUES('zhangsan',18,1,DATABASE());
INSERT INTO user(name,age,gender,db_source) VALUES('lisi',19,0,DATABASE());
INSERT INTO user(name,age,gender,db_source) VALUES('wangwu',20,1,DATABASE());
INSERT INTO user(name,age,gender,db_source) VALUES('zengliu',21,0,DATABASE());
INSERT INTO user(name,age,gender,db_source) VALUES('chengli',22,1,DATABASE());
  1. UserDao.java
package com.zealzhangz.dao;

import com.zealzhangz.dto.po.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * @version Version: 1.0
 * @date DateTime: 2018/08/15 00:22:00<br/>
 */
@Mapper
public interface UserDao {
    /**
     * add a user to db
     * @param user
     */
    void addUser(User user);

    /**
     * find a user by user name
     * @param user
     * @return
     */
    User findUserByName(User user);

    /**
     * get all user
     * @return
     */
    List<User> getAll();
}
  1. UserService.java
package com.zealzhangz.service;

import com.zealzhangz.dto.po.User;

import java.util.List;

/**
 * @version Version: 1.0
 * @date DateTime: 2018/08/15 00:32:00<br/>
 */
public interface UserService {
    /**
     * add a user to db
     * @param user
     */
    void addUser(User user);

    /**
     * find a user by user name
     * @param user
     * @return
     */
    User findUserByName(User user);

    /**
     * get all user
     * @return
     */
    List<User> getAll();
}
  1. UserServiceImpl.java
package com.zealzhangz.service.impl;

import com.zealzhangz.dao.UserDao;
import com.zealzhangz.dto.po.User;
import com.zealzhangz.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @version Version: 1.0
 * @date DateTime: 2018/08/15 00:33:00<br/>
 */
@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserDao userDao;

    @Override
    public void addUser(User user){
        userDao.addUser(user);
    }

    @Override
    public User findUserByName(User user){
        return userDao.findUserByName(user);
    }

    @Override
    public List<User> getAll(){
        return userDao.getAll();
    }
}

  1. UserController.java
package com.zealzhangz.controller;

import com.zealzhangz.dto.po.User;
import com.zealzhangz.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @version Version: 1.0
 * @date DateTime: 2018/08/15 00:39:00<br/>
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping(value="/add",method= RequestMethod.POST)
    public String addUser(@RequestBody User user){
        userService.addUser(user);
        return "SUCCESS";
    }

    @RequestMapping(value="/get/{name}",method=RequestMethod.GET)
    public User get(@PathVariable("name") String name) {
        User user = new User();
        user.setName(name);
        return userService.findUserByName(user);
    }

    @RequestMapping(value="/list",method=RequestMethod.GET)
    public List<User> list() {
        return userService.getAll();
    }
}
  1. 最后添加启动入口UserProvider8001App.java
package com.zealzhangz;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @version Version: 1.0
 * @date DateTime: 2018/08/15 00:44:00<br/>
 */
@SpringBootApplication
public class UserProvider8001App {
    public static void main(String[] args) {
        SpringApplication.run(UserProvider8001App.class,args);
    }
}

  1. 运行访问接口
http://127.0.0.1:8001/user/list
[
    {
        "id": 1,
        "name": "zhangsan",
        "age": 18,
        "gender": 1,
        "dbSource": "user_db"
    },
    {
        "id": 2,
        "name": "lisi",
        "age": 19,
        "gender": 0,
        "dbSource": "user_db"
    }
]

创建第三个模块--用户服务消费者

该模块直接调用用户服务提供者的服务

  1. POM.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>user-management</artifactId>
        <groupId>com.zealzhangz</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>microservice-cloud-consumer-user-8002</artifactId>

    <dependencies>
        <!-- 引入自己定义的api通用包,可以使用User用户Entity -->
        <dependency>
            <groupId>com.zealzhangz</groupId>
            <artifactId>dto</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
        <!-- 修改后立即生效,热部署 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>
</project>
  1. 代码结构目录
.
├── main
│   ├── java
│   │   └── com
│   │       └── zealzhangz
│   │           ├── UserConsumer8002App.java
│   │           ├── config
│   │           │   └── ConfigBean.java
│   │           └── controller
│   │               └── UserControlerConsumer.java
│   └── resources
│       └── application.yml
└── test
    └── java
  1. application.yml配置文件 主要定义服务端口
server:
  port: 8002
  1. 创建一个ConfigBean类
package com.zealzhangz.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @version Version: 1.0
 * @date DateTime: 2018/08/15 20:54:00<br/>
 */
@Configuration
public class ConfigBean {
    /**
     * RestTemplate提供了多种便捷访问远程Http服务的方法,
     * 是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集。
     */
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

  1. UserControllerConsumer.java
package com.zealzhangz.controller;

import com.zealzhangz.dto.po.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * @version Version: 1.0
 * @date DateTime: 2018/08/15 20:57:00<br/>
 */
@RestController
@RequestMapping("/consumer/user")
public class UserControllerConsumer {
    private static final String REST_URL_PREFIX = "http://localhost:8001";

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/add")
    public String add(User user){
        return restTemplate.postForObject(REST_URL_PREFIX + "/user/add",user,String.class);
    }
    @RequestMapping("/get/{name}")
    public User get(@PathVariable("name") String name){
        return restTemplate.getForObject(REST_URL_PREFIX + "/user/get/" + name,User.class);
    }
    @RequestMapping("/list")
    public List<User> list(){
        return restTemplate.getForObject(REST_URL_PREFIX + "/user/list",List.class);
    }
}

  1. 创建启动入口类
package com.zealzhangz;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @version Version: 1.0
 * @date DateTime: 2018/08/15 21:17:00<br/>
 */
@SpringBootApplication
public class UserConsumer8002App {
    public static void main(String[] args) {
        SpringApplication.run(UserConsumer8002App.class,args);
    }
}
  1. 访问接口
http://127.0.0.1:8002/consumer/user/list
[
    {
        "id": 1,
        "name": "zhangsan",
        "age": 18,
        "gender": 1,
        "dbSource": "user_db"
    },
    {
        "id": 2,
        "name": "lisi",
        "age": 19,
        "gender": 0,
        "dbSource": "user_db"
    }
]

总结

经过上面简单的几个步骤就建立了一个完整微服务示例,后面还会集成更多的SpringCloud组件,让我们的系统更加健壮