当前位置: 首页 > news >正文

【云岚到家】-day01-项目熟悉-查询区域服务开发

文章目录

  • 1 云岚家政项目概述
    • 1.1 简介
    • 1.2 项目业务流程
    • 1.3 项目业务模块
    • 1.4 项目架构及技术栈
    • 1.5 学习后掌握能力
  • 2 熟悉项目
    • 2.1 熟悉需求
    • 2.2 熟悉设计
      • 2.2.1 表结构
      • 2.2.2 熟悉工程结构
      • 2.2.3 jzo2o-foundations
        • 2.2.3.1 工程结构
        • 2.2.3.2 接口测试
  • 3 开发区域服务模块
    • 3.1 流程分析
    • 3.2 查询区域服务
      • 3.2.1 梳理接口
      • 3.2.2 接口设计
        • 3.2.2.1 接口文档
        • 3.2.2.2 HTTP请求方法
        • 3.2.2.3 接口路径
        • 3.2.2.4 请求参数类型
        • 3.2.2.5 请求参数内容
        • 3.2.2.6 响应结果类型
        • 3.2.2.7 响应结果状态码
        • 3.2.2.8 响应结果内容
      • 3.2.3 接口定义
        • 3.2.3.1 编写controller
          • 3.2.3.1.1 基础注释
          • 3.2.3.1.2 分页controller中实现
        • 3.2.3.2 编写mapper
          • 3.2.3.2.1 mapper代码生成工具
          • 3.2.3.2.2 分页mapper开发
          • 3.2.3.2.3 针对mapper的单元测试
          • 3.2.3.2.4 @Resource 和 @Autowired有什么区别?
        • 3.2.3.3 编写service
          • 3.2.3.3.1 单元测试
          • 3.2.3.3.2 PageHelper原理
        • 3.2.3.4 controller测试
        • 3.2.3.5 前后端联调


1 云岚家政项目概述

1.1 简介

云岚到家项目是一个家政服务o2o平台,互联网+家政是继打车、外卖后的又一个风口,创业者众多,比如:58到家,天鹅到家等,o2o(Online To Offline)是将线下商务的机会与互联网的技术结合在一起,让互联网成为线下交易的前台,同时起到推广和成交的作用。

C2B2C:

在家政 O2O(Online to Offline,线上到线下)领域中,“Consumer to Business to Consumer”(C2B2C)描述了一个商业模式,消费者不仅可以通过平台获取家政服务,还有机会成为服务提供者。在这个背景下,C2B2C 模式通常指的是:

  1. 消费者(Consumer):
  • 最终的家庭用户,他们需要家政服务,例如清洁、保姆、维修等。
  1. 企业(Business):
  • 在家政 O2O 中,企业通常是在线平台,提供家政服务的中介。这些平台通过在线渠道为消费者提供了查找、预订、支付等服务,同时也可能为家政服务提供者提供了工作机会。
  1. 消费者(家政服务提供者):
  • 在 C2B2C 模式中,一些消费者也可以成为服务的提供者。这些个体可能是独立的家政服务专业人员,他们可以在家政 O2O 平台上注册,提供自己的服务,并被其他需要服务的消费者雇佣。

B2B2C:

代表着"Business to Business to Consumer",即企业到企业到消费者的模式。家政服务平台作为中间商,通过与各种家政服务提供商(家政服务公司)合作,为消费者提供多样化的家政服务选择。

B2B2C与C2B2C的区别是:B2B2C中服务提供者是家政服务中介公司,在C2B2C中是服务提供者是拥有服务技能的服务人员(散户)。

本项目结合了C2B2C和B2B2C模式,个人和家政服务中介都可以通过平台提供家政服务,如下图:

项目包括四个端:用户端(小程序)、服务端(app)、机构端(PC)、运营管理端(PC),四个端对应四类用户角色:

家政需求方:通过用户端小程序完成在线预约下单、支付、评价、投诉、退款等操作。

家政服务人员:通过服务端APP完成在线接单、结算等操作。

家政服务公司:通过机构端完成在线接单、派单、投诉处理、结算等操作。

平台方:通过管理端完成服务人员管理、机构管理、订单管理、财务管理等操作,一笔完成的订单,结算时按照分成比例平台进行抽成。

1.2 项目业务流程

在这里插入图片描述

核心流程:

  1. 运营端在运营区域上架家政服务

比如:在北京上架 日常保洁、空调维修。

  1. 用户端通过定位区域获取当前区域的服务项目,选择家政服务,下单、支付

  2. 家政服务人员及家政服务公司(机构)通过平台抢单

  3. 家政服务人员现场服务,平台跟踪管理整个服务过程。

  4. 服务完成,用户评价、售后服务等。

1.3 项目业务模块

在这里插入图片描述

我们根据业务流程去分析各个模块的功能:

服务管理:对家政服务项目进行管理,最后在指定区域上架服务后用户可在当前区域购买。

下单支付:用户通过小程序完成下单支付,进入小程序首页查询服务,用户选择服务,下单并支付

抢单:服务人员和机构进行抢单。首先服务人员和机构设置接单范围、服务技能、开启抢单开关,然后进入抢单界面进行抢单。

派单调度:平台根据撮合匹配算法通过任务调度将订单和服务人员进行撮合匹配,促进成交。

订单管理:对订单的生命周期进行管理,包括创建订单、取消订单、删除订单、历史订单等。

服务人员管理:对服务人员的信息、认证等进行管理。

企业管理:对机构的信息、认证进行管理。

客户管理:对c端用户的信息、用户的状态等信息进行管理。

营销管理:对优惠券活动进行管理。

