springCloud微服务之用户微服务注册

上一节已经添加了eureka服务发现和服务治理中心,里面只有它自己显然是没有啥用的,这时候我们自己写好的业务微服务如何注册到注册中心呢?

做微服务架构首先是微服务的划分,这次的例子主要以用户购买商品并下单的方式来划分微服务,总共划分三个微服务:

  • cloud-user 用户微服务(用来维护用户基本信息)
  • cloud-order 订单微服务 (用来维护订单基本信息)
  • cloud-good 商品微服务 (用来维护商品基本信息)

不仅划分服务还划分数据库,每个微服务对应一个数据库这也是最大化的解耦,这种方式比如写了一个角色权限的微服务,其实用户角色权限大部分系统都差不多,有其他项目要用,只需要将一个微服务jar包和此微服务对应的数据库拿过去就可以了,这样就可以很方便的完成项目重复功能的复用

项目大体功能就是用户购买商品然后下单,会有服务调用操作,异步操作,消息提醒,数据聚合,网关路由,权限限制等。

其他两个微服务的注册后面会讲解,这节主要讲解用户微服务的编写和注册

1、创建数据库表结构

create schema if not exists cloud_user collate utf8mb4_0900_ai_ci;

create table if not exists user
(
	id char(32) not null,
	user_name varchar(20) not null comment '用户名',
	nick_name varchar(20) not null comment '用户昵称',
	user_pswd varchar(50) not null comment '用户密码',
	create_date datetime not null comment '创建日期',
	create_by char(32) not null comment '创建人',
	update_date datetime not null comment '更新日期',
	update_by char(32) not null comment '更新人',
	constraint user_id_uindex
		unique (id)
)
comment '用户表';

alter table user
	add primary key (id);

2、新建cloud-user微服务子模块

新建方式和上一节是类似的,这里就不再说了

3、添加用户微服务需要的依赖

在用户微服务pom.xml中添加如下代码

这里集成了druid数据库连接池,mysql jdbc驱动,jpa以及服务注册需要的依赖

<?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>spring-cloud-study</artifactId>
        <groupId>com.apgblogs</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.apgblogs</groupId>
    <artifactId>cloud-user</artifactId>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>
        <!--服务客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
</project>

4、创建controller,entity,service,repository等包

创建如下图所示的包和对应的类,entity中的实体类可以采用表映射的方式自动生成,对于如何表映射生成实体类可以访问下面的这篇文章链接

UserEntity类

package com.apgblogs.clouduser.entity;

import org.hibernate.annotations.GenericGenerator;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Objects;

/**
 * @author xiaomianyang
 * @description
 * @date 2019-07-02 20:10
 */
@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "user", schema = "cloud_user", catalog = "")
public class UserEntity {
    private String id;
    private String userName;
    private String nickName;
    private String userPswd;
    private Timestamp createDate;
    private String createBy;
    private Timestamp updateDate;
    private String updateBy;

    @Id
    @Column(name = "id", nullable = false, length = 32)
    @GenericGenerator(name = "jpa-uuid", strategy = "uuid")
    @GeneratedValue(generator = "jpa-uuid")
    public String getId() {
        return id;
    }

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

    @Basic
    @Column(name = "user_name", nullable = false, length = 20)
    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    @Basic
    @Column(name = "nick_name", nullable = false, length = 20)
    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    @Basic
    @Column(name = "user_pswd", nullable = false, length = 50)
    public String getUserPswd() {
        return userPswd;
    }

    public void setUserPswd(String userPswd) {
        this.userPswd = userPswd;
    }

    @Basic
    @Column(name = "create_date", nullable = false)
    @CreatedDate
    public Timestamp getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Timestamp createDate) {
        this.createDate = createDate;
    }

    @Basic
    @Column(name = "create_by", nullable = false, length = 32)
    public String getCreateBy() {
        return createBy;
    }

    public void setCreateBy(String createBy) {
        this.createBy = createBy;
    }

    @Basic
    @Column(name = "update_date", nullable = false)
    @LastModifiedDate
    public Timestamp getUpdateDate() {
        return updateDate;
    }

    public void setUpdateDate(Timestamp updateDate) {
        this.updateDate = updateDate;
    }

    @Basic
    @Column(name = "update_by", nullable = false, length = 32)
    public String getUpdateBy() {
        return updateBy;
    }

    public void setUpdateBy(String updateBy) {
        this.updateBy = updateBy;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UserEntity that = (UserEntity) o;
        return Objects.equals(id, that.id) &&
                Objects.equals(userName, that.userName) &&
                Objects.equals(nickName, that.nickName) &&
                Objects.equals(userPswd, that.userPswd) &&
                Objects.equals(createDate, that.createDate) &&
                Objects.equals(createBy, that.createBy) &&
                Objects.equals(updateDate, that.updateDate) &&
                Objects.equals(updateBy, that.updateBy);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, userName, nickName, userPswd, createDate, createBy, updateDate, updateBy);
    }
}

UserRepository接口

package com.apgblogs.clouduser.repository;

import com.apgblogs.clouduser.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * @author xiaomianyang
 * @description
 * @date 2019-07-02 20:12
 */
