SpringCloud工程部署启动 1.工程搭建部署

简介: 本教程提供两种SpringCloud微服务搭建方案:一键导入或从零创建。通过创建user-service与order-service,配置Maven依赖、数据库及YAML文件,实现基础服务运行。使用RestTemplate完成服务间远程调用,解决订单服务中用户信息缺失问题,帮助理解微服务拆分与通信机制,为后续深入学习打下基础。(239字)

方案一:完整工程导入
● ,如无法运行尝试换未编译版:
● 下载解压上述工程,ide工具导入
方案二:从零开始搭建
1.工程与module创建
1.1 父工程创建

1.2 子module创建
● module名称:order-service、user-service
● 无效文件夹删除,整体结构如图2

1.3 父pom资源引入

粘贴以下资源依赖,粘贴后maven会自动拉取依赖,如未拉取请手动刷新


org.springframework.boot
spring-boot-starter-parent
2.3.9.RELEASE


UTF-8
UTF-8
1.8
Hoxton.SR10
5.1.47
2.1.1
1.18.20





org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import



mysql
mysql-connector-java
${mysql.version}



org.mybatis.spring.boot
mybatis-spring-boot-starter
${mybatis.version}


org.projectlombok
lombok
${lombok.version}



1.4 子module资源引入
user-service



org.springframework.boot
spring-boot-starter-web


mysql
mysql-connector-java



org.mybatis.spring.boot
mybatis-spring-boot-starter


org.projectlombok
lombok


app


org.springframework.boot
spring-boot-maven-plugin



order-service



org.springframework.boot
spring-boot-starter-web


mysql
mysql-connector-java



org.mybatis.spring.boot
mybatis-spring-boot-starter


org.projectlombok
lombok




org.springframework.boot
spring-boot-maven-plugin



1.5 业务代码编写
1.user-service
application.yml配置文件
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
username: root
password: root123456
driver-class-name: com.mysql.jdbc.Driver
mybatis:
type-aliases-package: cn.itcast.user.pojo
configuration:
map-underscore-to-camel-case: true
logging:
level:
cn.itcast: debug
pattern:
dateformat: MM-dd HH:mm:ss:SSS
|--mapper
|-- UserMapper
package cn.itcast.user.mapper;

import cn.itcast.user.pojo.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