1.4 项目架构及技术栈

项目是基于Spring Cloud Alibaba框架构建的微服务项目,采用前后端分离模式进行开发,系统架构图如下

在这里插入图片描述

  • 用户层:

    包括四个端:运营端(PC)、服务端(APP)、机构端(PC)、用户端(小程序)

  • 负载层:

    反向代理、负载均衡。

  • 服务层:包括网关、业务微服务、基础服务。

    业务微服务:包括运营基础服务、客户管理服务、订单管理服务、抢单服务、派单服务、支付服务等。

    基础服务:Nacos(服务注册、配置中心)、XXL-JOB(任务调度)、RabbitMQ(消息队列)、Elasticsearch(全文检索)、Canal(数据同步)、Sentinel(熔断降级、限流)等。

  • 数据层:

    MySQL数据库存储:服务信息、区域信息、客户信息、订单信息、支付信息、抢单池、派单池、结算信息等。

    分库分表:使用ShardingShphere进行分库分表。

    TiDB分布式数据库存储:历史订单信息。

    消息队列:存储数据同步消息、各类异步消息等。

    索引:服务信息、服务提供者信息、订单信息等。

    缓存:服务信息、订单信息、服务单信息等。

项目核心交互流程如下图:

在这里插入图片描述

1.5 学习后掌握能力

掌握项目需求分析能力
掌握系统分析与设计的能力
掌握Spring Cloud 在项目中的开发与调优能力
掌握Redis在项目中的应用能力
掌握缓存技术方案的分析与设计能力
掌握Canal+MQ异构数据同步的开发调试能力
掌握Elasticsearch全文检索与地理搜索的开发能力
掌握ShardingSphere分库分表的方案设计与开发能力
掌握Seata分布式事务控制的开发能力
掌握数据冷热分离技术方案的设计与开发能力
掌握XXL-JOB+线程池任务调度方案的设计与开发能力
掌握系统调优与线上故障处理的能力
掌握状态机组件的设计与开发能力

掌握门户业务的设计与开发能力
掌握订单支付业务的系统设计与开发能力
掌握优惠券&活动管理业务的系统设计与开发能力
掌握秒杀抢购业务的常见设计方案与开发能力
掌握派单调度类业务的系统设计与开发能力
掌握客户管理业务的系统设计与开发能力
掌握活动管理业务的系统设计与开发能力
掌握搜索附近业务的系统设计与开发能力
掌握服务管理&商品管理业务的系统计与开发能力
掌握统计分析与看板业务的系统设计与开发能力

2 熟悉项目

2.1 熟悉需求

目标:阅读需求文档,理解基本概念和业务流程。

在这里插入图片描述

1-4已经开发的差不多了,模拟实际公司的业务环节,我们需要新开发5,添加对区域服务管理的开发。

2.2 熟悉设计

理解运营基本管理模块的表结构,熟悉工程结构,能够对接口进行断点调试。

2.2.1 表结构

根据需求熟悉本模块的核心表,如下图:

在这里插入图片描述

serve_type:服务类型表(家电清洗)

serve_item: 服务项表,存储了本平台的家政服务项目(家电清洗的具体项目,如洗衣机清洗,空调清洗等等)

每个服务项都有一个服务类型,一个服务类型下有多个服务项,服务类型与服务项是一对多关系。

region:区域表,存储运营地区信息,一般情况区域表行政级别是市。

serve: 服务表,存储了各个区域运营的服务及相关信息。(直接与用户/运营相关)

注意:这里不要把serve表简单理解为只是区域表和服务项表的中间关系表,因为如果是简单的关联关系表只需记录区域表和服务项表各自的主键Id即可,serve记录的是平台运营服务的信息,凡是与运营相关的信息都要记录在serve表,比如:运营价格。后期也可能会增加其它运营相关的字段。

注意:

  • region与serve_item是什么关系?

    一个区域下可以设置多个服务项,一个服务项可以被多个区域设置,region与serve_item是多对多关系。

2.2.2 熟悉工程结构

在这里插入图片描述

2.2.3 jzo2o-foundations

2.2.3.1 工程结构

首先熟悉jzo2o-foundations运营基础服务工程的结构,jzo2o-foundations工程结构如下图:

在这里插入图片描述

依赖:

    <dependencies><!--Nacos服务发现--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--Nacos服务管理配置--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--开启Bootstrap配置文件的支持--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency><!--jzo2o-mvc在jzo2o-framework下,针对web开发的依赖--><dependency><groupId>com.jzo2o</groupId><artifactId>jzo2o-mvc</artifactId></dependency><!--knife4j用于生成swagger文档--><dependency><groupId>com.jzo2o</groupId><artifactId>jzo2o-knife4j-web</artifactId></dependency><!--        <dependency>-->
<!--            <groupId>com.jzo2o</groupId>-->
<!--            <artifactId>jzo2o-es</artifactId>-->
<!--        </dependency>--><!--单元测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--api接口,定义了服务之间的远程调用接口--><dependency><groupId>com.jzo2o</groupId><artifactId>jzo2o-api</artifactId></dependency><!--序列化工具库--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><!--jzo2o-redis定义在jzo2o-framework工程,定义了持久层相关的依赖--><dependency><groupId>com.jzo2o</groupId><artifactId>jzo2o-redis</artifactId></dependency>
<!--        <dependency>-->
<!--            <groupId>com.jzo2o</groupId>-->
<!--            <artifactId>jzo2o-canal-sync</artifactId>-->
<!--        </dependency>--><!--jzo2o-mysql定义在jzo2o-framework工程,定义了持久层相关的依赖--><dependency><groupId>com.jzo2o</groupId><artifactId>jzo2o-mysql</artifactId></dependency>
<!--        <dependency>-->
<!--            <groupId>com.jzo2o</groupId>-->
<!--            <artifactId>jzo2o-xxl-job</artifactId>-->
<!--        </dependency>--></dependencies>

