【二】、SpringCloud工程的搭建

导读:本篇文章讲解 【二】、SpringCloud工程的搭建,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

1.开发步骤(实用)

  1. 建module
  2. 改pom
  3. 写yml
  4. 主启动
  5. 写业务类

基本思路

前后端分离,后端传json字符串给前端,前端不需要了解后端的具体业务,前端按照约定和规范判断里面的编码是不是成功,成功的话就去完成逻辑的展现

2.搭建父工程

1.新建空项目

新建空项目:cloud2022

2.在空项目中建父项目

建父项目

删除src无关文件

父工程

3.配置JDK版本

配置JDK版本

4.在父工程中导入相关依赖

注意:

  1. 父工程dependencyManagement中管理的依赖在你们仓库中可能没有,所以要注释掉dependencyManagement先下载对应版本的依赖
  2. dependencyManagement只是声明依赖,并不实现引入,因此子项目需要显示声明需要用的依赖
  3. 子模块继承之后,提供作用:锁定版本并且子modlue不用写groupId和version
  4. 如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并没有指定具体版本,才会从父项目中继承该项依赖,并且version和scope都取自父pom
  5. 如果子项目中指定了版本号,则使用子项目指定的jar版
 <!--统一管理jar包和版本-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
        <mysql.version>8.0.27</mysql.version>
        <druid.verison>1.2.6</druid.verison>
        <mybatis.spring.boot.verison>1.3.0</mybatis.spring.boot.verison>
    </properties>

    <!--子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version-->
    <!--dependencyManagement只是声明依赖,并不实现引入,因此子项目需要显示声明需要用的依赖-->
    <!--如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并没有指定具体版本,才会从父项目中继承该项依赖,并且version和scope都取自父pom-->
    <!--如果子项目中指定了版本号,则使用子项目指定的jar版本-->
    <dependencyManagement>
        <dependencies>
            <!--spring boot 2.2.2-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud Hoxton.SR1-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud alibaba 2.1.0.RELEASE-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- MySql -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <!--druid -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.verison}</version>
            </dependency>
            <!-- mybatis-springboot整合 -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.spring.boot.verison}</version>
            </dependency>
            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
            <!--junit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
            <!-- log4j -->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

5.创建数据库

CREATE DATABASE /*!32312 IF NOT EXISTS*/`cloud` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci */;USE `cloud`;/*Table structure for table `payment` */DROP TABLE IF EXISTS `payment`;CREATE TABLE `payment` (
	  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
	  `serial` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL,
	  PRIMARY KEY (`id`)
	) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;/*Data for the table `payment` */insert  into `payment`(`id`,`serial`) values (1,'尚硅谷'),(2,'alibaba'),(3,'京东'),(4,'头条');

3.搭建cloud-provider-payment8001子工程

1.在父工程下创建cloud-provider-payment8001子工程

创建cloud-provider-payment8001子工程

2.在子工程中导入相关依赖

<dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-actuator</artifactId>
       </dependency>
       <dependency>
           <groupId>org.mybatis.spring.boot</groupId>
           <artifactId>mybatis-spring-boot-starter</artifactId>
       </dependency>
       <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>druid-spring-boot-starter</artifactId>
       </dependency>
       <!--mysql-connection-java-->
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
       </dependency>
       <!--jdbc-->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-jdbc</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-devtools</artifactId>
           <scope>runtime</scope>
           <optional>true</optional>
       </dependency>
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <optional>true</optional>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
       </dependency>
   </dependencies>

3.在子工程中新建application.yml文件

注意:

  1. MySQL5用的驱动url是com.mysql.jdbc.Driver
  2. MySQL6以后用的是com.mysql.cj.jdbc.Driver
server:
  port: 8001 #服务端口

