尚庭公寓项目搭建
文章目录
一、 前端项目初始化
1.1 导入前端程序
使用vscode导入后台管理和移动端app前端程序即可!
1.2 下载启动依赖
npm install
注意: 因为依赖量较大,建议配置npm的镜像地址再进行下载!!
1.3 启动测试
npm run dev
1.4 明确接口访问地址
-
rentHouseAdmin
位置:
.env.development
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 VITE_APP_NODE_ENV='development' VITE_APP_TITLE='后台管理' VITE_APP_PORT=5174 VITE_APP_BASE_API='/admin' VITE_APP_BASE_URL='http://localhost:8080'
-
rentHouseH5
位置:
.env.development
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 VITE_APP_NODE_ENV='development' # 项目名称 VITE_API_TITLE='硅谷租房' VITE_APP_PORT=8888 #后端接口前缀 VITE_APP_BASE_API='/app' #后端接口地址 VITE_APP_BASE_URL='http://localhost:8081'
二、后台项目初始化
2.1 数据库初始化
-
创建数据库
在MySQL中创建一个
lease
数据库,建库语句如下CREATE DATABASE lease CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-
导入数据库脚本
将资料中的
lease.sql
脚本导入lease
数据库,其中包含了建表语句和少量的原始数据。
2.2 创建工程
按照如下目录结构创建一个多模块的Maven工程。
lease
├── common(公共模块——工具类、公用配置等)
│ ├── pom.xml
│ └── src
├── model(数据模型——与数据库相对应地实体类)
│ ├── pom.xml
│ └── src
├── web(Web模块)
│ ├── pom.xml
│ ├── web-admin(后台管理系统Web模块——包含mapper、service、controller)
│ │ ├── pom.xml
│ │ └── src
│ └── web-app(移动端Web模块——包含mapper、service、controller)
│ ├── pom.xml
│ └── src
└── pom.xml
各模块的pom.xml文件内容如下:
1. 根模块(lease)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atguigu</groupId>
<artifactId>lease</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>common</module>
<module>model</module>
<module>web</module>
</modules>
<name>lease</name>
</project>
2. common模块
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu</groupId>
<artifactId>lease</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>common</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
3. model模块
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu</groupId>
<artifactId>lease</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>model</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
4. web模块
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu</groupId>
<artifactId>lease</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>web</artifactId>
<packaging>pom</packaging>
<modules>
<module>web-admin</module>
<module>web-app</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
5. web-admin模块
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu</groupId>
<artifactId>web</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>web-admin</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
6. web-app模块
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu</groupId>
<artifactId>web</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>web-app</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
三、后台管理系统后端开发
3.1 项目初始配置
3.1.1 SpringBoot配置
1. pom文件配置
在**父工程(lease)**的pom.xml文件中增加如下内容
<!-- 继承Spring Boot父项目 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.5</version>
</parent>
<!-- 注意:直接替换pom文件中原有的properties -->
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<pagehelper.boot.version>2.0.0</pagehelper.boot.version>
<swagger.version>2.9.2</swagger.version>
<jwt.version>0.11.2</jwt.version>
<easycaptcha.version>1.6.2</easycaptcha.version>
<minio.version>8.2.0</minio.version>
<knife4j.version>4.1.0</knife4j.version>
<aliyun.sms.version>2.0.23</aliyun.sms.version>
</properties>
<!--配置dependencyManagement统一管理依赖版本-->
<dependencyManagement>
<dependencies>
<!--mybatis-plus 持久层-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- pagehelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.boot.version}</version>
</dependency>
<!--knife4j文档-->
<!--官方文档:https://doc.xiaominfo.com/docs/quick-start -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<!--JWT登录认证相关-->
<!--官方文档:https://github.com/jwtk/jjwt#install-jdk-maven -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<scope>runtime</scope>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<scope>runtime</scope>
<version>${jwt.version}</version>
</dependency>
<!--图形验证码-->
<!--官方文档:https://gitee.com/ele-admin/EasyCaptcha -->
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>${easycaptcha.version}</version>
</dependency>
<!--对象存储,用于存储图像等非结构化数据-->
<!--官方文档:https://min.io/docs/minio/linux/developers/minio-drivers.html?ref=docs#java-sdk -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>${minio.version}</version>
</dependency>
<!--阿里云短信客户端,用于发送短信验证码-->
<!--官方文档:https://help.aliyun.com/document_detail/215759.html?spm=a2c4g.215759.0.0.49f32807f4Yc0y -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<version>${aliyun.sms.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
在web模块的pom.xml文件中增加如下内容
- 依赖
<!--包含spring web相关依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--包含spring test相关依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
- 插件
<!-- Spring Boot Maven插件,用于打包可执行的JAR文件 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2. 创建application.yml文件
在web-admin模块的src/main/resources
目录下创建application.yml
配置文件,内容如下:
server:
port: 8080
3. 创建SpringBoot启动类
在web-admin模块下创建com.atguigu.lease.AdminWebApplication
类,内容如下:
@SpringBootApplication
public class AdminWebApplication {
public static void main(String[] args) {
SpringApplication.run(AdminWebApplication.class, args);
}
}
3.1.2 Mybatis-Plus配置
Mybatis-Plus为公用工具,故将其配置于common模块。具体配置可参考其官方文档。
1. pom文件配置
在common模块的pom.xml文件中增加如下内容:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
在model模块的pom.xml文件中增加如下内容:
因为model模块下的实体类中需要配置Mybatis-Plus相关注解,故也需引入Mybatis-Plus依赖
<!--mybatis-plus 持久层-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2. application.yml配置
在web-admin模块的application.yml
文件增加如下内容:
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:mysql://<hostname>:<port>/<database>?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2b8
username: <username>
password: <password>
hikari:
connection-test-query: SELECT 1 # 自动检测连接
connection-timeout: 60000 #数据库连接超时时间,默认30秒
idle-timeout: 500000 #空闲连接存活最大时间,默认600000(10分钟)
max-lifetime: 540000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
maximum-pool-size: 12 #连接池最大连接数,默认是10
minimum-idle: 10 #最小空闲连接数量
pool-name: SPHHikariPool # 连接池名称
#用于打印框架生成的sql语句,便于调试
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
注意:需根据实际情况修改hostname
、port
、database
、username
、password
。
3. 配置类
在common模块下创建com.atguigu.lease.common.mybatisplus.MybatisPlusConfiguration
类,内容如下:
@Configuration
@MapperScan("com.atguigu.lease.web.*.mapper")
public class MybatisPlusConfiguration {
}
注意:@MapperScan()
的包路径需要根据实际情况进行修改。
3.1.3 Knife4j配置
1. pom文件配置
在web模块的pom.xml文件添加如下内容(有瑕疵)
因为web-app模块和web-admin模块同样需要Knife4j依赖,故在两个的父工程引入依赖即可
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
</dependency>
在model模块的pom.xml文件添加上述内容
因为model模块下的实体类需要配置Knife4j相关注解,故也需引入Knife4j依赖。思考?
2. 配置类
后台管理系统和移动端的接口配置并不相同,所以需各自编写一个配置类。在web-admin模块下创建com.atguigu.lease.web.admin.custom.config.Knife4jConfiguration
类,内容如下:
@Configuration
public class Knife4jConfiguration {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI().info(
new Info()
.title("后台管理系统API")
.version("1.0")
.description("后台管理系统API"));
}
@Bean
public GroupedOpenApi systemAPI() {
return GroupedOpenApi.builder().group("系统信息管理").
pathsToMatch(
"/admin/system/**"
).
build();
}
@Bean
public GroupedOpenApi loginAPI() {
return GroupedOpenApi.builder().group("后台登录管理").
pathsToMatch(
"/admin/login/**",
"/admin/info"
).
build();
}
@Bean
public GroupedOpenApi apartmentAPI() {
return GroupedOpenApi.builder().group("公寓信息管理").
pathsToMatch(
"/admin/apartment/**",
"/admin/room/**",
"/admin/label/**",
"/admin/facility/**",
"/admin/fee/**",
"/admin/attr/**",
"/admin/payment/**",
"/admin/region/**",
"/admin/term/**",
"/admin/file/**"
).build();
}
@Bean
public GroupedOpenApi leaseAPI() {
return GroupedOpenApi.builder().group("租赁信息管理").
pathsToMatch(
"/admin/appointment/**",
"/admin/agreement/**"
).build();
}
@Bean
public GroupedOpenApi userAPI() {
return GroupedOpenApi.builder().group("平台用户管理").
pathsToMatch(
"/admin/user/**"
).build();
}
}
注意:pathsToMatch
参数需要根据实际情况进行配置。
3.2 生成或导入基础代码
在完成上述配置后,便可使用一些逆向工具自动生成基础代码了(例如实体类、mapper、service等),在使用Mybatis-Plus作为存储层框架时,推荐使用IDEA中的Mybatis X插件。除了可自动生成这些代码,也可直接导入资料中提供的代码。推荐大家直接导入。
导入的代码和目标位置如下:
导入代码 | 模块 | 包名/路径 | 说明 |
---|---|---|---|
实体类 | model | com.atguigu.lease.model.entity | 与数据库表一一对应 |
枚举类 | model | com.atguigu.lease.model.enums | 实体类中的某些状态类字段,使用枚举类型 |
mapper接口 | web-admin | com.atguigu.lease.web.admin.mapper | 略 |
mapper xml | web-admin | src/main/resources/mapper | 略 |
service | web-admin | com.atguigu.lease.web.admin.service | 略 |
serviceImpl | web-admin | com.atguigu.lease.web.admin.service.impl | 略 |
知识点:
-
实体类中的公共字段(例如
id
、create_time
、update_time
、is_deleted
)抽取到一个基类,进行统一管理,然后让各实体类继承该基类。 -
实体类中的状态字段(例如
status
)或类型字段(例如type
),全部使用枚举类型。状态(类型)字段,在数据库中通常用一个数字表示一个状态(类型)。例如:订单状态(1:待支付,2:待发货,3:待收货,4:已收货,5:已完结)。若实体类中对应的字段也用数字类型,例如
int
,那么程序中就会有大量的如下代码:order.setStatus(1); if (order.getStatus() == 1) { order.setStatus(2); }
这些代码后期维护起来会十分麻烦,所以本项目中所有的此类字段均使用枚举类型。例如上述订单状态可定义为以下枚举:
public enum Status { CANCEL(0, "已取消"), WAIT_PAY(1, "待支付"), WAIT_TRANSFER(2, "待发货"), WAIT_RECEIPT(3, "待收货"), RECEIVE(4, "已收货"), COMPLETE(5, "已完结"); private final Integer value; private final String desc; public Integer value() { return value; } public String desc() { return desc; } }
订单实体类中的状态字段定义为
Status
类型:@Data public class Order{ private Integer id; private Integer userId; private Status status; ... }
这样上述代码便可调整为如下效果,后期维护起来会容易许多。
order.setStatus(Status.WAIT_PAY);
-
所有的实体类均实现了
Serializable
接口,方便对实体对象进行缓存。 -
所有的
Mapper
接口均没有使用@Mapper
注解,而是使用@MapperScan
注解统一扫描。
3.3 导入接口定义代码
资料中提供了所有的Controller代码,并且Controller中定义好了每个接口(只有定义,没有实现),大家可直接导入接口定义相关的代码,然后只专注于接口逻辑的实现。
导入的代码和目标位置如下:
导入代码 | 模块 | 包名/路径 | 说明 |
---|---|---|---|
controller | web-admin | com.atguigu.lease.web.admin.controller | 略 |
vo | web-admin | com.atguigu.lease.web.admin.vo | View Object,用于封装或定义接口接受及返回的数据结构 |
result | common | com.atguigu.lease.common.result | 统一定义接口返回的数据结构 |
导入完成后,便可启动SpringBoot项目,并访问接口文档了,Knife4j文档的url为:http://localhost:8080/doc.html。
知识点:
-
vo(View Object):用于封装或定义接口接收及返回的数据的结构。
-
统一接口返回数据结构:为方便前端对接口数据进行处理,统一接口返回数据结构是一个良好的习惯。
以下是所有接口统一返回的数据结构
{ "code": 200, "message": "正常", "data": { "id": "1", "name": "zhangsan", "age": 10 } }
以下是与上述结构相对应的Java类
-
Result
@Data public class Result<T> { //返回码 private Integer code; //返回消息 private String message; //返回数据 private T data; public Result() { } private static <T> Result<T> build(T data) { Result<T> result = new Result<>(); if (data != null) result.setData(data); return result; } public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) { Result<T> result = build(body); result.setCode(resultCodeEnum.getCode()); result.setMessage(resultCodeEnum.getMessage()); return result; } public static <T> Result<T> ok(T data) { return build(data, ResultCodeEnum.SUCCESS); } public static <T> Result<T> ok() { return Result.ok(null); } public static <T> Result<T> fail() { return build(null, ResultCodeEnum.FAIL); } public static <T> Result<T> fail(Integer code, String message) { Result<T> result = build(null); result.setCode(code); result.setMessage(message); return result; } }
-
ResultCodeEnum
为方便管理,可将返回码
code
和返回消息message
封装到枚举类。@Getter public enum ResultCodeEnum { SUCCESS(200, "成功"), FAIL(201, "失败"), PARAM_ERROR(202, "参数不正确"), SERVICE_ERROR(203, "服务异常"), DATA_ERROR(204, "数据异常"), ILLEGAL_REQUEST(205, "非法请求"), REPEAT_SUBMIT(206, "重复提交"), DELETE_ERROR(207, "请先删除子集"), ADMIN_ACCOUNT_EXIST_ERROR(301, "账号已存在"), ADMIN_CAPTCHA_CODE_ERROR(302, "验证码错误"), ADMIN_CAPTCHA_CODE_EXPIRED(303, "验证码已过期"), ADMIN_CAPTCHA_CODE_NOT_FOUND(304, "未输入验证码"), ADMIN_LOGIN_AUTH(305, "未登陆"), ADMIN_ACCOUNT_NOT_EXIST_ERROR(306, "账号不存在"), ADMIN_ACCOUNT_ERROR(307, "用户名或密码错误"), ADMIN_ACCOUNT_DISABLED_ERROR(308, "该用户已被禁用"), ADMIN_ACCESS_FORBIDDEN(309, "无访问权限"), APP_LOGIN_AUTH(501, "未登陆"), APP_LOGIN_PHONE_EMPTY(502, "手机号码为空"), APP_LOGIN_CODE_EMPTY(503, "验证码为空"), APP_SEND_SMS_TOO_OFTEN(504, "验证法发送过于频繁"), APP_LOGIN_CODE_EXPIRED(505, "验证码已过期"), APP_LOGIN_CODE_ERROR(506, "验证码错误"), APP_ACCOUNT_DISABLED_ERROR(507, "该用户已被禁用"), TOKEN_EXPIRED(601, "token过期"), TOKEN_INVALID(602, "token非法"); private final Integer code; private final String message; ResultCodeEnum(Integer code, String message) { this.code = code; this.message = message; } }
注意:
由于
Result
和ResultCodeEnum
中使用@Data
、@Getter
注解,因此需要在common模块中引入lombok
依赖。<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
-