持久层:MySQL数据库,mybatis-plus框架,com.github.pagehelper分页组件

中间件:Redis、Elasticsearch、xxl-job

服务层:通过Spring进行事务控制,redisson分布式锁、Spring Cache缓存框架

web层: SpringMVC框架(基于SpringBoot开发)

web容器:undertow(Undertow 是一个采用 Java 开发的灵活的高性能 Web 服务器,红帽公司的开源产品)

高并发场景下undertow的性能更好。

2.2.3.2 接口测试

启动jzo2o-foundations工程。启动docker中的redis,mysql,nacos。

在这里插入图片描述

通过swagger接口文档去熟悉模块的接口,通过测试接口去理解接口的整个交互流程。

打开接口文档:http://localhost:11509/foundations/doc.html

在这里插入图片描述

通过左侧菜单找到“运营端-服务类型相关接口”,如下图:

在这里插入图片描述

点击“服务类型分页查询”打开接口文档,如下图:

在这里插入图片描述

找到接口地址:/foundations/operation/serve-type/page

/foundations:微服务的content-path路径

/operation:表示给运营端使用的接口

/serve-type/page:具体的接口地址

在jzo2o-foundations工程搜索“/serve-type”关键字

在这里插入图片描述

继续在ServeTypeController.java类中找/page接口,如下图:

@GetMapping("/page")
@ApiOperation("服务类型分页查询")
public PageResult<ServeTypeResDTO> page(ServeTypePageQueryReqDTO serveTypePageQueryReqDTO) {return serveTypeService.page(serveTypePageQueryReqDTO);
}

下边debug运行工程,跟踪接口执行的流程:

首先打上断点,如下图:

在这里插入图片描述

debug运行jzo2o-foundations工程。下边通过swagger接口文档测试该接口,进入“调试”窗口,点击“发送”

在这里插入图片描述

跟踪请求参数:

在这里插入图片描述

放行继续执行,测试结束,观察响应结果

在这里插入图片描述

观察idea控制台输出的SQL执行语句

在这里插入图片描述

3 开发区域服务模块

3.1 流程分析

我们的开发流程肯定是先点区域,然后在区域中设置服务,所以我们应当先开发查询区域再查询服务列表的流程。

3.2 查询区域服务

3.2.1 梳理接口

在定义接口前先梳理本模块涉及哪些接口,根据梳理出的接口制定工作计划。

通常对于前后端交互的接口根据界面原型、需求文档去梳理。

通过阅读需求文档在区域服务模块包括以下接口:

  1. 区域服务分页查询接口

  2. 区域服务新增接口

  3. 区域服务删除接口

  4. 区域服务价格修改接口

  5. 区域服务设置热门接口

  6. 区域服务取消热门接口

  7. 区域服务上架接口

  8. 区域服务下架接口

3.2.2 接口设计

下边设计区域服务分页查询接口,企业中前后分离开发通常由java程序员设计接口,设计完成提供接口文档给前端工程师。

如何设计一个接口?

我们根据最终提供的接口文档看看需要设计哪些内容。

3.2.2.1 接口文档

接口设计信息如下:

接口路径:GET/foundations/operation/serve/page

请求数据类型 application/x-www-form-urlencoded

在这里插入图片描述

响应参数:

在这里插入图片描述

在这里插入图片描述

首先明确该接口是一个前后端交互接口,该接口由前端通过HTTP协议进行调用,前端去调用接口需要知道以下内容:

  1. HTTP请求方法

  2. 接口路径

  3. 请求参数类型

  4. 请求参数内容

  5. 响应结果类型

  6. 响应结果状态码

  7. 响应结果内容

所以我们设计接口需要设计这些内容。

3.2.2.2 HTTP请求方法

根据RESTful规范:

查询方法用GET,请求参数比较多可用POST

新增方法用POST

修改方法用PUT

删除方法用DELETE

本接口是一个分页查询接口,查询条件我们用GET。

具体的代码实现可以找一些现有的类参考,比如:ServeTypeController类

3.2.2.3 接口路径

定义为RESTful风格的路径。

接口路径为:/foundations/operation/serve/page

因为我们在bootstrap.yml文件中已经定义了项目根路径 server.servlet.context-path: /foundations

server:port: 11509undertow:accesslog:enabled: truepattern: "%t %a &quot;%r&quot; %s (%D ms)"dir: /data/logs/undertow/${spring.application.name}/access-logs/servlet:context-path: /foundations

可以在类上边使用@RequestMapping指定该类中接口的路径的基础路径。

在方法中指定具体的路径。

3.2.2.4 请求参数类型

常用的有:

  • json格式:

    application/json,传递json格式字符串,当传递的参数是属于一个对象的属性时可用此格式,比如:新增、修改时通常传递的数据是某个对象的信息就可以使用此格式。

  • 表单格式:

    application/x-www-form-urlencoded,传递key/value串,就是在url后通过?和&进行拼接的参数,比如:

/foundations/operation/serve/page?pageNo=1&pageSize=10

当传递的参数比较杂且不属于某个特定的对象时使用此格式,本接口使用application/x-www-form-urlencoded格式。

3.2.2.5 请求参数内容

请求参数的内容根据需求文档和界面原型去识别。

分页式查询首先有当前页码和每页显示记录数。

对于查询类的接口还有常用的参数有:排序方式、排序字段。

