基于ant design pro + springboot的后台管理系统
简介
在之前的Java快速学习找实习中曾经提到过,在学完springboot,理解从前端请求到后台响应的过程之后,可以尝试自己写一个后台管理系统,这次就来介绍如何快速创建一个管理系统,一小时完成基于单表增删改查的后台管理系统。
在实际的请求过程中,请求流程如下:
在我们自己创建管理系统时,可以采用数据库,后台,前端的开发过程。
企业项目开发流程
需求分析==> 系统设计 ==>技术选型 ==> 初始化 ==>编写业务代码 ==> 测试 ==> review ==> 部署 ==> 上线
注 因为后台管理系统过于简单,一般不用需求分析和系统设计
技术选型:ant design pro + springboot + mybatisplus +mysql
下面直接进入初始化
初始化
后端
1.使用 idea 新建一个springboot 项目
2.根据技术选型引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
3.运行项目
前端
1.创建 ant design pro 项目
npm i @ant-design/pro-cli -g
pro create myapp(项目名称)
2.下载依赖
cd myapp
npm install
3.执行项目
npm run start
数据库
库表设计应该在之前完成,但是对于单表的增删改查我们无需过多设计,只需考虑单表对应的实体类应该具有哪些属性,对应单表字段即可。这里提供一个例子,仅供参考。也是我后台管理系统用到的表。
create table t_book
(
book_id bigint not null comment '书籍id'
primary key,
book_name varchar(100) not null comment '书籍名称',
book_price decimal(5, 2) null comment '书籍价格',
book_count int default 0 null comment '书籍数量',
book_author varchar(50) null comment '书籍作者',
book_description varchar(1000) null comment '书籍简介',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
is_delete tinyint default 0 not null comment '是否删除'
)
comment '书籍表';
小技巧:可以尝试用chatgpt生成一些假数据添加到表中
编写业务代码
后端
正常情况下,我们需要写controller、service、mapper、entity,由于mybatisplus单表查询的优势,service、mapper、entity可以直接使用Mybatis-X插件生成
生成过程
之后我们需要自己编写controller,只需要了解springboot基本注解即可。
示例代码
package com.wdlm.demo.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wdlm.demo.pojo.Book;
import com.wdlm.demo.request.book.AddBookRequest;
import com.wdlm.demo.request.book.DeleteBookRequest;
import com.wdlm.demo.request.book.QueryBookRequest;
import com.wdlm.demo.request.book.UpdateBookRequest;
import com.wdlm.demo.response.Response;
import com.wdlm.demo.service.BookService;
import com.wdlm.demo.vo.BookVO;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/book")
public class BookController {
@Resource
private BookService bookService;
@PostMapping("/add")
public Response<Long> addBook(@RequestBody AddBookRequest addBookRequest) {
Book book = new Book();
BeanUtils.copyProperties(addBookRequest,book);
boolean isSave = bookService.save(book);
if (isSave) {
return new Response(1, book.getBookId(), "插入成功");
} else {
return new Response(-1, book.getBookId(), "插入失败");
}
}
@PostMapping("/delete")
public Response<Boolean> deleteBook(@RequestBody DeleteBookRequest deleteBookRequest) {
Long bookId = deleteBookRequest.getBookId();
boolean isDelete = bookService.removeById(bookId);
if (isDelete) {
return new Response(1, "删除成功");
} else {
return new Response(-1, "删除失败");
}
}
@PostMapping("/update")
public Response<Boolean> updateBook(@RequestBody UpdateBookRequest updateBookRequest) {
Book book = new Book();
BeanUtils.copyProperties(updateBookRequest,book);
boolean isUpdate = bookService.updateById(book);
if (isUpdate) {
return new Response(1, "更新成功");
} else {
return new Response(-1, "更新失败");
}
}
@GetMapping("/query")
public Response<List<BookVO>> getBook(@RequestBody QueryBookRequest queryBookRequest) {
String bookName = queryBookRequest.getBookName();
BigDecimal bookPrice = queryBookRequest.getBookPrice();
Integer bookCount = queryBookRequest.getBookCount();
String bookAuthor = queryBookRequest.getBookAuthor();
String bookDescription = queryBookRequest.getBookDescription();
Integer current = queryBookRequest.getCurrent();
Integer size = queryBookRequest.getSize();
if (current == null) {
current = 1;
}
if (size == null) {
size = 5;
}
QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
if (bookName!= null) {
queryWrapper.eq("book_name", bookName);
}
if (bookPrice!= null) {
queryWrapper.eq("book_price", bookPrice);
}
if (bookCount!= null) {
queryWrapper.eq("book_count", bookCount);
}
if (bookAuthor!= null) {
queryWrapper.eq("book_author", bookAuthor);
}
if (bookDescription!= null) {
queryWrapper.like("book_description", bookDescription);
}
IPage<Book> page = new Page<>(current,size);
IPage<Book> bookPage = bookService.page(page, queryWrapper);
if (bookPage == null) {
return new Response(-1, null, "查无所有");
}
List<Book> list = bookPage.getRecords();
List<BookVO> bookVOList = new ArrayList<>();
for (Book book : list) {
BookVO bookVO = new BookVO();
BeanUtils.copyProperties(book, bookVO);
bookVO.setBookId(String.valueOf(book.getBookId()));
bookVOList.add(bookVO);
}
return new Response(1, bookVOList, "查询成功");
}
}
规范写法:
1.对每个请求单独设置一个请求参数类
2.设置统一的响应类
3.设置统一的异常处理
前端
前端自动生成的代码中,已经包含了一个登录页面和一个查询表格,对于单表的增删改查来说已经足够了。我们需要做的是改造这两个界面,完成前后端联调。
ant design pro 提供了基于openapi,自动在前端生成后端接口的方式
首先需要后端提供接口文档
引入依赖
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
编写配置
package com.wdlm.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
@Profile({"dev", "test"})
public class Knife4jConfig {
@Bean
public Docket defaultApi2() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.title("接口文档")
.description("springboot-demo")
.version("1.0")
.build())
.select()
.apis(RequestHandlerSelectors.basePackage("com.wdlm.demo.controller"))
.paths(PathSelectors.any())
.paths(PathSelectors.regex("/error").negate())
.build();
}
}
启动后端项目,输入localhost:8888/api/doc.html,可以看到
输入localhost:8888/api/v3/api-docs可以获得接口文档json数据。
前端设置
在config.ts中设置接口文档地址
openAPI: [
{
requestLibPath: "import { request } from '@umijs/max'",
schemaPath: 'http://localhost:8888/api/v3/api-docs',
projectName: 'back-end-demo',
},
],
在package.json中执行
生成的接口在services目录下。
修改注册页面
修改查询表格
设置请求路径
之前requestErrorConfig中包含异常处理信息,可以在这里设置请求路径,并在app.tsx中导入,为了见名知意,将requestErrorConfig改为requestConfig
之所以设置withCredentials:true,是让前端携带cookie数据进行访问。注意,之后的项目启动采用npm run dev(不使用mock数据,直接请求后端)。
项目效果