/**

  • 用户持久层
    *
  • @author
  • @date 2022-12-22 14:12
    */
    public interface UserMapper {

    /**

    • 根据ID查找用户
    • @param id 用户ID
    • @return 用户实体信息
      /
      @Select("select
      from tb_user where id=#{id}")
      User findById(@Param("id") Long id);
      }
      |--pojo
      |-- User
      package cn.itcast.user.pojo;

import lombok.Data;

/**

  • 用户实体
    *
  • @author
  • @date 2022-12-22 14:07
    */
    @Data
    public class User {

    /**

    • 主键ID
      */
      private Long id;

      /**

    • 用户姓名
      */
      private String username;

      /**

    • 用户地址
      */
      private String address;
      }
      |--service
      |-- UserService
      package cn.itcast.user.service;

import cn.itcast.user.mapper.UserMapper;
import cn.itcast.user.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**

  • 用户业务层
    *
  • @author
  • @date 2022-12-22 14:13
    */
    @Service
    public class UserService {

    @Autowired
    private UserMapper userMapper;

    /**

    • 根据ID查找用户
    • @param id 用户ID
    • @return 用户实体信息
      */
      public User findById(Long id) {
      if (Objects.isNull(id)) {
       return null;
      
      }
      return userMapper.findById(id);
      }

}
|--web
|-- UserController
package cn.itcast.user.web;

import cn.itcast.user.pojo.User;
import cn.itcast.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**

  • 用户控制层
    *
  • @author
  • @date 2022-12-22 14:15
    */
    @RestController
    @RequestMapping("/user")
    public class UserController {

    @Autowired
    private UserService userService;

    /**

    • 根据ID查找用户
    • @param id ID
    • @return 用户信息
      */
      @GetMapping("/{id}")
      public User findById(@PathVariable("id") Long id) {
      return userService.findById(id);
      }
      }
      |--UserApplication
      package cn.itcast.user;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**

  • 启动类
    *
  • @author
  • @date 2022-12-22 14:00
    */
    @MapperScan("cn.itcast.user.mapper")
    @SpringBootApplication
    public class UserApplication {

    public static void main(String[] args) {

     SpringApplication.run(UserApplication.class, args);
     System.out.println("用户工程启动成功");
    

    }
    }

2.order-service
application.yml配置文件
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
username: root
password: root123456
driver-class-name: com.mysql.jdbc.Driver
mybatis:
type-aliases-package: cn.itcast.order.pojo
configuration:
map-underscore-to-camel-case: true
logging:
level:
cn.itcast: debug
pattern:
dateformat: MM-dd HH:mm:ss:SSS
|--mapper
|-- OrderMapper
package cn.itcast.order.mapper;

import cn.itcast.order.pojo.Order;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

/**

  • 订单持久层
    *
  • @author
  • @date 2022-12-22 14:22
    */
    public interface OrderMapper {

    /**

    • 根据ID查找订单
    • @param id 订单ID
    • @return 订单对象
      /
      @Select("select
      from tb_order where id=#{id}")
      Order findById(@Param("id")Long id);
      }

|--pojo
|-- Order
package cn.itcast.order.pojo;

import lombok.Data;

/**

  • 订单实体(vo并非dto)
    *
  • @author
  • @date 2022-12-22 14:19
    */
    @Data
    public class Order {

    /**

    • 主键ID
      */
      private Long id;

      /**

    • 用户主键ID
      */
      private Long userId;

      /**

    • 商品名称
      */
      private String name;

      /**

    • 商品价格
      */
      private Long price;

      /**

    • 商品数量
      */
      private Integer num;

      /**

    • 用户信息
      */
      private User user;
      }

|-- User
package cn.itcast.order.pojo;

import lombok.Data;

/**

  • 用户实体
    *
  • @author
  • @date 2022-12-22 14:07
    */
    @Data
    public class User {

    /**

    • 主键ID
      */
      private Long id;

      /**

    • 用户姓名
      */
      private String username;

      /**

    • 用户地址
      */
      private String address;
      }

|--service
|-- OrderService
package cn.itcast.order.service;

import cn.itcast.order.mapper.OrderMapper;
import cn.itcast.order.pojo.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**

  • 订单业务层
    *
  • @author
  • @date 2022-12-22 14:24
    */
    @Service
    public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    /**

    • 根据ID查找订单
    • @param id 订单ID
    • @return 订单对象
      */
      public Order findById(Long id) {
      Order order = orderMapper.findById(id);
      return order;
      }
      }

|--web
|-- OrderController
package cn.itcast.order.web;

import cn.itcast.order.pojo.Order;
import cn.itcast.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**

  • 订单控制层
    *
  • @author
  • @date 2022-12-22 14:25
    */
    @RestController
    @RequestMapping("/order")
    public class OrderController {

    @Autowired
    private OrderService orderService;

    /**

    • 根据ID查找订单
    • @param orderId 订单ID
    • @return 订单对象
      */
      @GetMapping("/{orderId}")
      public Order findById(@PathVariable("orderId")Long orderId) {
      return orderService.findById(orderId);
      }
      }

|--OrderApplication
package cn.itcast.order;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**

  • 启动类
    *
  • @author
  • @date 2022-12-22 14:05
    */
    @MapperScan("cn.itcast.order.mapper")
    @SpringBootApplication
    public class OrderApplication {

    public static void main(String[] args) {

     SpringApplication.run(OrderApplication.class, args);
     System.out.println("订单工程启动成功");
    

    }
    }

2.数据库导入

● 需参见上图新建两个数据库,然后导入DDL语句


导完如下

3.项目启动
3.1 启动并访问user-service

3.2 启动并访问order-service

观察发现,虽然order-service服务调用成功,但是里面的user对象却是空的。原因我们应该也可以了解到是因为User对象数据数存储在数据库:tb_user,而此工程连接数据库是:tb_order,查询此数据库时无法获取对应的User数据,怎么获取?获取的具体实现我们将在下一章节进一步铺开。
4.服务远程调用
分析现有链路调用关系可以发现:
http://localhost:8081/user/{id} 可以获取用户信息
http://localhost:8081/order/{orderId} 可以获取订单信息,但是用户信息为空
想要订单信息中返回用户信息,只要在获取订单链路中追加对用户信息的获取、返回值的组装即可,由此引申出微服务之间的远程服务调用,具体调整可见下图。

时序图说明
上述图形为时序图,一般用来描述系统与系统之间的交互流程,主要是交互API、代码顺序、参数一般忽略,时序图不同于业务流程,更关注业务实现过程中系统前后依赖,数据请求与返回,以下为笔者实际工作场景示例:

服务远程调用实现
注入RestTemplate
此处推荐一个小的优雅工具:https://carbon.now.sh/

RestTemplate完成远程服务调用
在此笔者除了完成远程服务调用,同时对代码做了结构化、异常校验、函数封装。虽然此处逻辑并不复杂,但是对于主干逻辑简化和代码风格,希望能起到一个引导作用。
package cn.itcast.order.service;

import cn.itcast.order.mapper.OrderMapper;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Objects;

/**

  • 订单业务层
    *
  • @author
  • @date 2022-12-22 14:24
    */
    @Service
    public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RestTemplate restTemplate;

    /**

    • 根据ID查找订单
    • @param id 订单ID
    • @return 订单对象
      */
      public Order findById(Long id) {

      // step 1 : 查询订单原始数据
      Order order = orderMapper.findById(id);
      if (Objects.isNull(order)) {

       return null;
      

      }

      // step 2 : 查询用户数据
      User user = queryUserInfoById(order.getUserId());

      // step 3 : 组装用户数据
      if (Objects.nonNull(user)) {

       order.setUser(user);
      

      }

      // step 4: 数据返回
      return order;
      }

      /**

    • 根据用户ID查找用户信息
    • @param userId 用户ID
    • @return 用户信息
      */
      private User queryUserInfoById(Long userId) {
      String url = "http://localhost:8081/user/" + userId;
      return restTemplate.getForObject(url, User.class);
      }
      }
      重启并访问order-service