再根据需求的梳理,查询某个区域下的服务需要传递一个区域id。

请求参数如下:

在这里插入图片描述

3.2.2.6 响应结果类型

常见的类型有:text/html、text/plain、application/json等。

本项目统一使用application/json

3.2.2.7 响应结果状态码

HTTP状态码是服务器返回给客户端的数字代码(三位数字),共分为五类:

1xx: 表示服务器接收到了客户端请求并正在处理

2xx: 表示成功状态码

3xx:表示重向定状态码

4xx:表示客户端错误状态码

5xx: 表示服务端错误状态码

当服务端处理成功返回200,其它表示失败。

3.2.2.8 响应结果内容

分页查询通用的响应内容有:数据列表、总页数、总记录数

数据列表中需要分析具体的属性,根据界面原型进行分析:

在这里插入图片描述

属性包括:

在这里插入图片描述

制定分页查询通用的响应内容如下:

msg、code、 data、total、pages是固定的。

data中List数据的内容对于不同的分页查询会不一样。

在这里插入图片描述

响应示例

{"msg": "OK","code": 200,"data": {"list": [{"serveTypeId": 0,"serveItemName": "","updateTime": "","saleStatus": 0,"serveItemId": 0,"referencePrice": 0,"createTime": "","regionId": 0,"price": 0,"id": 0,"isHot": 0,"serveTypeName": ""}],"total": 0,"pages": 0}
}

3.2.3 接口定义

3.2.3.1 编写controller
3.2.3.1.1 基础注释

根据接口设计的内容编写controller方法,最后通过swagger生成接口文档。

在这里插入图片描述

缺少请求路径的/foundations/operation/serve/page的serve的controller,所以在com.jzo2o.foundations.controller.operation中创建ServeController

注意 @RestController注入到Spring容器中的名字,采用包名+类名,来避免重复

@RestController("operationServeController")

注意@RequestMapping路径,因为我们在bootstrap.yml文件中已经定义了项目根路径 server.servlet.context-path: /foundations,所以路径应该是

@RequestMapping("/operation/serve")

注意是否要添加@Validated,可以对id等字段进行校验,@NotNull(message = "id不能为空")

public void update(@NotNull(message = "id不能为空") @PathVariable("id") Long id,@RequestParam("managerName") String managerName,@RequestParam("managerPhone") String managerPhone) {regionService.update(id, managerName, managerPhone);
}

注意我们使用的swagger接口文档编写,所以要添加@Api

@Api(tags = "运营端 - 区域服务管理相关接口")
3.2.3.1.2 分页controller中实现

请求参数用com.jzo2o.foundations.model.dto.request.ServePageQueryReqDTO封装起来,进行请求

@Data
@ApiModel("服务分页查询类")
public class ServePageQueryReqDTO extends PageQueryDTO {@ApiModelProperty(value = "区域id", required = true)private Long regionId;
}

返回参数用com.jzo2o.foundations.model.dto.response.ServeResDTO封装到List列表中,再和total和pages组成data返回。

@RestController("operationServeController")
@RequestMapping("/operation/serve")
@Api(tags = "运营端 - 区域服务管理相关接口")
public class ServeController {@GetMapping("/page")@ApiOperation("分页查询区域服务列表")public PageResult<ServeResDTO> page(ServePageQueryReqDTO servePageQueryReqDTO) {return null;}
}

初步构建完毕,重新启动后,查看swagger文档,成功查询到

在这里插入图片描述

3.2.3.2 编写mapper
3.2.3.2.1 mapper代码生成工具

代码生成工具

通常一个接口需求明确后从持久层开始开发。

对于一个新模块需要使用工具生成模型类、mapper接口、mapper映射文件等,下边介绍一个工具用于自动生成代码。

使用MybatisPlus插件自动生成代码

1、安装插件

在这里插入图片描述

2.重启IDEA,连接mysql

在这里插入图片描述

在这里插入图片描述

配置连接的数据库

输入连接字符串:jdbc:mysql://192.168.101.68:3306/jzo2o-foundations?useSSL=false&serverTimezone=UTC

账号和密码跟我们day00设置一样,账号root,密码mysql

3、配置代码生成规则

在这里插入图片描述

1)选择表:上图选择serve_type表。

2)设置生成代码的根目录:上图设置generator

3)设置包路径:上图设置为com.jzo2o.foundations

4)主键生成策略:根据表中主键的生成策略进行选择,支持的主键生成策略如下图:

在这里插入图片描述

本项目使用的MyBatisPlus版本支持前5个,对应MyBatisPlus源码如下:

public enum IdType {AUTO(0),NONE(1),INPUT(2),ASSIGN_ID(3),ASSIGN_UUID(4);
  • AUTO:基于数据库的自增主键
  • NONE: 不设置id生成策略
  • INPUT:用户手工输入id
  • ASSIGN_ID:雪花算法生成id(可兼容数值型与字符串型)
  • ASSIGN_UUID:以UUID生成算法作为id生成策略

本项目使用ASSIGN_ID方式,即分配ID。

5)勾选要生成的类及包路径(Entity、Mapper、Controller、Service、ServiceImpl)。

6)勾选是否生成lombok注解、restController注解、swagger注解等。

点击“check field”选择表中的字段。

点击“code generatro”生成代码。

生成成功在项目工程根目录有一个generator目录,里边为生成的代码,如下图:

在这里插入图片描述

对生成的代码根据自己的需求稍加修改,修改后拷贝到工程相应的包下即可。

3.2.3.2.2 分页mapper开发

因为我们最后获取的响应里由服务名称,但是serve表中并没有服务名称