spring:
  application:
  	#设置当前应用的名称,将来会在eureka中显示。将来需要该名称来获取路径
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource  #当前数据源操作类型
    driver-class-name: com.mysql.cj.jdbc.Driver   #数据库驱动包
    #characterEncoding=UTF-8  指定所处理字符的解码和编码的格式
    #useSSL=false     MySQL在高版本需要指明是否进行SSL连接  1.true 需要连接  2.false 不需要连接
    #serverTimezone   配置连接数据库驱动的时区参数
        #TC代表的是全球标准时间,是以原子时计时,更加精准,适应现代社会的精确计时。
        #GMT格林威治标准时间,是指位于伦敦郊区的皇家格林尼治天文台的标准时间。
        #但是我们使用的时间是北京时区也就是东八区,领先UTC和GMT八个小时。
        #一般视为无差别,即:北京时间=UTC+8=GMT+8。
    #rewriteBatchedStatements 这个参数允许JDBC连接能够一次执行多条增删改查,假如没配这个参数的话,所有批量操作都会报错。
        #MySQL的JDBC连接的url中要加rewriteBatchedStatements参数,并保证5.1.13以上版本的驱动,才能实现高性能的批量插入。
        #MySQL JDBC驱动在默认情况下会无视executeBatch()语句,
        #把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,
        #批量插入实际上是单条插入,直接造成较低的性能。
        #只有把rewriteBatchedStatements参数置为true, 驱动才会帮你批量执行SQL
        #另外这个选项对INSERT/UPDATE/DELETE都有效
    url: jdbc:mysql://localhost:3306/cloud?characterEncoding=UTF-8&&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
    username: root
    password: 123456

  devtools:
    restart:
      enabled: true

mybatis:
  #如果mapper类和mapper.xml不在同一个路径下的时候,可以指定mapper.xml的路径
  #1.classpath:只会到你的classes路径中查找找文件。
  #2.classpath*:不仅会到classes路径,还包括jar文件中(classes路径)进行查找。
  mapper-locations: classpath*:mapper/*.xml
  type-aliases-package: com.asule.entities #所有别名所在包

4.创建实体类

  1. Payment实体类

    package com.asule.entities;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.io.Serializable;
    import java.math.BigInteger;
    
    /**
     * @author: ASULE
     * @create: 2022/1/21 22:45
     * @version: 1.0
     **/
    //@Data:生成@Setter、@Getter、@RequiredArgsConstructor、@ToString、@EqualsAndHashCode
    @Data
    //@AllArgsConstructor:生产全参构造器
    @AllArgsConstructor
    //@NoArgsConstructor:生产无参构造器
    @NoArgsConstructor
    public class Payment implements Serializable {
    
        BigInteger id;
        String serial;
    }
    
  2. Json封装体CommonResult

    package com.asule.entities;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    /**
     * @author: ASULE
     * @create: 2022/1/22 16:57
     * @version: 1.0
     **/
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    //泛型,不管传过来什么类型都可以接受并且发送给前端
    public class CommonResult<T> {
    
        //报错信息:404 not_found
        private Integer code;
        private String message;
        private T data;
    
        //当data为空的时候需要这个构造方法
        public CommonResult(Integer code,String message){
            this(code,message,null);
        }
    
    }
    

