SA实战 ·《SpringCloud Alibaba实战》快速搭建三大微服务(一)

Pike_Chen
发布于 2022-5-31 16:30
浏览
0收藏

 

大家好,我是冰河~~

在《SpringCloud Alibaba实战》专栏中前面的文章,我们为开发用户微服务、商品微服务和订单微服务做了充分的准备。今天,我们就一起正式开撸三大微服务的核心业务。


点击上方卡片关注我

文章结构
本文有点长,文章的总体结构如下图所示。

SA实战 ·《SpringCloud Alibaba实战》快速搭建三大微服务(一)-鸿蒙开发者社区

 

项目概述
为了便于大家理解和跟上开发的进度,今天我们先使用SpringBoot快速搭建三大微服务,并基于SpringBoot完成三大微服务之间的交互。在后续的文章中,我们会陆续加入SpringCloud Alibaba的各种组件进行优化。

整体交互流程
在正式开撸源码之前,我们还是先来看下用户微服务、商品微服务和订单微服务的交互流程吧,也好让小伙伴们能够大体上了解系统的交互流程。

SA实战 ·《SpringCloud Alibaba实战》快速搭建三大微服务(一)-鸿蒙开发者社区

 

上图中比较清晰的描述了三大微服务的交互流程,这里,我就不再赘述了。如果有个别小伙伴对服务的交互流程存在疑问或者问题,可以到【冰河技术】知识星球中向我提问,文末有星球优惠券。

服务规划
对于用户微服务、商品微服务和订单微服务来说,每个服务占用的端口和访问的基础路径是不同的,这里就将每个服务占用的端口和访问的基础路径整理成下表所示。

SA实战 ·《SpringCloud Alibaba实战》快速搭建三大微服务(一)-鸿蒙开发者社区好了,接下来,我们就基于SpringBoot正式开撸三大微服务。

用户微服务
用户微服务主要用来提供对于用户基础信息的增删改查操作,用户执行下单操作时,会从用户微服务中查询用户的基本信息。用户微服务的总体结构如下图所示。

SA实战 ·《SpringCloud Alibaba实战》快速搭建三大微服务(一)-鸿蒙开发者社区

 

搭建项目
创建名称为shop-user的Maven项目,由于我们在前面的文章中,已经完成了对项目整体结构的搭建,所以,在shop-user的pom.xml文件里添加如下依赖即可。

<dependencies>
    <dependency>
        <groupId>io.binghe.shop</groupId>
        <artifactId>shop-bean</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>
</dependencies>

接下来,在项目的resources目录下创建application.yml文件,并在application.yml文件中添加如下配置。

server:
  port: 8060
  servlet:
    context-path: /user
spring:
  application:
    name: server-user
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/shop?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai
    username: root
    password: root
    platform: mysql
    type: com.alibaba.druid.pool.DruidDataSource
    # 下面为连接池的补充设置,应用到上面所有数据源中
    # 初始化大小,最小,最大
    initialSize: 10
    minIdle: 5
    maxActive: 20
    # 配置获取连接等待超时的时间
    maxWait: 60000
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 3600000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 3600000
    validationQuery: select 1 from dual
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    # 打开PSCache,并且指定每个连接上PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    maxOpenPreparedStatements: 20
    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat

  http:
    encoding:
      enabled: true
      charset: UTF-8
      force: true

  mybatis-plus:
    global-config:
      db-config:
        id-type: auto
        field-strategy: not-empty
        table-underline: true
        db-type: oracle
        logic-delete-value: 1
        logic-not-delete-value: 0
    mapper-locations: classpath:/mapper/*.xml
    configuration:
      jdbc-type-for-null: 'null'

 

从配置文件中,我们也可以看出,用户微服务启动后监听的端口为8060,基础的访问路径为/user,应用的名称为server-user,使用的数据库为MySQL,使用的数据库连接池为阿里开源的Druid,项目的交互编码采用UTF-8,持久化框架采用的是MyBatis-Plus。

这里注意一点的是,我们在application.yml文件中的mybatis-plus节点下定义了Mapper的xml文件的存放位置,如下所示

spring:
  mybatis-plus:
    mapper-locations: classpath:/mapper/*.xml

Mapper的xml文件位置在当前项目的classpath目录下的mapper目录下。也就是说,我们在使用MyBatis-Plus框架时,如果涉及到自己写SQL语句时,会将SQL语句写到XML文件中,而不是通过注解的方式写到接口的方法上。

开发持久层
用户持久层主要是提供对于用户数据表的基本增删改查操作。持久化框架采用的是MyBatis-Plus,在项目的io.binghe.shop.user.mapper包下创建UserMapper接口,主要用作使用MyBatis-Plus框架操作用户数据表的基础Mapper接口,源码如下所示。

/**
 * @author binghe
 * @version 1.0.0
 * @description 用户Mapper
 */
public interface UserMapper extends BaseMapper<User> {
    
}

可以看到,在UserMapper接口中没有定义任何方法,这是由于MyBatis-Plus框架中已经封装好了针对实体类的基础增删改查操作,而我们目前快速搭建三大微服务的过程中,使用MyBatis-Plus框架封装的基础增删改查操作就能够满足需求了。所以,在UserMapper接口中,未定义任何方法。

接下来,在resources目录下创建mapper目录里创建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="io.binghe.shop.user.mapper.UserMapper">
 
</mapper>

UserMapper.xml文件与UserMapper接口是一一对应的,UserMapper中定义的接口方法,都会在UserMapper.xml文件中写对应的SQL语句。由于UserMapper接口中位定义任何方法,所以在UserMapper.xml文件中,也就未声明任何SQL语句了。