RestTemplate如何实现远程服务调用

5.总结
本节笔者带领大家完成了SpringCloud工程从0->1的搭建,当然你不想搭建也可以直接采用方案一,二者等效,至此读者们完成了一个微服务工程的搭建、部署、访问。同时在本节最后一章,笔者基于RestTemplate发起的http请求实现远程调用,实现当A系统想要获取B系统数据时的跨系统数据交互。然而RESTful API(进一步了解可移步:链接)访问并不是微服务的唯一解决方案,如Dubbo的交互一样可以实现,希望读者们能不限于此。
在本章节,笔者希望大家对于微服务的拆分,服务调用关系有个初步认知,本例中当order-service调用user-service时,前者就充当了服务调用方,后者则是服务提供方,这种调用关系在后续我们将会大量使用。

相关文章
|
4月前
|
负载均衡 算法 Java
【SpringCloud(3)】Ribbon负载均衡:IRule原理轮询算法;LB负载均衡;loadbalancer和IRule组件;Ribbon和Ngin负载均衡的区别
Spring Cloud Ribbon 是基于Netflix Ribbon实现的一套客户端的负载均衡工具 简单地说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时、重试等。就在在配置文件中列出Load Balancer(LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机链接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法
502 136
|
2月前
|
XML Java 数据库
SpringCloud工程部署启动
本文介绍SpringCloud微服务工程的搭建与部署,涵盖项目创建、模块配置、数据库导入及服务远程调用实现。通过RestTemplate完成服务间HTTP通信,解决跨服务数据获取问题,并引导读者理解微服务拆分与调用关系,为后续深入学习奠定基础。(239字)
 SpringCloud工程部署启动
|
4月前
|
负载均衡 算法 Java
【SpringCloud(2)】微服务注册中心:Eureka、Zookeeper;CAP分析;服务注册与服务发现;单机/集群部署Eureka;连接注册中心
1. 什么是服务治理? SpringCloud封装了Netfix开发的Eureka模块来实现服务治理 在传统pc的远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册
349 1
|
2月前
|
存储 安全 Java
Java HashMap 全面解析:原理、用法与实战要点
本文深入解析Java中HashMap的底层原理与使用实践,涵盖其“数组+链表+红黑树”的结构演变、哈希计算、扩容机制及线程安全问题,详解常用方法、性能优化与最佳实践,助力开发者高效掌握这一核心数据结构。
387 10
|
7月前
|
存储 缓存 NoSQL
分布式锁
分布式锁是分布式系统中实现跨节点资源互斥访问的关键机制,常用于解决多进程、多机器环境下的并发控制问题。它依赖外部存储(如Redis、ZooKeeper)协调锁状态,确保全局唯一性和原子性操作。常见实现包括基于Redis的单点锁与RedLock算法、ZooKeeper的临时顺序节点及数据库唯一索引。适用于任务调度、缓存重建和库存管理等场景。设计时需关注可重入性、锁超时、续租及异常处理,并权衡性能与可靠性。
261 0
|
缓存 Java
异步&线程池 线程池的七大参数 初始化线程的4种方式 【上篇】
这篇文章详细介绍了Java中线程的四种初始化方式,包括继承Thread类、实现Runnable接口、实现Callable接口与FutureTask结合使用,以及使用线程池。同时,还深入探讨了线程池的七大参数及其作用,解释了线程池的运行流程,并列举了四种常见的线程池类型。最后,阐述了在开发中使用线程池的原因,如降低资源消耗、提高响应速度和增强线程的可管理性。
异步&线程池 线程池的七大参数 初始化线程的4种方式 【上篇】
|
存储 缓存 监控
【JVM调优】如何进行JVM调优?一篇文章就够了!
深入解读JVM性能的监控、定位和调优方案,阐述jps/stat/jstack、MAT等常用性能分析工具的使用,提出JVM参数、内存溢出、内存泄漏、CPU飙升、GC频繁等实际场景下JVM调优的方案。
【JVM调优】如何进行JVM调优?一篇文章就够了!
|
Java 数据库连接 数据库
Spring基础3——AOP,事务管理
AOP简介、入门案例、工作流程、切入点表达式、环绕通知、通知获取参数或返回值或异常、事务管理
Spring基础3——AOP,事务管理
|
存储
​SpringSecurity-7-自定义AuthenticationProvider实现图形验证码
上一章节我们介绍了如何使用过滤器(Filter)实现图形验证,这是属于Servlet层面,比较简单容易理解。那么这次我们介绍SpringSecurity提供的另一种比较高端的实现图形化验证码,这就是AuthenticationProvider自定义认证。
431 0
|
存储 算法 安全
详细解读CA认证原理以及实现(上)
详细解读CA认证原理以及实现(上)
441 1