5.创建dao层

  1. 新建PaymentDao接口

    package com.asule.dao;
    
    import com.asule.entities.Payment;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Param;
    
    /**
     * @author: ASULE
     * @create: 2022/1/21 22:24
     * @version: 1.0
     **/
    /*
        @Mapper 和 @MapperScan的区别
        1.@Mapper
            作用:用在接口类上,在编译之后会生成相应的接口实现类
            位置:对应的某个接口类上面
        2.@MapperScan
            作用:扫描指定包下所有的接口类,然后所有接口在编译之后都会生产相应的实现类
            位置:在启动类上添加
        小结: @Mapper是对单个接口的注解,适用于单个操作
              @MapperScan是对整个包下所有的接口类的注解,适用于批量操作。
              使用@MapperScan后接口类就不需要@Mapper
     */
    @Mapper
    public interface PaymentDao {
    
        int create(Payment payment);
    
        /*
            @Param
                作用:给参数命名,参数命名后就能根据名字得到参数值,
              正确的将参数传入sql语句中(一般通过#{}的方式,${}会有sql注入的问题)
                说明:当你使用了@Param注解来声明时,使用#{}和${}的方式都可以,如果
              不使用@Param注解来声明参数时,必须使用#{},如果使用${}的方式会报错。
                当传递对象时JavaBean时(即一个对象),最好不使用@Param注解,这样
              在SQL语句里就可以直接引用JavaBean属性,而且只能引用JavaBean存在的属性。
              如果添加了@Param注解在SQL中使用#{名称.属性}会取不到值
         */
        Payment getPaymentById(@Param("id")Long id);
    }
    
  2. 在resources下创建mapper文件夹,并在文件夹下创建PaymentMapper.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">
    <!--
        在mybatis中,映射文件中的namespace是用于绑定Dao接口的,即面向接口编程。
        当你的namespace绑定接口后,你可以不用写接口实现类,mybatis会通过该绑定自动
        帮你找到对应要执行的SQL语句
    -->
    <mapper namespace="com.asule.dao.PaymentDao">
        <!--
        ResultMap的作用:主要用于解决实体类属性名与数据库表中字段名不
        一致的情况下,解决将查询结果映射成实体对象。
    
        ResultMap的属性:
                id:是该封装规则的唯一标识符
                type:是封装出来的类型,可以是jdk自带的,也可以是
            自定义的,由于我们开启了别名标签,所以可以不写路径只写类名
                <result>:用来映射数据表的列到实体对象的属性
                <id>:用来映射标识属性
                column:从数据库中查询到的结果集的列名或列别名(字段名)
                property:将column属性指定的列结果映射到对象的哪个属性
        -->
        <resultMap id="BaseResultMap" type="com.asule.entities.Payment">
            <id column="id" property="id" jdbcType="BIGINT"></id>
            <result column="serial" property="serial" jdbcType="VARCHAR"></result>
        </resultMap>
    
        <!--useGeneratedKeys="true",keyProperty="id"
        指的是:如果插入的表id以自增列为主键,则允许JDBC支持自动生成逐渐
        并可以将自动生成的主键id返回
        注意:useGeneratedKeys参数只针对 insert 语句生效,默认为false-->
        <insert id="create" parameterType="payment" useGeneratedKeys="true" keyProperty="id">
            insert into payment(serial) values(#{serial})
        </insert>
    
        <select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
            select * from payment where id = #{id}
        </select>
    </mapper>
    

6.创建服务层

  1. 创建PaymentService接口

    package com.asule.service;
    
    import com.asule.entities.Payment;
    import org.apache.ibatis.annotations.Param;
    
    /**
     * @author: ASULE
     * @create: 2022/1/21 23:05
     * @version: 1.0
     **/
    public interface PaymentService {
    
        int create(Payment payment);
    
        Payment getPaymentById(Long id);
    }
    
  2. 创建PaymentServiceImpl实现类实现PaymentService接口

    package com.asule.service.impl;
    
    import com.asule.dao.PaymentDao;
    import com.asule.entities.Payment;
    import com.asule.service.PaymentService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * @author: ASULE
     * @create: 2022/1/21 23:14
     * @version: 1.0
     **/
    @Service
    public class PaymentServiceImpl implements PaymentService {
    
        @Autowired
        private PaymentDao paymentDao;
    
        @Override
        public int create(Payment payment) {
            return paymentDao.create(payment);
        }
    
        @Override
        public Payment getPaymentById(Long id) {
            return paymentDao.getPaymentById(id);
        }
    }
    

7.创建控制层

@RestController、@Controller、@ResponseBody注解的区别
后续自己写一个自己的理解

package com.asule.controller;

import com.asule.entities.CommonResult;
import com.asule.entities.Payment;
import com.asule.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @author: ASULE
 * @create: 2022/1/21 23:19
 * @version: 1.0
 **/
@RestController
//用于做日志输出
@Slf4j
@RequestMapping("/payment")
public class PaymentController {
    /*
        @Autowired的作用:它可以对类成员变量、方法及构造函数进行标注,让 spring完成bean自动装配的工作。
        @Autowired 默认是按照类去匹配,配合@Qualifier可以指定按照名称去装配bean。
     */
    @Autowired
    private PaymentService paymentService;

    /*
        前后端分离了,我们只能传一个CommonResult
        @RequestBody的作用是将前端传来的json格式的数据转为自己定义好的javabean对象
        注:@RequestBody要写在方法的参数前,不能写在方法名上方
        @ResponseBody的作用是将后端以return返回的javabean类型数据转为json类型数据。
     */
    @PostMapping("/create")
    public CommonResult create(@RequestBody Payment payment){
        int result = paymentService.create(payment);
        log.info("插入数据的ID:\t" + payment.getId());
        log.info("插入数据的结果:" + result);
        if (result > 0){
            return new CommonResult(200,"插入数据成功",result);
        }else {
            return new CommonResult(444,"插入数据失败",null);
        }
    }

    @GetMapping("/get/{id}")
    /*
        @PathVariable的作用:接收请求路径中占位符的值
     */
    public CommonResult getPaymentById(@PathVariable("id") Long id){
        Payment payment = paymentService.getPaymentById(id);
        int age = 10/2;
        System.out.println(age);
        log.info("***查询结果:" + payment);
        if(payment != null){
            return new CommonResult(200,"查询数据成功",payment);
        }else {
            return new CommonResult(444,"没有对应记录",null);
        }
    }
}

8.使用Postman测试

  1. post测试
    post测试
  2. get测试get测试

4.搭建cloud-consumer-order80

1.在父工程下创建cloud-consumer-order80子工程

父工程下创建cloud-consumer-order80子工程

2.在子工程中导入相关依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
</dependencies>

3.在子工程中新建application.yml文件

server:
  port: 80
  
#设置当前应用的名称,将来会在eureka中显示。将来需要该名称来获取路径  
spring:
  application:
    name: cloud-consumer-order80

4.启动类(此后启动类代码无特殊情况不再赘述)

package com.asule;

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

/**
 * @author: ASULE
 * @create: 2022/1/22 18:13
 * @version: 1.0
 **/
@SpringBootApplication
public class Order80Application {
    public static void main(String[] args) {
        SpringApplication.run(Order80Application.class,args);
    }
}

5.实体类与payment8001工程中相同

直接拷贝payment8001工程中的entities文件

6.使用RestTemplate完成远程调用

RestTemplate是一种简单便捷的访问restful服务的模板类,用于在Java代码里访问restful服务。

package com.asule.config;

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

/**
 * @author: ASULE
 * @create: 2022/1/22 18:43
 * @version: 1.0
 **/
@Configuration
public class Config {
    /*
        @Bean注解:用于告诉方法,产生一个Bean对象
    ,然后把这个Bean对象交给Spring管理
     */
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

7.创建控制层

package com.asule.controller;

import com.asule.entities.CommonResult;
import com.asule.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

/**
 * @author: ASULE
 * @create: 2022/1/22 18:47
 * @version: 1.0
 **/
@RestController
@Slf4j
@RequestMapping("/consumer")
public class OrderController {

    private final static String PAYMENT_URL = "http://localhost:8001";

    @Autowired
    private RestTemplate restTemplate;
    /*
        用RestTemplate的postForObject请求其他系统的接口,发现该接口是接收json格式参数
     */
    @PostMapping ("/payment/create")
    public CommonResult<Payment> create(Payment payment){
        return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
    }

    @GetMapping("/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
        return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    }
}

5.工程重构

观察到的问题:系统中有重复的部分,所以要重构
重复部分

  1. 建立cloud-api-commons模块

  2. 导入相关依赖

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.1.0</version>
        </dependency>
    </dependencies>
    
  3. 将消费者和服务者中重复的部分(即entities)拷贝到新模块当中,删除消费者和服务中的重复的那部分

  4. clean
    clean

  5. install

将项目本身编译并打包到本地仓库,这样其他项目引用本项目的jar包时不用去私服上下载jar包,直接从本地就可以拿到刚刚编译打包好的项目的jar包

install

  1. 在consumer和provider中引入自己所定义的包
 <!--引入自己定义的api通用包,可以使用Payment支付Entity-->
       <dependency>
           <groupId>com.asule</groupId>
           <!--自己所打包模块的名称-->
           <artifactId>cloud-api-commons</artifactId>
           <version>1.0-SNAPSHOT</version>
       </dependency>

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/81911.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!