需求分析
教学机构人员点击课程管理
按钮进入课程查询界面,在课程列表页面输入查询条件查询课程的信息
本教学机构查询本机构的课程信息
数据模型(model工程)
课程查询功能涉及到的数据表有课程基本信息表,教学计划表
创建数据字典表
: 在课程基本信息表中直接记录审核未通过
的字符串不利于后期修改,如果有一天客户想要将数据表中审核未通过的记录在显示时改为未通过
三个字就很麻烦
对于分类项较为固定的数据
(如课程状态、课程类型、用户类型等),为了提高系统的可扩展性可以专门定义数据字典表去维护
202001
,前端在展示查询出的数据时再根据代码取出它对应的文字描述显示给用户[
{"code":"202001","desc":"审核未通过"},
{"code":"202002","desc":"未审核"},
{"code":"202003","desc":"审核通过"}
]
第一步: 使用IDEA自带的客户端
连接MySQL,创建内容管理数据库xc_content
,执行xc_content.sql
脚本向创建的内容管理数据库导入数据
第二步: 使用MyBatis-Plus提供的generator工程
或MyBatisX插件
生成数据库表对应的PO类、Mapper接口、Mapper的xml文件
xuecheng-plus-generator工程
导入当前项目工程,点击pom.xml
文件右键Add as Maven Project
可以自动识别maven工程第三步: 修改generator工程中ContentCodeGenerator
类的信息,包括数据库地址、数据库账号、数据库密码、生成的表、生成路径
//数据库账号
private static final String DATA_SOURCE_USER_NAME = "root";
//数据库密码
private static final String DATA_SOURCE_PASSWORD = "123456";
//生成的表
private static final String[] TABLE_NAMES = new String[]{
"course_base",
"course_market",
"course_teacher",
"course_category",
"teachplan",
"teachplan_media",
"course_publish",
"course_publish_pre"
};
// TODO 默认生成entity,需要生成DTO修改此变量
// 一般情况下要先生成 DTO类 然后修改此参数再生成 PO 类。
private static final Boolean IS_DTO = false;
public static void main(String[] args) {
....
//生成路径
gc.setOutputDir(System.getProperty("user.dir") + "/xuecheng-plus-generator/src/main/java");
....
// 数据库配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setUrl("jdbc:mysql://192.168.101.65:3306/xcplus_" + SERVICE_NAME+"166"
+ "?serverTimezone=UTC&useUnicode=true&useSSL=false&characterEncoding=utf8");
...
}
第四步: 修改完成后执行ContentCodeGenerator
类的main方法
,自动生成content包
并包含内容管理模块的controller、mapper、po及service
相关代码
第五步: 在生成的PO类中含有MyBatisPlus框架
的注解,所以需要在当前模块的model
工程中添加MyBatisPlus框架的依赖
消除错误
@Data
@TableName("course_base")
public class CourseBase implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 机构ID
*/
private Long companyId;
/**
* 机构名称
*/
private String companyName;
/**
* 课程名称
*/
private String name;
/**
* 适用人群
*/
private String users;
/**
* 课程标签
*/
private String tags;
/**
* 大分类
*/
private String mt;
/**
* 小分类
*/
private String st;
/**
* 课程等级
*/
private String grade;
/**
* 教育模式(common普通,record 录播,live直播等)
*/
private String teachmode;
/**
* 课程介绍
*/
private String description;
/**
* 课程图片
*/
private String pic;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createDate;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime changeDate;
/**
* 创建人
*/
private String createPeople;
/**
* 更新人
*/
private String changePeople;
/**
* 审核状态
*/
private String auditStatus;
/**
* 课程发布状态 未发布 已发布 下线
*/
private String status;
}
<dependencies>
<dependency>
<groupId>com.xuechenggroupId>
<artifactId>xuecheng-plus-baseartifactId>
<version>0.0.1-SNAPSHOTversion>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-annotationartifactId>
<version>${mybatis-plus-boot-starter.version}version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-coreartifactId>
<version>${mybatis-plus-boot-starter.version}version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
dependencies>
请求响应模型类
查询条件
包括: 课程名称(name)、课程审核状态(auditStatus)、课程发布状态(status),对于分页查询还要包括当前页码、每页显示记录数
第一步定义请求模型类
: 对于查询条件较多的接口可以定义单独的模型类接收参数
分页查询的参数
(当前页码、每页显示的记录数)可以单独在xuecheng-plus-base
工程中定义课程查询的特有参数
(审核状态,课程名称,发布状态)可以在xuecheng-plus-content-model
工程中定义package com.xuecheng.base.model;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageParams {
// 默认起始页码
public static final long DEFAULT_PAGE_CURRENT = 1L;
// 默认每页记录数
public static final long DEFAULT_PAGE_SIZE = 10L;
// 当前页码
@ApiModelProperty("当前页码")
private Long pageNo = DEFAULT_PAGE_CURRENT;
// 当前每页记录数
@ApiModelProperty("每页记录数")
private Long pageSize = DEFAULT_PAGE_SIZE;
}
package com.xuecheng.content.model.dto;
@Data
@AllArgsConstructor
public class QueryCourseParamsDto {
// 审核状态,审核状态为数据字典中的代码字段,前端会根据审核状态代码 找到对应的名称显示
@ApiModelProperty("审核状态")
private String auditStatus;
// 课程名称
@ApiModelProperty("课程名称")
private String courseName;
// 发布状态
@ApiModelProperty("发布状态")
private String publishStatus;
}
由于请求模型类中用到了lombok注解
所以在base工程
添加依赖包
<dependencies>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
dependencies>
查询结果
包括: 课程id、课程名称、任务数(关联教学计划表查询)、创建时间、审核状态、类型,对于分页查询还要包括总记录数、当前页码、每页显示记录数
第二步定义响应模型类
: 由于分页查询的结果数据和格式比较固定(json格式),所以单独在xuecheng-plus-base
工程中定义一个基础的结果模型类
package com.xuecheng.base.model;
@Data
@AllArgsConstructor
public class PageResult<T> implements Serializable {
// 数据列表,课程查询接口的返回类型可以是CourseBase类型
private List<T> items;
// 总记录数
private long counts;
// 当前页码
private long page;
// 每页记录数
private long pageSize;
}
接口定义(api工程)
第一步: 使用HttpClient模拟请求
: 对于查询类接口通常为GET(查询条件较少)或POST(查询条件较多),对于POST还要确定content-type
即参数以什么数据格式提交
POST /content/course/list?pageNo=2&pageSize=1
Content-Type: application/json
{
"auditStatus": "202002",
"courseName": ""
}
// 成功响应结果
{
"items": [
{
"id": 26,
"companyId": 1232141425,
"companyName": null,
"name": "spring cloud实战",
"users": "所有人",
"tags": null,
"mt": "1-3",
"mtName": null,
"st": "1-3-2",
"stName": null,
"grade": "200003",
"teachmode": "201001",
"description": "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud 基础入门 3.实战Spring Boot 4.注册中心eureka。",
"pic": "https://cdn.educba.com/academy/wp-content/uploads/2018/08/Spring-BOOT-Interview-questions.jpg",
"createDate": "2019-09-04 09:56:19",
"changeDate": "2021-12-26 22:10:38",
"createPeople": null,
"changePeople": null,
"auditStatus": "202002",
"auditMind": null,
"auditNums": 0,
"auditDate": null,
"auditPeople": null,
"status": 1,
"coursePubId": null,
"coursePubDate": null
}
],
"counts": 23,
"page": 2,
"pageSize": 1
}
第二步: 在当前模块的api
接口工程的resources
目录下添加日志的配置文件log4j2-dev.xml
<Configuration monitorInterval="180" packages="">
<properties>
<property name="logdir">logsproperty>
<property name="PATTERN">%date{YYYY-MM-dd HH:mm:ss,SSS} %level [%thread][%file:%line] - %msg%n%throwableproperty>
properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${PATTERN}"/>
Console>
<RollingFile name="ErrorAppender" fileName="${logdir}/error.log"
filePattern="${logdir}/$${date:yyyy-MM-dd}/error.%d{yyyy-MM-dd-HH}.log" append="true">
<PatternLayout pattern="${PATTERN}"/>
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
Policies>
RollingFile>
<RollingFile name="DebugAppender" fileName="${logdir}/info.log"
filePattern="${logdir}/$${date:yyyy-MM-dd}/info.%d{yyyy-MM-dd-HH}.log" append="true">
<PatternLayout pattern="${PATTERN}"/>
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
Policies>
RollingFile>
<Async name="AsyncAppender" includeLocation="true">
<AppenderRef ref="ErrorAppender"/>
<AppenderRef ref="DebugAppender"/>
Async>
Appenders>
<Loggers>
<logger name="org.springframework" level="INFO">
logger>
<logger name="org.mybatis" level="INFO">
logger>
<logger name="cn.itcast.wanxinp2p.consumer.mapper" level="DEBUG">
logger>
<logger name="springfox" level="INFO">
logger>
<logger name="org.apache.http" level="INFO">
logger>
<logger name="com.netflix.discovery" level="INFO">
logger>
<logger name="RocketmqCommon" level="INFO" >
logger>
<logger name="RocketmqRemoting" level="INFO" >
logger>
<logger name="RocketmqClient" level="WARN">
logger>
<logger name="org.dromara.hmily" level="WARN">
logger>
<logger name="org.dromara.hmily.lottery" level="WARN">
logger>
<logger name="org.dromara.hmily.bonuspoint" level="WARN">
logger>
<Root level="DEBUG" includeLocation="true">
<AppenderRef ref="AsyncAppender"/>
<AppenderRef ref="Console"/>
<AppenderRef ref="DebugAppender"/>
Root>
Loggers>
Configuration>
第三步: 在当前模块api
接口工程的resources
目录下中添加属性配置文件bootstrap.yml
server:
servlet:
context-path: /content
# 设置内容管理服务的端口为63040
port: 63040
## 微服务配置
spring:
application:
name: content-api
## 日志文件配置路径
logging:
config: classpath:log4j2-dev.xml
## swagger文档的配置信息
swagger:
title: "学成在线内容管理系统"
description: "内容系统管理系统对课程相关信息进行业务管理数据"
base-package: com.xuecheng.content
enabled: true
version: 1.0.0
第四步: 在当前模块api
接口工程的pom.xml
文件中添加定义请求接口时所需要的依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-contextartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-loggingartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-validationartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-log4j2artifactId>
dependency>
<dependency>
<groupId>com.spring4allgroupId>
<artifactId>swagger-spring-boot-starterartifactId>
<version>1.9.0.RELEASEversion>
dependency>
dependencies>
第五步: 在当前模块的api
接口工程中定义Controller
方法接收请求
pageParams
分页参数在URL中以键值对格式,queryCourseParams
课程查询参数在请求体中以json格式传入,使用@RequestBody注解将json转成Java对象@RequestBody注解
后添加(required=false)属性
package com.xuecheng.content.api;
@RestController
@Api(value = "课程信息编辑接口", tags = "课程信息编辑接口")
public class CourseBaseInfoController {
@ApiOperation("课程查询接口")
@PostMapping("/course/list")
public PageResult<CourseBase> list(PageParams pageParams, @RequestBody(required=false) QueryCourseParamsDto queryCourseParams){
// 定义测试数据
/*CourseBase courseBase = new CourseBase();
courseBase.setId(15L);
courseBase.setDescription("测试课程");
PageResult result = new PageResult<>();
result.setItems(Arrays.asList(courseBase));
result.setPage(1);
result.setPageSize(10);
result.setCounts(1);
return result;*/
// 调用业务层提供的方法查询课程信息
PageResult<CourseBase> pageResult = courseBaseInfoService.queryCourseBaseList(pageParams, queryCourseParams);
return pageResult;
}
}
第六步: 在当前模块的api
接口工程中定义启动类,同时使用@EnableSwagger2Doc注解
启用Swagger
package com.xuecheng;
@EnableSwagger2Doc
@SpringBootApplication(scanBasePackages = "com.xuecheng")
public class ContentApiApplication {
public static void main(String[] args) {
SpringApplication.run(ContentApiApplication.class, args);
}
}
第七步: 运行api工程
的启动类ContentApiApplication
,即对外暴露API接口
,使用浏览器访问http://localhost:63040/content/swagger-ui.html查看接口信息
第八步: 在base工程的com.xuecheng.base.config
包下配置LocalDateTimeConfig
类指定json字符串与LocalDateTime类型
相互转换时的格式
@Configuration
public class LocalDateTimeConfig {
/*
* 序列化内容
* LocalDateTime -> String
* 服务端返回给客户端内容
* */
@Bean
public LocalDateTimeSerializer localDateTimeSerializer() {
return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
/*
* 反序列化内容
* String -> LocalDateTime
* 客户端传入服务端数据
* */
@Bean
public LocalDateTimeDeserializer localDateTimeDeserializer() {
return new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
// 配置
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> {
builder.serializerByType(LocalDateTime.class, localDateTimeSerializer());
builder.deserializerByType(LocalDateTime.class, localDateTimeDeserializer());
};
}
}
业务层环境搭建
service工程即业务层
负责为api接口工程
提供业务处理支撑,本项目的业务层包括了持久层的代码,也可以将持久层和业务层分为两个工程但需要增加成本
第一步: 将generator工程
或MyBatisX插件
自动生成数据库表的Mapper接口和XML映射文件并拷贝到service
工程的com.xuecheng.content.mapper
包下(注意修改包路径)
第二步: 在service
工程的pom.xml
中添加MP和数据库以及日志相关
的依赖
<dependencies>
<dependency>
<groupId>com.xuechenggroupId>
<artifactId>xuecheng-plus-content-modelartifactId>
<version>0.0.1-SNAPSHOTversion>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-contextartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-loggingartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-log4j2artifactId>
dependency>
dependencies>
第三步: 在service工程
的com.xuecheng.content.config
包下创建MybatisPlusConfig
配置类,配置扫描Mapper接口注解
和分页拦截器
/**
* Mybatis-Plus配置
*/
@Configuration
@MapperScan("com.xuecheng.content.mapper")
public class MybatisPlusConfig {
/**
* 定义分页拦截器
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
第四步: 在service
工程的test/resources
目录下创建所需要的配置文件log4j2-dev.xml(日志文件)
和bootstrap.yml(配置数据库连接信息)
spring:
#application:
#name: content-service
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/xc_content?serverTimezone=UTC&userUnicode=true&useSSL=false
username: root
password: 123456
# 日志文件配置路径
logging:
config: classpath:log4j2-dev.xml
第五步: 在service
工程的test
目录下添加启动类
package com.xuecheng.content;
@Slf4j
@SpringBootApplication
public class ContentApplication {
public static void main(String[] args) {
SpringApplication.run(ContentApplication.class, args);
}
}
第六步: 在service
工程的test目录
下对应Java目录
所在的包结构com.xuecheng.content
,然后编写测试类测试Mapper的功能
@Slf4j
@SpringBootTest
class CourseBaseMapperTests{
@Autowired
CourseBaseMapper courseBaseMapper;
@Test
public void testCourseBaseMapper() {
CourseBase courseBase = courseBaseMapper.selectById(22);
log.info("查询到数据:{}", courseBase);
Assertions.assertNotNull(courseBase);
}
}
业务层开发(service工程)
第一步: 使用IDEA自带的客户端连接MySQL,创建系统管理数据库xc_system
,执行xcplus_system.sql
脚本向创建的系统管理数据库导入数据
第二步: 编写Service接口及其实现类
package com.xuecheng.content.service;
// 课程基本信息管理业务接口
public interface CourseBaseInfoService {
/**
* @description 课程查询接口
* @param pageParams 分页参数
* @param queryCourseParamsDto 条件条件
* @return com.xuecheng.base.model.PageResult
* @author Mr.M
* @date 2022/9/6 21:44
*/
PageResult<CourseBase> queryCourseBaseList(PageParams pageParams, QueryCourseParamsDto queryCourseParamsDto);
}
package com.xuecheng.content.service.impl;
/**
* @description 课程信息管理业务接口实现类
* @author Mr.M
* @date 2022/9/6 21:45
* @version 1.0
*/
@Service
public class CourseBaseInfoServiceImpl implements CourseBaseInfoService {
@Autowired
CourseBaseMapper courseBaseMapper;
@Override
public PageResult<CourseBase> queryCourseBaseList(PageParams pageParams, QueryCourseParamsDto queryCourseParamsDto) {
//构建查询条件对象
LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
//构建查询条件,根据课程名称查询
queryWrapper.like(StringUtils.isNotEmpty(queryCourseParamsDto.getCourseName()),CourseBase::getName,
queryCourseParamsDto.getCourseName());
//构建查询条件,根据课程审核状态查询
queryWrapper.eq(StringUtils.isNotEmpty(queryCourseParamsDto.getAuditStatus()),CourseBase::getAuditStatus,
queryCourseParamsDto.getAuditStatus());
//构建查询条件,根据课程发布状态查询
queryWrapper.eq(StringUtils.isNotEmpty(queryCourseParams.getPublishStatus()), CourseBase::getStatus,
queryCourseParams.getPublishStatus());
//分页对象
Page<CourseBase> page = new Page<>(pageParams.getPageNo(), pageParams.getPageSize());
//查询数据内容获得结果
Page<CourseBase> pageResult = courseBaseMapper.selectPage(page, queryWrapper);
//获取数据列表
List<CourseBase> list = pageResult.getRecords();
//获取数据总数
long total = pageResult.getTotal();
//构建结果集封装到QueryCourseParamDto对象中
PageResult<CourseBase> courseBasePageResult = new PageResult<>(list, total, pageParams.getPageNo(), pageParams.getPageSize());
return courseBasePageResult;
}
}
在test
目录下编写测试类CourseBaseInfoServiceTests
测试courseBaseInfoService
@SpringBootTest
public class CourseBaseInfoServiceTests {
@Autowired
CourseBaseInfoService courseBaseInfoService;
@Test
void testCourseBaseInfoService() {
//查询条件
QueryCourseParamsDto queryCourseParamsDto = new QueryCourseParamsDto();
queryCourseParamsDto.setCourseName("java");
queryCourseParamsDto.setAuditStatus("202004");
queryCourseParamsDto.setPublishStatus("203001");
//分页参数
PageParams pageParams = new PageParams();
pageParams.setPageNo(1L);//页码
pageParams.setPageSize(3L);//每页记录数
/
PageResult<CourseBase> courseBasePageResult = courseBaseInfoService.queryCourseBaseList(pageParams, queryCourseParamsDto);
System.out.println(courseBasePageResult);
}
}
Swagger测试
第一步: 访问http://localhost:63040/content/swagger-ui.html, 打开Swagger文档输入查询条件进行测试
第二步: 查看请求响应的结果
Httpclient测试
使用Swagger
时每次测试都需要进入浏览器并且它并不能保存测试数据,所以IDEA提供了一个非常方便的http接口测试工具httpclient
第一步: 进入Controller类
并找到http接口对应的方法
第二步: 点击Generate request in HTTP Client
即可生成一个以.http结尾
的文件.它可以随着项目工程一起保存
第三步: 添加请求参数进行测试,注意请求和参数之间需要保留一个空白行
第四步: 观察控制台
查看响应结果
http://localhost:63040/course/list?pageNo=2&pageSize=10
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 07 Sep 2022 00:54:50 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{
"items": [
{
"id": 88,
"companyId": 1232141425,
"companyName": null,
"name": "1",
"users": "1",
"tags": "1",
"mt": "1-1",
"mtName": null,
"st": "1-1-1",
"stName": null,
"grade": "204001",
"teachmode": "200002",
"description": "1",
"pic": "http://r3zc5rung.hd-bkt.clouddn.com/cb1b6038-ef68-4362-8c29-a966886d1dc5sakUiFHLb5sRFdIK",
"createDate": "2021-12-27 20:14:53",
"changeDate": "2021-12-27 20:28:58",
"createPeople": null,
"changePeople": null,
"auditStatus": "202002",
"auditMind": null,
"auditNums": 0,
"auditDate": null,
"auditPeople": null,
"status": 1,
"coursePubId": null,
"coursePubDate": null
},
....
],
"counts": 14,
"page": 2,
"pageSize": 10
}
第五步: 为了方便保存.http文件
,我们单独在项目工程的根目录下
创建一个api-test
目录并以模块为单位创建.http文件
第六步: 为了方便将来和网关集成测试,我们可以创建配置文件http-client.env.json
并配置测试主机地址,文件名和位置固定,否则找不到对应的变量
{
"dev": {
"access_token": "",
"gateway_host": "localhost:63010",
"content_host": "localhost:63040",
"system_host": "localhost:63110",
"media_host": "localhost:63050",
"search_host": "localhost:63080",
"auth_host": "localhost:63070",
"checkcode_host": "localhost:63075",
"learning_host": "localhost:63020"
}
}
第七步: 在xc-content-api.http
文件中将http://localhost:63040用配置的content_host变量
代替