开发业务逻辑层
用户微服务的业务逻辑层主要提供针对用户信息的业务逻辑开发,在io.binghe.shop.user.service包下创建UserService接口,源码如下所示。

/**
 * @author binghe
 * @version 1.0.0
 * @description 用户业务接口
 */
public interface UserService {

    /**
     * 根据id获取用户信息
     */
    User getUserById(Long userId);
}

可以看到,在UserService接口中,定义了一个通过用户id获取用户信息的方法getUserById(),提供这个方法传入用户的id编号就可以获取到用户的信息。

接下来,在io.binghe.shop.user.service.impl包下创建UserServiceImpl类,实现UserService接口,并实现UserService接口定义的方法getUserById(),UserServiceImpl类的源码如下所示。

/**
 * @author binghe
 * @version 1.0.0
 * @description 用户业务实现类
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public User getUserById(Long userId) {
        return userMapper.selectById(userId);
    }
}

由于项目中使用了SpringBoot,SpringBoot又是基于Spring开发的,所以我们在项目开发过程中,都是使用Spring来管理Java对象的生命周期,也就是bean的生命周期。所以在UserServiceImpl类上标注了@Service注解,使用@Autowired注解注入了UserMapper对象,并在getUserById()中调用UserMapper对象的selectById()方法获取用户的基本信息。

开发接口层
用户微服务的接口层主要对外提供用户微服务的接口,在io.binghe.shop.user.controller包下创建UserController类,源码如下所示。

/**
 * @author binghe
 * @version 1.0.0
 * @description 用户接口
 */
@Slf4j
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping(value = "/get/{uid}")
    public User getUser(@PathVariable("uid") Long uid){
        User user = userService.getUserById(uid);
        log.info("获取到的用户信息为:{}", JSONObject.toJSONString(user));
        return user;
    }
}

在UserController上标注了@RestController注解,表明UserController能够提供Restful风格的接口,同时在UserController类中使用@Autowired注解注入了UserService对象,在getUser()方法中调用UserService对象的getUserById()方法获取用户的信息,并返回用户的信息,同时在getUserById()方法上标注了@GetMapping注解表示这个接口采用HTTP GET方式访问,并定义了这个接口的访问路径。

用户调用订单微服务的提交订单接口下单时,订单微服务会调用用户微服务的接口获取用户的基本信息。

开发服务启动类
在用户微服务的io.binghe.shop包下创建UserStarter类,作为用户微服务的启动类,源码如下所示。

/**
 * @author binghe
 * @version 1.0.0
 * @description 启动用户服的类
 */
@SpringBootApplication
@EnableTransactionManagement(proxyTargetClass = true)
@MapperScan(value = { "io.binghe.shop.user.mapper" })
public class UserStarter {

    public static void main(String[] args){
        SpringApplication.run(UserStarter.class, args);
    }
}

 

至此,用户微服务开发完成。

商品微服务
商品微服务主要用来提供对于商品基础信息的增删改查操作,用户执行下单操作时,会从商品微服务中查询商品的基本信息,并完成商品的库存扣减操作。商品微服务的总体结构如下图所示。

SA实战 ·《SpringCloud Alibaba实战》快速搭建三大微服务(一)-鸿蒙开发者社区

 

项目搭建
商品微服务的搭建过程和用户微服务的搭建过程类似,只是在application.yml文件中的部分配置不同,在商品微服务的application.yml文件中,需要将端口修改为8070,基础访问路径修改为/product,应用名称修改为server-product,具体的源码可以到【冰河技术】星球获取,文末有优惠券。

开发持久层
商品持久层主要提供对于商品数据表的增删改查操作,在io.binghe.shop.product.mapper包下创建ProductMapper接口,用于MyBatis-Plus操作商品数据表的基础Mapper接口,源码如下所示。

/**
 * @author binghe
 * @version 1.0.0
 * @description 商品服务Mapper接口
 */
public interface ProductMapper extends BaseMapper<Product> {

    /**
     * 扣减商品库存
     */
    int updateProductStockById(@Param("count") Integer count, @Param("id") Long id);
}

 

可以看到,在ProductMapper接口中除了可以使用MyBatis-Plus框架提供的基础增删改查外,还提供了一个单独的扣减商品库存的方法updateProductStockById(),传入需要扣减的商品数量和商品的id就可以实现商品库存的扣减操作。

接下来,在resources的mapper目录下创建ProductMapper.xml文件,在ProductMapper.xml文件中实现updateProductStockById对应的SQL语句,如下所示。

<?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="io.binghe.shop.product.mapper.ProductMapper">
    <update id="updateProductStockById">
        update t_product set t_pro_stock = t_pro_stock - #{count} where id = #{id}
    </update>
</mapper>

开发业务逻辑层
商品微服务的业务逻辑层主要提供针对商品信息的业务逻辑操作,在io.binghe.shop.product.service包下创建ProductService接口,源码如下所示。

/**
 * @author binghe
 * @version 1.0.0
 * @description 商品Service接口
 */
public interface ProductService {

    /**
     * 根据商品id获取商品信息
     */
    Product getProductById(Long pid);


    /**
     * 扣减商品库存
     */
    int updateProductStockById(Integer count, Long id);
}

 

可以看到,在ProductService接口中定义了获取商品信息的方法getProductById()和扣减商品库存的方法updateProductStockById()。

 

文章转自公众号:冰河技术

分类
已于2022-5-31 16:30:55修改
收藏
回复
举报
回复
    相关推荐