在这里插入图片描述

所以就涉及多表查询,而MybatisPlus生成的代码只适合单表查询。

查看响应参数,保证返回值与响应一致,驼峰为返回值,下划线为数据库查询出来的参数

在这里插入图片描述

先查询一个北京区域的服务,region_id为1686303222843662337

SELECTst.id serve_type_id,si.name serve_item_name,s.update_time update_time,s.sale_status sale_status,si.id serve_item_id,si.reference_price reference_price,s.create_time create_time,s.region_id region_id,s.price price,s.id id,s.is_hot is_hot,st.name serve_type_name	
FROMserve sINNER JOIN serve_item si ON s.serve_item_id = si.idINNER JOIN serve_type st ON si.serve_type_id = st.id 
WHEREregion_id = 1686303222843662337

在这里插入图片描述

持久层基础代码生成完毕下边开发mapper接口,对于通用的CRUD接口由MybatisPlus提供。

对于需要自定义mapper接口的需求则需要自定义mapper接口及mapper映射文件,根据需求本接口要返回的数据包括多张表的数据,而MybatisPlus提供的CRUD是针对单表的,下边定义mapper实现多表关联查询。

先定义mapper接口:

mapper接口讲究通用性,根据数据处理最底层的需求去定义接口,本需求是根据区域查询服务列表,参数为区域id,方法返回值为服务列表。

生成com.jzo2o.foundations.mapper.ServeMapper

public interface ServeMapper extends BaseMapper<Serve> {List<ServeResDTO> queryServeListByRegionId(@Param("regionId") Long regionId);
}

@Param("regionId")是我们待会在mapper的xml文件中需要使用的。

在这里插入图片描述

因为我们的查询方法是新生成的,自然在mapper的xml无法找到,所以alt+enter在src/main/resources/mapper/ServeMapper.xml中自动生成

在这里插入图片描述

复制我们刚刚的sql语句,修改where语句为 region_id = #{regionId},现在都是使用#{}:占位符号,#{ }${ } 会有不同的表现。#{ }:解析为一个 JDBC 预编译语句(prepared statement)的参数标记符。而${ } 仅仅为一个纯碎的 string 替换,在动态 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="com.jzo2o.foundations.mapper.ServeMapper"><select id="queryServeListByRegionId" resultType="com.jzo2o.foundations.model.dto.response.ServeResDTO">SELECTst.id serve_type_id,si.NAME serve_item_name,s.update_time update_time,s.sale_status sale_status,si.id serve_item_id,si.reference_price reference_price,s.create_time create_time,s.region_id region_id,s.price price,s.id id,s.is_hot is_hot,st.NAME serve_type_nameFROMserve sINNER JOIN serve_item si ON s.serve_item_id = si.idINNER JOIN serve_type st ON si.serve_type_id = st.idWHEREregion_id = 1686303222843662337</select>
</mapper>
3.2.3.2.3 针对mapper的单元测试

大厂都严格要求对mapper进行单元测试,创建com.jzo2o.foundations.service.ServeMapperTest

在这里插入图片描述

@SpringBootTest
@Slf4j
public class ServeMapperTest {@Resourceprivate ServeMapper serveMapper;@Testpublic void testQueryServeListByRegionId() {List<ServeResDTO> serveResDTOS = serveMapper.queryServeListByRegionId(1686303222843662337L);Assert.notEmpty(serveResDTOS, "查询结果为空");}
}
  • @SpringBootTestspring测试类注释
  • @Slf4j日志记录
  • @Test测试方法注解
  • @Resource自动注入

运行我们的单元测试

在这里插入图片描述

成功查询到,说明我们的单元测试通过。

3.2.3.2.4 @Resource 和 @Autowired有什么区别?
  1. 来源不同

@Resource 是 Java EE(Java Platform, Enterprise Edition)规范定义的注解,位于 javax.annotation 包中,不仅可以用于 Spring 环境,还可以用于其他 Java EE 容器。

@Autowired 是 Spring 框架定义的注解,位于 org.springframework.beans.factory.annotation 包中,主要用于 Spring 环境中。

  1. 注入方式不同

@Resource默认按名称注入,如果在spring容器找不到对应名称的 Bean,则按照 byType 进行注入。

@Autowired默认按照 byType 的方式进行注入。如果有多个类型相同的 Bean,可以结合 @Qualifier 使用指定具体的 Bean 名称

// 使用 @Resource
@Resource(name = "myBean")
private MyBean myBean;// 使用 @Autowired
@Autowired
@Qualifier("myBean")
private MyBean myBean;
3.2.3.3 编写service

用我们针对serve生成的代码进行修改

在这里插入图片描述

在这里插入图片描述

复制到相应的位置,他生成的是针对单表查询的mybatisplus。所以我们单表查询的时候可以直接使用。

在controller中注入service

@RestController("operationServeController")
@RequestMapping("/operation/serve")
@Api(tags = "运营端 - 区域服务管理相关接口")
public class ServeController {@Resourceprivate IServeService serveService;@GetMapping("/page")@ApiOperation("分页查询区域服务列表")public PageResult<ServeResDTO> page(ServePageQueryReqDTO servePageQueryReqDTO) {return serveService.page(servePageQueryReqDTO);}
}

service接口

public interface IServeService extends IService<Serve> {PageResult<ServeResDTO> page(ServePageQueryReqDTO servePageQueryReqDTO);}

实现层,分页有两种思路,一种是mybatisplus的分页,但是不能自定义查询语句,也就是只能单表查询,另一种是用pagehelper插件,可以自定义,我们的语句是自定义的,因此我们采用pagehelper。

