微服务项目(mybatis与微服务注册)

news2024/11/16 6:03:51

目录

一、SpringBoot整合MybatisPlus

创建自动生成代码子模块

 创建商品服务子模块

 二、SpringBoot整合

Freeamarker

 三、SpringBoot整合微服务&gateway&nginx

整合微服务之商品服务zmall-product

创建并配置网关gateway服务

安装配置SwitchHosts

 安装配置Windows版nginx

请求链路测试


一、SpringBoot整合MybatisPlus

创建自动生成代码子模块

基于maven方式创建子模块zmall-generator,用于结合mybatis-plus生成代码

在公共模块zmall-common中注释掉mybatis的依赖引入,改换成mybatis-plus依赖引入

<!-- mybatis plus依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.0</version>
</dependency>

在zmall-generator中引入mybatis-plus-generator依赖,该模块专用于mybatis-plus的代码生成,所以单独在此引入该依赖即可

<!-- mybatis-plus-generator依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.0</version>
</dependency>

在src/main/resources下创建templates目录,并导入mybatis-generator生成代码模板页

在src/main/java下创建包com.zking.zmall,并导入generator下的CodeGenerator类用于代码生成

 修改CodeGenerator类基本生成参数,并生成代码

//数据库连接参数
public static String driver = "com.mysql.jdbc.Driver";
public static String url = "jdbc:mysql://localhost:3306/zmall?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true";
public static String username="root";
public static String password="123456";
//父级别包名称
public static String parentPackage = "com.zking.zmall";
//项目名设置(如果是SpringCloud项目则需要设置,其他为""即可)
public static String projectName="/zmall-generator";
//代码生成的目标路径
public static String generateTo = "/src/main/java";
//mapper.xml的生成路径
public static String mapperXmlPath = "/src/main/resources/mapper";
//控制器的公共基类,用于抽象控制器的公共方法,null值表示没有父类
public static String baseControllerClassName ;
//业务层的公共基类,用于抽象公共方法
public static String baseServiceClassName ;
//作者名
public static String author = "zking";
//模块名称,用于组成包名
public static String modelName = "model";

注意:

  • 修改数据库连接URL中的数据库名、数据库账号和密码;
  • 修改父级别包名称
  • 修改项目名,如果是SpringCloud项目则修改,不是则默认

先后生成

zmall_product_category,zmall_product

 创建商品服务子模块

基于Spring Initializr方式创建商品服务模块zmall-product

 在主模块pom.xml中加入商品服务子模块zmall-product

<modules>
    <module>zmall-common</module>
    <module>zmall-user</module>
    <module>zmall-generator</module>
    <module>zmall-product</module>
</modules>

配置商品服务子模块zmall-product的application.yml配置文件

server:
  port: 8020
spring:
  application:
    name: zmall-product
  datasource:
    #type连接池类型 DBCP,C3P0,Hikari,Druid,默认为Hikari
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/zmall?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
    username: root
    password: 1234
  freemarker:
    suffix: .html
    template-loader-path: classpath:/templates/