public interface UserRepository extends JpaRepository<UserEntity,String> {
}

UserServiceImpl 用户业务实现类

package com.apgblogs.clouduser.service;

import com.apgblogs.clouduser.entity.UserEntity;
import com.apgblogs.clouduser.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
 * @author xiaomianyang
 * @description
 * @date 2019-07-02 20:15
 */
@Service
public class UserServiceImpl {
    
    @Autowired
    private UserRepository userRepository;
    
    /**
     * @description 通过用户Id获取用户
     * @author xiaomianyang
     * @date 2019-07-02 20:16
     * @param [id]
     * @return com.apgblogs.clouduser.entity.UserEntity
     */
    public UserEntity getUser(String id){
        if(!userRepository.existsById(id)){
            return null;
        }
        return userRepository.findById(id).get();
    }
    
    /**
     * @description 保存用户
     * @author xiaomianyang
     * @date 2019-07-02 20:19
     * @param [userEntity]
     * @return com.apgblogs.clouduser.entity.UserEntity
     */
    public UserEntity saveUser(UserEntity userEntity){
        if(StringUtils.isEmpty(userEntity)){
            return null;
        }
        userEntity.setCreateBy("sys");
        userEntity.setUpdateBy("sys");
        return userRepository.save(userEntity);
    }
}

UserController 用户控制器

package com.apgblogs.clouduser.service;

import com.apgblogs.clouduser.entity.UserEntity;
import com.apgblogs.clouduser.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
 * @author xiaomianyang
 * @description
 * @date 2019-07-02 20:15
 */
@Service
public class UserServiceImpl {
    
    @Autowired
    private UserRepository userRepository;
    
    /**
     * @description 通过用户Id获取用户
     * @author xiaomianyang
     * @date 2019-07-02 20:16
     * @param [id]
     * @return com.apgblogs.clouduser.entity.UserEntity
     */
    public UserEntity getUser(String id){
        if(!userRepository.existsById(id)){
            return null;
        }
        return userRepository.findById(id).get();
    }
    
    /**
     * @description 保存用户
     * @author xiaomianyang
     * @date 2019-07-02 20:19
     * @param [userEntity]
     * @return com.apgblogs.clouduser.entity.UserEntity
     */
    public UserEntity saveUser(UserEntity userEntity){
        if(StringUtils.isEmpty(userEntity)){
            return null;
        }
        userEntity.setCreateBy("sys");
        userEntity.setUpdateBy("sys");
        return userRepository.save(userEntity);
    }
}

5、编写启动类,添加服务发现和启用jpa注解

UserApplication 启动类

@EnableJpaAuditing 主要是用来自动生成实体类创建日期和修改日期的
@EnableDiscoveryClient 表示该类是一个服务客户端,可以被服务注册中心所发现
package com.apgblogs.clouduser;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

/**
 * @author xiaomianyang
 * @description
 * @date 2019-07-02 20:07
 */
@SpringBootApplication
@EnableJpaAuditing
@EnableDiscoveryClient
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class,args);
    }
}

6、编写配置文件

创建两个配置文件,如下图

application.yml

以下配置文件主要是连接数据库和jpa的配置,这些之前springBoot都有介绍,eureka就是服务注册中心地址的配置,配置了这个注解在配合启动类上的@EnableDiscoveryClient注解就可以完成服务的注册了
server:
  port: 8881
spring:
  datasource:
    name: druidDataSource
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://apg-server:3306/cloud_user?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
    druid:
      filters: stat,wall,log4j,config
      max-active: 100
      initial-size: 1
      max-wait: 60000
      min-idle: 1
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      validation-query: select 'x'
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      pool-prepared-statements: true
      max-open-prepared-statements: 50
      max-pool-prepared-statement-per-connection-size: 20
      web-stat-filter:
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
        url-pattern: /*
      stat-view-servlet:
        allow: 127.0.0.1
        deny: apg-server
        login-username: admin
        login-password: admin
        reset-enable: true
  jpa:
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    show-sql: true
    hibernate:
      ddl-auto: none
  application:
    name: cloud-user
#服务注册地址配置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8801/eureka/
  instance:
    prefer-ip-address: true

log4j.properties log属性文件

log4j.rootLogger=debug, stdout, R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%5p - %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=log4j.log

log4j.appender.R.MaxFileSize=100KB
log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

7、注释掉之前Eureka的高可用将配置2注释掉,目前还用不到所以也没必要启动那么多服务

在eureka微服务中对配置文件以下代码进行注册

8、启动项目访问测试

将Eureka和User两个微服务同时启动,也可以先启动Eureka在启动User,都可以的。

访问服务注册中心看看User微服务是不是已经出现了

如果出现以下的应用名那就用户微服务注册成功了

9、用postMan对用户微服务进行接口测试

新增用户接口测试

通过用户Id查询用户测试

10、文章源码地址

码云: https://gitee.com/apgblogs/springCloudStudy/tree/user/

至此用户微服务就已经完美注册到服务中心了,也完成了用户微服务基本的新增用户和获取单个用户的restFul风格的接口,下一节会继续讲解后续的操作

1 条评论

发表评论