未来工作中有很多别人的代码,我们要学习观察和替换,把参数和方法改成我们自己的。

在这里插入图片描述

@Service
public class ServeServiceImpl extends ServiceImpl<ServeMapper, Serve> implements IServeService {@Overridepublic PageResult<ServeResDTO> page(ServePageQueryReqDTO servePageQueryReqDTO) {PageResult<ServeResDTO> serveResDTOPageResult = PageHelperUtils.selectPage(servePageQueryReqDTO,() -> baseMapper.queryServeListByRegionId(servePageQueryReqDTO.getRegionId()));return serveResDTOPageResult;}
}
3.2.3.3.1 单元测试
@SpringBootTest
@Slf4j
class IServeServiceTest {@Resourceprivate IServeService serveService;//分页测试@Testpublic void test_page(){ServePageQueryReqDTO servePageQueryReqDTO = new ServePageQueryReqDTO();servePageQueryReqDTO.setRegionId(1677152267410149378L);servePageQueryReqDTO.setPageNo(1L);servePageQueryReqDTO.setPageSize(3L);PageResult<ServeResDTO> page = serveService.page(servePageQueryReqDTO);log.info("page : {}", page);Assert.notEmpty(page.getList(),"列表为空");}
}

成功输出五条共两页。

在这里插入图片描述

3.2.3.3.2 PageHelper原理

使用com.github.pagehelper分页插件实现分页功能,下边介绍它的执行原理。

PageHelperUtils是项目封装的一个工具类,进入selectPage方法,调用PageHelper.startPage方法设置分页参数,通过一层一层进入源码,最终将分页参数设置到ThreadLocal<Page>LOCAL_PAGE=newThreadLocal(); 中。

在这里插入图片描述

通过PageInterceptor拦截器拦截 MyBatis的Executor 的 query() 方法得到原始的sql语句,首先得到count总数,然后从newThreadLocal中取出分页参数,在原始sql语句中添加分页参数查询分页数据。

部分源码截图如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我们的分页参数在ThreadLocal中存储,最后拼合在一起

在这里插入图片描述

如果查询第二页,会自动进行计算拼接(page-1)*size

在这里插入图片描述

3.2.3.4 controller测试

重启服务,通过接口文档工具进行测试。

遇到问题在controller、service中打断点进行调试。

测试时注意请求参数填写是否正确,下边是测试结果

在这里插入图片描述

返回

在这里插入图片描述

3.2.3.5 前后端联调

启动foundations服务和gateway服务。

通过cmd进入project-xzb-pc-admin-vue3-java目录启动前端项目

运行命令,启动前端工程

npm run dev 

根据业务操作流程进行测试。

点击服务管理中区域服务,对北京市进行设置服务

在这里插入图片描述

成功查询到五条服务项目

在这里插入图片描述

相关文章:

【云岚到家】-day01-项目熟悉-查询区域服务开发

文章目录 1 云岚家政项目概述1.1 简介1.2 项目业务流程1.3 项目业务模块1.4 项目架构及技术栈1.5 学习后掌握能力 2 熟悉项目2.1 熟悉需求2.2 熟悉设计2.2.1 表结构2.2.2 熟悉工程结构2.2.3 jzo2o-foundations2.2.3.1 工程结构2.2.3.2 接口测试 3 开发区域服务模块3.1 流程分析…...

Docker面试整理-如何进行Docker镜像的构建和发布?

构建和发布 Docker 镜像是 Docker 使用中的一个常见任务,通常涉及编写 Dockerfile、构建镜像以及将其推送到镜像仓库的过程。以下是构建和发布 Docker 镜像的详细步骤: 1. 编写 Dockerfile 首先,你需要创建一个 Dockerfile,这是一个包含了一系列指令的文本文件,用来告诉 D…...

macOS Sequoia 将 Mac 生产力与智能化提升至全新高度 (macOS 15 ISO、IPSW、PKG 下载)

macOS Sequoia 将 Mac 生产力与智能化提升至全新高度 (macOS 15 ISO、IPSW、PKG 下载) iPhone 镜像、Safari 浏览器重大更新、备受瞩目的游戏和 Apple Intelligence 等众多全新功能令 Mac 使用体验再升级 请访问原文链接&#xff1a;https://sysin.org/blog/macOS-Sequoia/&a…...

用户管理与服务器远程管理

用户管理 服务器系统版本介绍 windows服务器系统&#xff1a;win2000 win2003 win2008 win2012 linux服务器系统&#xff1a;Redhat Centos 用户管理 用户概述 &#xff08;1&#xff09;每一个用户登录系统后&#xff0c;拥有不同的操作权限。 &#xff08;2&#xff09;…...

Pytorch 实现简单的 线性回归 算法

Pytorch实现简单的线性回归算法 简单 tensor的运算 Pytorch涉及的基本数据类型是tensor&#xff08;张量&#xff09;和Autograd&#xff08;自动微分变量&#xff09; import torch x torch.rand(5, 3) #产生一个5*3的tensor&#xff0c;在 [0,1) 之间随机取值 y torch.o…...

Django中配置日志

在Django中配置日志的方法非常简单&#xff0c;只需要在 setting 文件中添加配置项&#xff0c;系统会自动生成相应的日志文件&#xff0c;也可以配置调试时显示内容&#xff0c;报错发送邮件等操作。 在setting.py中添加以下配置。 # 日志配置 LOGS_DIRS os.path.join(BASE…...

海外盲盒小程序背后的技术支撑与实现