#mybatis-plus配置
mybatis-plus:
  #所对应的 XML 文件位置
  mapper-locations: classpath*:/mapper/*Mapper.xml
  #别名包扫描路径
  type-aliases-package: com.zking.zmall.model
  configuration:
    #驼峰命名规则
    map-underscore-to-camel-case: true
#日志配置
logging:
  level:
    com.zking.zmall.mapper: debug

在商品服务子模块中启动类上添加

@SpringBootApplication
@MapperScan({"com.zking.zmall.mapper"})
public class ZmallProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZmallProductApplication.class, args);
    }
}

将公共子模块中生成的service层代码复制到商品服务子模块zmall-product中,并删除掉非商品相关的service接口及实现类

创建junit实现接口测试

zmall-common模块

<!--        用于test目录下的测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

 测试类

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest
    public class ProductServiceImplTest {
    
        @Autowired
        private IProductService productService;
    
        @Before
        public void setUp() throws Exception {
        }
    
        @After
        public void tearDown() throws Exception {
        }
    
        @Test
        public void queryProduct() {
            List<Product> list = productService.list();
            list.forEach(System.out::println);
        }
    }

运行结果

 二、SpringBoot整合

Freeamarker

在公共模块zmall-common中引入freemarker依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

在商品子模块zmall-product中添加首页和商品详情页面及公共资源(js/css/images)

将资料目录中的《易买网网页素材.rar》解压后,将其中Index.html、Product.html和js/css/images等等添加到项目的templates和static目录下,最好请将Index.html、Product.html页面首字母改成小写

导入资料目录中的common目录到项目的templates目录下

 将页面中的头部申明<!DOCTYPE html ....>修改成<!DOCTYPE html>(支持H5风格)

在页面中通过<#include>指令引入common目录中的head.html

创建ProductController定义请求方法

package com.zking.zmall.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zking.zmall.model.Product;
import com.zking.zmall.service.IProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
public class ProductController {

    @Autowired
    private IProductService productService;

    @RequestMapping("/index.html")
    public String index(Model model){
        //按照商品的销量降序排序获取销量排名Top5的商品
        List<Product> products = productService.list(new QueryWrapper<Product>()
                .orderByDesc("hot")
                .last("limit 5"));
        model.addAttribute("hots",products);
        return "index";
    }

    @RequestMapping("/product.html")
    public String detail(Model model,Integer pid){
        //根据商品ID查询商品详情信息
        Product product = productService.getById(pid);
        model.addAttribute("product",product);
        return "product";
    }
}

在index.html中绑定热门数据和product.html中绑定商品详情数据

index.html

<ul class="featureUL">
                                <#--判断hots是否为空-->
                                <#if hots??>
                                <#--循环遍历热销商品-->
                                    <#list hots as it>
                                        <li class="featureBox">
                                            <div class="box">
                                                <div class="h_icon"><img src="images/hot.png" width="50" height="50" /></div>
                                                <div class="imgbg">
                                                    <a href="../product.html?pid=${(it.id)!}"><img src="${(it.fileName)!}" width="160" height="136" /></a>
                                                </div>
                                                <div class="name">
                                                    <a href="../product.html?pid=${(it.id)!}">
                                                        <#-- <h2>德国进口</h2>-->
                                                        ${(it.name)!}
                                                    </a>
                                                </div>
                                                <div class="price">
                                                    <font>¥<span>${(it.price)!}</span></font>   26R
                                                </div>
                                            </div>
                                        </li>
                                    </#list>
                                </#if>
                            </ul>

product.html

<div class="content">

        <div id="tsShopContainer">
            <div id="tsImgS"><a href="${(product.fileName)!}" title="Images" class="MagicZoom" id="MagicZoom"><img src="${(product.fileName)!}" width="390" height="390" /></a></div>
            <div id="tsPicContainer">
                <div id="tsImgSArrL" onclick="tsScrollArrLeft()"></div>
                <div id="tsImgSCon">
                    <ul>
                        <li onclick="showPic(0)" rel="MagicZoom" class="tsSelectImg"><img src="images/ps1.jpg" tsImgS="images/ps1.jpg" width="79" height="79" /></li>
                        <li onclick="showPic(1)" rel="MagicZoom"><img src="images/ps2.jpg" tsImgS="images/ps2.jpg" width="79" height="79" /></li>
                        <li onclick="showPic(2)" rel="MagicZoom"><img src="images/ps3.jpg" tsImgS="images/ps3.jpg" width="79" height="79" /></li>
                        <li onclick="showPic(3)" rel="MagicZoom"><img src="images/ps4.jpg" tsImgS="images/ps4.jpg" width="79" height="79" /></li>
                        <li onclick="showPic(4)" rel="MagicZoom"><img src="images/ps1.jpg" tsImgS="images/ps1.jpg" width="79" height="79" /></li>
                        <li onclick="showPic(5)" rel="MagicZoom"><img src="images/ps2.jpg" tsImgS="images/ps2.jpg" width="79" height="79" /></li>
                        <li onclick="showPic(6)" rel="MagicZoom"><img src="images/ps3.jpg" tsImgS="images/ps3.jpg" width="79" height="79" /></li>
                        <li onclick="showPic(7)" rel="MagicZoom"><img src="images/ps4.jpg" tsImgS="images/ps4.jpg" width="79" height="79" /></li>
                    </ul>
                </div>
                <div id="tsImgSArrR" onclick="tsScrollArrRight()"></div>
            </div>
            <img class="MagicZoomLoading" width="16" height="16" src="images/loading.gif" alt="Loading..." />
        </div>

        <div class="pro_des">
            <div class="des_name">
                <p>${(product.name)!}</p>
                “开业巨惠,北京专柜直供”,不光低价,“真”才靠谱!
            </div>
            <div class="des_price">
                本店价格:<b>¥${(product.price)}</b><br />
                消费积分:<span>28R</span>
            </div>
            <div class="des_choice">
                <span class="fl">型号选择:</span>
                <ul>
                    <li class="checked">30ml<div class="ch_img"></div></li>
                    <li>50ml<div class="ch_img"></div></li>
                    <li>100ml<div class="ch_img"></div></li>
                </ul>
            </div>
            <div class="des_choice">
                <span class="fl">颜色选择:</span>
                <ul>
                    <li>红色<div class="ch_img"></div></li>
                    <li class="checked">白色<div class="ch_img"></div></li>
                    <li>黑色<div class="ch_img"></div></li>
                </ul>
            </div>
            <div class="des_share">
                <div class="d_sh">
                    分享
                    <div class="d_sh_bg">
                        <a href="#"><img src="images/sh_1.gif" /></a>
                        <a href="#"><img src="images/sh_2.gif" /></a>
                        <a href="#"><img src="images/sh_3.gif" /></a>
                        <a href="#"><img src="images/sh_4.gif" /></a>
                        <a href="#"><img src="images/sh_5.gif" /></a>
                    </div>
                </div>
                <div class="d_care"><a onclick="ShowDiv('MyDiv','fade')">关注商品</a></div>
            </div>
            <div class="des_join">
                <div class="j_nums">
                    <input type="text" value="1" name="" class="n_ipt" />
                    <input type="button" value="" onclick="addUpdate(jq(this));" class="n_btn_1" />
                    <input type="button" value="" onclick="jianUpdate(jq(this));" class="n_btn_2" />
                </div>
                <span class="fl"><a onclick="ShowDiv_1('MyDiv1','fade1')"><img src="images/j_car.png" /></a></span>
            </div>
        </div>

        <div class="s_brand">
            <div class="s_brand_img"><img src="images/sbrand.jpg" width="188" height="132" /></div>
            <div class="s_brand_c"><a href="#">进入品牌专区</a></div>
        </div>


    </div>

效果图

 

 三、SpringBoot整合微服务&gateway&nginx

 请求链路要求:客户端发送请求先经过nginx,再用nginx转至内部访问网关gateway,最后由网关服务的路由规则转发到微服务的内部服务

整合微服务之商品服务zmall-product

在公共模块zmall-common中导入微服务相关依赖

<!--nacos客户端-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<!--fegin组件-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<!--nacos配置中心-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

配置商品服务模块zmall-product的application.yml文件

spring:
  application:
    name: zmall-product
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

修改启动类,向nacos进行注册

@EnableDiscoveryClient
@SpringBootApplication
@MapperScan({"com.zking.zmall.mapper"})
public class ZmallProductApplication {

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

创建并配置网关gateway服务

基于Spring initializr方式创建网关模块zmall-gateway

配置pom.xml添加nacos和gateway的依赖

<modelVersion>4.0.0</modelVersion>
<parent>
        <groupId>com.zking.zmall</groupId>
        <artifactId>zmall</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
<artifactId>zmall-gateway</artifactId>
<dependencies>
    <!--gateway 注意 此模式不能引入starter-web -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

    <!--nacos客户端-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>    
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
    </dependency>
</dependencies>

修改启动类,向nacos进行注册

@EnableDiscoveryClient
@SpringBootApplication
public class ZmallGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZmallGatewayApplication.class, args);
    }
}

配置application.yml设置gateway路由转发规则

server:
  port: 8000
spring:
  application:
    name: zmall-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      routes:
        - id: product_route
          uri: lb://zmall-product # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
          predicates:
            - Path=/product-serv/**
          filters:
            - StripPrefix=1

将易买网网页素材中的公共静态资源js/css/images复制到gateway网关服务中

这里请注意了,之前在商品服务模块zmall-product中已经配置了易买网的静态资源,为什么还要在gateway网关服务中再配置一次呢?这是因为当请求经过gateway网关服务后会进行断言条件匹配和条件路径截取等操作,从而导致gateway网关路由转发后静态资源失效404的问题,所以特此在gateway网关服务中也配置一次易买网网页素材中的公共静态资源js/css/images,确保能正常访问

安装配置SwitchHosts

直接双击exe文件即可安装SwitchHosts

 进入C:\Windows\System32\drivers\etc目录,设置hosts文件访问权限并取消只读模式

 安装配置Windows版nginx

解压nginx-1.18.0.zip至任意目录

进入conf目录,并修改nginx.conf配置文件

server
{
    listen 80;
    server_name zmall.com;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    location / {
        proxy_pass http://127.0.0.1:8000/;
    }
}

最后运行nginx根目录下的nginx.exe启动nginx

如果出现IIS7

那么cmd窗口中执行下列指令

net stop w3svc

请求链路测试

单独访问商品服务:http://localhost:8020/index.html

通过gateway访问:http://localhost:8000/product-serv/index.html

通过nginx访问:http://zmall.com/product-serv/index.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/339982.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SpringBoot+Vue的疫苗预约管理系统(Java项目)

【辰兮要努力】&#xff1a;hello你好我是辰兮&#xff0c;很高兴你能来阅读&#xff0c;昵称是希望自己能不断精进&#xff0c;向着优秀程序员前行&#xff01; 博客来源于项目以及编程中遇到的问题总结&#xff0c;偶尔会有读书分享&#xff0c;我会陆续更新Java前端、后台、…

RabbitMQ详解(一):RabbitMQ相关概念

RabbitMQ是目前非常热门的一款消息中间件&#xff0c;不管是互联网大厂还是中小企业都在大量使用。作为一名合格的开发者&#xff0c;有必要对RabbitMQ有所了解&#xff0c;本系列是RabbitMQ快速入门文章&#xff0c;主要内容包括RabbitMQ是什么、RabbitMQ核心概念、五种消息模…

设备管理(7)

设备管理 1 I/O硬件组成 设备的类型&#xff1a; 块设备&#xff1a;如&#xff1a;磁盘、磁带&#xff0c;块大小512B~32KB&#xff0c;通常为512B。块设备的特点是速度高、随机访问、I/O采用DMA。字符设备&#xff1a;如&#xff1a;键盘、行式打印机。特点是速度低、不可寻…

河道治理漂浮物识别监测系统 yolov7

河道治理漂浮物识别监测系统通过yolov7网络模型深度视觉分析技术&#xff0c;河道治理漂浮物识别监测算法模型实时检测着河道水面是否存在漂浮物、水浮莲以及生活垃圾等&#xff0c;识别到河道水面存在水藻垃圾等漂浮物&#xff0c;立即抓拍存档预警。You Only Look Once说的是…

LeetCode 1138. 字母板上的路径

【LetMeFly】1138.字母板上的路径 力扣题目链接&#xff1a;https://leetcode.cn/problems/alphabet-board-path/ 我们从一块字母板上的位置 (0, 0) 出发&#xff0c;该坐标对应的字符为 board[0][0]。 在本题里&#xff0c;字母板为board ["abcde", "fghij…

66 使用注意力机制的seq2seq【动手学深度学习v2】

66 使用注意力机制的seq2seq【动手学深度学习v2】 深度学习学习笔记 学习视频&#xff1a;https://www.bilibili.com/video/BV1v44y1C7Tg/?spm_id_from…top_right_bar_window_history.content.click&vd_source75dce036dc8244310435eaf03de4e330 在机器翻译时&#xff0c;…

指针引用字符串问题(详解)

通过指针引用字符串可以更加方便灵活的使用字符串。 字符串的引用方式有两种&#xff0c;下面简单介绍一下这两种方法。 1.用字符数组来存放一个字符串。 1.1 可以通过数组名和下标来引用字符串中的一个字符。 1.2 还可以通过数组名和格式声明符%s输出整个字符串。 具体实…

【项目精选】百货中心供应链管理系统

点击下载源码 近年来&#xff0c;随着计算机技术的发展&#xff0c;以及信息化时代下企业对效率的需求&#xff0c;计算机技术与通信技术已经被越来越多地应用到各行各业中去。百货中心作为物流产业链中重要的一环&#xff0c;为了应对新兴消费方式的冲击&#xff0c;从供货到销…

第五十二章 BFS进阶(二)——双向广搜

第五十二章 BFS进阶&#xff08;二&#xff09;——双向广搜一、双向广搜1、优越之处2、实现逻辑3、复杂度分析二、例题1、问题2、分析3、代码一、双向广搜 1、优越之处 双向广搜是指我们从终点和起点同时开始搜索&#xff0c;当二者到达同一个中间状态的时候&#xff0c;即相…

Python __all__变量用法

事实上&#xff0c;当我们向文件导入某个模块时&#xff0c;导入的是该模块中那些名称不以下划线&#xff08;单下划线“_”或者双下划线“__”&#xff09;开头的变量、函数和类。因此&#xff0c;如果我们不想模块文件中的某个成员被引入到其它文件中使用&#xff0c;可以在其…

【算法题解】15. 设计最小栈

这是一道 中等难度 的题。 题目来自&#xff1a;leetcode 题目 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在 常数时间 内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void p…

C语言-重点知识总结-建议收藏(完结)

一图带你梳理C语言重点知识。图片解析&#xff1a;这张图从C语言初阶开始&#xff0c;一直讲解到C语言进阶的知识。在C语言初阶&#xff1a;从初识C语言开始学习&#xff1a;初识C语言带你进入C语言的大门&#xff0c;了解C语言的魅力。然后为你讲解C语言的基本语法&#xff1a…

软件测试只会“点点点”,凭什么让开发看的起你?

众所周知&#xff0c;如今无论是大厂还是中小厂&#xff0c;自动化测试基本是标配了&#xff0c;毕竟像双 11、618 这种活动中庞大繁杂的系统&#xff0c;以及多端发布、多版本、机型发布等需求&#xff0c;但只会“写一些自动化脚本”很难胜任。这一点在招聘要求中就能看出来。…

开源代码的寿命为何只有1年?

说实话&#xff0c;如果古希腊的西西弗斯是一个在2016年编写开源代码的开发者&#xff0c;那他会有宾至如归的感觉。著名的西西弗斯处罚&#xff0c;是神话流传下来的&#xff0c;他被迫推一块巨大的石头上山&#xff0c;当登顶之后&#xff0c;只能眼睁睁看着它滚下去&#xf…

国内唯一一部在CentOS下正确编译安装和使用RediSearch的教程

开篇 Redis6开始增加了诸多激动人心的模块&#xff0c;特别是&#xff1a;RedisJSON和RediSearch。这两个模块已经完全成熟了。它们可以直接使用我们的生产上的Redis服务器来做全文搜索&#xff08;二级搜索&#xff09;以取得更廉价的硬件成本、同时在效率上竟然超过了Elastic…

基于人工大猩猩部队优化CNN-LSTM(GTO-CNN-LSTM)多变量时间序列预测(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

移动测试相关

一、环境搭建 准备工作&#xff1a; &#xff08;python、pycharm安装配置好&#xff09; 1、Java SDK 安装配置 Java Downloads | Oracle 下载安装后配置系统环境变量&#xff1a;JAVA_HOME&#xff08;jdk根目录路径&#xff09;和path&#xff08;jdk根目录下的bin目录路径…

opencv的环境搭建

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…

CV——day75 读论文:基于差分特征融合CNN的轨道交通目标检测

Differential feature fusion convolutional neural network基于差分特征融合CNN的轨道交通目标检测I. INTRODUCTIONII. RELATED WORKSIII. NETWORK ARCHITECTUREA. Prior Detection ModuleB. Object-Detection ModuleV. CONCLUSION基于差分特征融合CNN的轨道交通目标检测 基于…

数据仓库层Repository(CrudRepository、PagingAndSortingRepository、JpaRepository)

什么是数据仓库层Repository&#xff1f; 数据仓库接口的作用&#xff1a;Repository原意指的是仓库&#xff0c;即数据仓库的意思。Repository居于业务层和数据层之间&#xff0c;将两者隔离开来&#xff0c;在它的内部封装了数据查询和存储的逻辑。 Repository接口&#xff…