海外盲盒小程序之所以能够迅速崛起并受到全球消费者的喜爱&#xff0c;除了其独特的商业模式和营销策略外&#xff0c;更重要的是其背后的技术支撑和实现。本文将深入探讨海外盲盒小程序背后的技术支撑及其实现方式。 一、多语言与本地化技术 为了满足全球不同地区消费者的需…...

vue问题记录

vue3 路由跳转携带参数 路由跳转携带参数 query方法 //跳转传参 this.$router.push({path:/home,query: {id:1}}) //接受参数 this.$route.query.id问题&#xff1a;刷新页面&#xff0c;参数会丢失—未解决 将参数存在本地存储中&#xff0c;但是组件销毁时&#xff0c;清…...

Flutter - Material3适配

demo 地址: https://github.com/iotjin/jh_flutter_demo 代码不定时更新&#xff0c;请前往github查看最新代码 Flutter - Material3适配 对比图具体实现一些组件的变化 代码实现Material2的ThemeDataMaterial3的ThemeData Material3适配官方文档 flutter SDK升级到3.16.0之后 …...

一个有趣的c++案例

1. 源码 #include <stdio.h> #include <stdint.h> #include <iostream>using namespace std;uint8_t a 0; uint8_t b 0;#define MY_LOG#ifdef MY_LOG#define my_log(...) printf(__VA_ARGS__); fflush(stdout)#else #define my_log(...) #endifvoid …...

【python】OpenCV—Background Estimation(15)

文章目录 中值滤波中值滤波得到图像背景移动侦测 学习来自 OpenCV基础&#xff08;14&#xff09;OpenCV在视频中的简单背景估计 中值滤波 中值滤波是一种非线性平滑技术&#xff0c;主要用于数字信号处理&#xff0c;特别是在图像处理中去除噪声。 一、定义与原理 定义&am…...

【Java毕业设计】基于JavaWeb的旅游论坛管理系统

文章目录 摘 要目 录1 概述1.1 研究背景及意义1.2 国内外研究现状1.3 拟研究内容1.4 系统开发技术1.4.1 Java编程语言1.4.2 vue技术1.4.3 MySQL数据库1.4.4 B/S结构1.4.5 Spring Boot框架 2 系统需求分析2.1 可行性分析2.2 系统流程2.2.1 操作流程2.2.2 登录流程2.2.3 删除信息…...

讲一下v-model的底层实现原理?

什么是v-model&#xff1f; 在Vue.js中&#xff0c;v-model是一个用于实现双向数据绑定的指令。它通常用于表单控件上&#xff0c;以便能够在视图和数据模型之间自动同步数据。具体来说&#xff0c;当用户在输入框中输入内容时&#xff0c;数据模型会自动更新&#xff1b;当数…...

大模型基础——从零实现一个Transformer(3)

大模型基础——从零实现一个Transformer(1)-CSDN博客 一、前言 之前两篇文章已经讲了Transformer的Embedding,Tokenizer,Attention,Position Encoding, 本文我们继续了解Transformer中剩下的其他组件. 二、归一化 2.1 Layer Normalization layerNorm是针对序列数据提出的一种…...

一二三应用开发平台应用开发示例——概述、应用开发示例简介及创建前后端模块

概述 对于应用开发平台的核心基石——系统管理模块&#xff0c;我精心撰写了一份详尽的说明手册。该手册旨在从使用者的角度出发&#xff0c;不仅全面阐述系统的各项属性和功能&#xff0c;更着重强调使用过程中的注意事项和最佳实践。 在手册的编写过程中&#xff0c;我特别…...

springboot+minio+kkfileview实现文件的在线预览

在原来的文章中已经讲述过springbootminio的开发过程&#xff0c;这里不做讲述。 原文章地址&#xff1a; https://blog.csdn.net/qq_39990869/article/details/131598884?spm1001.2014.3001.5501 如果你的项目只是需要在线预览图片或者视频那么可以使用minio自己的预览地址进…...

HTML5+CSS3小实例:粘性文字的滚动效果

实例:粘性文字的滚动效果 技术栈:HTML+CSS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-sca…...

Java 关于抽象 -- Java 语言的抽象类、接口和函数式接口

大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 008 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进一步完善自己对整个 Java 技术体系来充实自…...

用 Notepad++ 写 Java 程序

安装包 百度网盘 提取码&#xff1a;6666 安装步骤 双击安装包开始安装。 安装完成&#xff1a; 配置编码 用 NotePad 写 Java 程序时&#xff0c;需要设置编码。 在 设置&#xff0c;首选项&#xff0c;新建 中进行设置&#xff0c;可以对每一个新建的文件起作用。 Note…...

malloc brk mmap

malloc 是一个库函数&#xff0c;通常在 C 标准库中实现&#xff0c;用于动态内存分配。malloc 的具体实现可能因库、操作系统和平台而异&#xff0c;但通常它会与底层操作系统提供的内存管理功能进行交互。 对于大多数现代操作系统&#xff08;如 Unix、Linux、Windows 等&am…...

java多线程相关概念

在Java多线程编程中&#xff0c;有几个关键的术语需要理解&#xff1a; 1.线程(Thread)&#xff1a;线程是操作系统能够进行运算调度的最小单位&#xff0c;它被包含在进程之中&#xff0c;是进程中的实际运作单位。 2.进程(Process)&#xff1a;进程是系统进行资源分配和调度…...

【html】简单网页模板源码

大家每一次在写网页的时候会不会因为布局而困扰今天就给大家带来一个我自己亲自编写的网页的基本的模板大家可以直接去利用&#xff0c;大家也可以利用自己的想法去做空间的美化和完善。 源码&#xff1a; html: <!DOCTYPE html> <html lang"zh"><…...

借助Historian Connector + TDengine,打造工业创新底座

在工业自动化的领域中&#xff0c;数据的采集、存储和分析是实现高效决策和操作的基石。AVEVA Historian (原 Wonderware Historian) 作为领先的工业实时数据库&#xff0c;专注于收集和存储高保真度的历史工艺数据。与此同时&#xff0c;TDengine 作为一款专为时序数据打造的高…...

51单片机-实机演示(LED点阵)

目录 前言: 一.线位置 二.扩展 三.总结 前言: 这是一篇关于51单片机实机LED点阵的插线图和代码说明.另外还有一篇我写的仿真的连接在这:http://t.csdnimg.cn/ZNLCl,欢迎大家的点赞,评论,关注. 一.线位置 接线实机图. 引脚位置注意: 1. *-* P00->RE8 P01->RE7 …...

STM32硬件接口I2C应用(基于MP6050)

目录 概述 1 STM32Cube控制配置I2C 1.1 I2C参数配置 1.2 使用STM32Cube产生工程 2 HAL库函数介绍 2.1 初始化函数 2.2 写数据函数 2.3 读数据函数 3 认识MP6050 3.1 MP6050功能介绍 3.2 加速计测量寄存器 ​编辑3.3 温度计量寄存器 3.4 陀螺仪测量寄存器 4 MP60…...

基于JSP的贝儿米幼儿教育管理系统

开头语&#xff1a; 你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果您对本系统感兴趣或者有相关需求&#xff0c;文末可以找到我的联系方式。 开发语言&#xff1a; Java 数据库&#xff1a; MySQL 技术&#xff1a; JSP技术 工具&#xff1a; IDEA/Eclipse、…...

数字化与文化交融,树莓集团助力园区文化升级

树莓集团在产业园运营领域建设了特色空间布局&#xff0c;包括产业实训基地、产业办公中心、业务资源平台、产学研中心、数字资产空间、双创孵化空间、产业实验室和人才项目转化中心等八大板块&#xff0c;共同构建了一个全面而深入的产业支撑体系&#xff0c;为园区文化建设提…...

【原创课程】如何制作安装板

具体步骤如下: 第一步:新建页类型为“安装板布局图(交互式)”并修改页描述为“安装板布局图”。 第二步:新建安装板 第三步:设置图纸上符号元件的部件,双击符号,弹出常规设备窗口,点击部件进行选择 第四步:打开2D安装板导航器,将图纸中的设备拖拽到安装板上 第五步…...

简单聊聊【java.util.Stream】,更新中

public class Main {public static void main(String[] args) {List<Integer> numbers Arrays.asList(1, 2, 3, 4, 5, 6); // 原始容器&#xff1a;java.util.Arrays.ArrayList#ArrayList// 创建一个 Stream&#xff0c;过滤出偶数&#xff0c;并打印它们numbers.str…...

GIS之arcgis系列07:conda环境下安装arcpy环境

首先将python27环境下的“Desktop10.8.pth”拷贝到anaconda环境下。 路径如下&#xff08;仅参考&#xff09;&#xff1a; C:\Python27\ArcGIS10.8\Lib\site-packages\Desktop10.8.pth D:\Anaconda\Lib\site-packages 在anaconda prompt中穿创建一个新环境 conda create -…...

读书郎营销网站/百度广告联盟赚广告费

字符串操作C语言提供了较多的库函数&#xff0c;本题目要求代码中不能使用字符串操作相关的库函数&#xff0c;可以使用malloc。 用例中可以使用中提供的库函数。 实现接口&#xff0c;每个接口实现1个基本操作&#xff1a; unsigned int strlenth(char*s)&#xff1a;计算字…...

加强 政府网站信息内容 建设/甲马营seo网站优化的

Android环境搭建 首先下载jdk8和之前学过的Java的配置环境相同 之后下载Android Studio选择与自己电脑所对应的安装包 只有新建项目工程 然后打开Android 虚拟机 选择与自己手机相匹配的Android版本 然后虚拟安卓手机模仿按键图标 依次可以运行出来按钮界面...

做网站南宁/什么是网络营销

C语言每天提供专门的字符串类型&#xff0c;需要通过字符数组才能对字符串进行存储和处理。在标准C中&#xff0c;字符串类由C STL实现。string是一个基于字符的序列容器&#xff0c;具有vector向量一样的内部线性结构&#xff0c;字符逐一写入容器&#xff0c;最后以null字符结…...

高港区住房和城乡建设局网站/厦门seo网站排名优化

Webpack 简介 什么是 Webpack&#xff1f; webpack是一种前端资源构建工具&#xff0c;一个静态模块打包器在webpack看来&#xff0c;前端所有的资源文件都会作为模块处理它将根据模块的依赖关系进行静态分析&#xff0c;打包生成对应的静态资源(bundle)’ Webpack 五个核心…...

做企业网站的步骤/东莞seo优化

今天晕晕沉沉的创建一个JOB&#xff0c;用PLSQL图形化界面没成功&#xff0c;SQL语句也没成果&#xff0c;最后发现竟然是job变量未定义&#xff0c;留个坑在这里…… SQL> begin 2 sys.dbms_job.submit(job > :job, 3 what > proc_export_containers;, 4…...

wordpress支付宝/360推广登录入口

最近研究基于 GeoServer 的开源 GIS 框架&#xff0c;其中构建 GIS database 需要使用 PostgreSQL PostGIS 插件。花了些时间学习&#xff0c;这里记录一下。如有错误&#xff0c;感谢不吝指正&#xff5e;&#xff5e;本文地址&#xff1a;https://segmentfault.com/a/1190000…...