Spring Boot 实现审核功能,实战来了!

守听  金牌会员 | 2023-11-5 01:46:02 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 895|帖子 895|积分 2685

一、审核功能实现的方式

1、普通

方案:经办时入A表,审核后从A表读取数据,然后操作目标B表;
优势:思路简单
劣势:对后端功能实行高度的嵌入;审核功能数据操作不统一
2、弹框式

方案:前台实现,操作时判断是否需要权限控制,如果需要,则弹出框,由审核人员进行审核,审核通过后,进行后续操作。
优势:对后台功能无嵌入;可支持查询、导出、操作等全部功能;
劣势:需要经办人和审核人同时在场操作
3、入参缓冲时

方案:审核功能是独立的功能,前台发起业务后,入参存入数据库。待审核通过后,后台触发调用相应的接口,并将执行结果通知到经办人。
优势:对前后台功能均无嵌入;支持导出及操作类;经办人和审核人可以异步操作;审核功能数据操作统一;
劣势:需要框架层支持;实现逻辑稍微复杂
4、临时表

方案:所有需要审核功能涉及的表均增加相应的表,该表比源表主要增加1个字段,即审核流水,其余字段命名完全一致;所有功能操作时先入该表,审核通过后,由后台从该表将数据同步至正表。
优势:无需要框架支持;支持导出及操作类;经办人和审核人可以异步操作;审核功能数据操作统一;
劣势:对后端功能实行高度的嵌入;
Spring Boot 基础就不介绍了,推荐看这个实战项目:
https://github.com/javastacks/spring-boot-best-practice
二、SpringBoot实现

1.创建数据库表SQL
  1. CREATE TABLE `audit` (
  2.   `id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',
  3.   `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '报修名称',
  4.   `user` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '报修人',
  5.   `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '报修时间',
  6.   `img` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '详情图片',
  7.   `state` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT '待审核' COMMENT '待审核,审核通过,审核不通过',
  8.   PRIMARY KEY (`id`)
  9. ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
复制代码
2.写Java后端


其实审核功能最主要的就是我们的新增功能,用户只有新增过后,我们的管理员才能去对你的申请进行审核,最后实现效果。
AuditController
  1. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  2. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  3. import com.example.demo.common.Result;
  4. import com.example.demo.entity.Audit;
  5. import com.example.demo.entity.Sanitation;
  6. import com.example.demo.entity.User;
  7. import com.example.demo.mapper.FileMapper;
  8. import com.example.demo.service.IAuditService;
  9. import com.example.demo.utils.TokenUtils;
  10. import org.springframework.web.bind.annotation.*;
  11. import javax.annotation.Resource;
  12. import java.util.List;
  13. @CrossOrigin
  14. @RestController
  15. @RequestMapping("/audit")
  16. public class AuditController {
  17.     @Resource
  18.     private IAuditService auditService;
  19.     @Resource
  20.     private FileMapper fileMapper;
  21. //    //新增或者更新
  22. //    @PostMapping
  23. //    public Result save(@RequestBody Audit audit) {
  24. //        audit.setUser(TokenUtils.getCurrentUser().getUsername());
  25.         audit.setImg(Files.url);
  26. //        return Result.success(auditService.saveOrUpdate(audit));
  27. //    }
  28.     // 新增或者更新
  29.     @PostMapping
  30.     public Result save(@RequestBody Audit audit) {
  31.         if (audit.getId() == null) {
  32.             // 新增
  33.             audit.setUser(TokenUtils.getCurrentUser().getUsername());
  34.         }
  35.         auditService.saveOrUpdate(audit);
  36.         return Result.success();
  37.     }
  38.     //删除
  39. //    @DeleteMapping("/{id}")
  40. //    public Result delete(@PathVariable Integer id) {
  41. //        return Result.success(userService.removeById(id));
  42. //    }
  43.     @PostMapping("/del/batch")
  44.     public Result deleteBatch(@RequestBody List<Integer> ids) {//批量删除
  45.         return Result.success(auditService.removeByIds(ids));
  46.     }
  47.     //查询所有数据
  48.     @GetMapping
  49.     public Result findAll() {
  50.         return Result.success(auditService.list());
  51.     }
  52. //    @GetMapping("/role/{role}")
  53. //    public Result findNames(@PathVariable String role) {
  54. //        QueryWrapper<Audit> queryWrapper = new QueryWrapper<>();
  55. //        queryWrapper.eq("role", role);
  56. //        List<Audit> list = auditService.list(queryWrapper);
  57. //        return Result.success(list);
  58. //    }
  59.     @GetMapping("/{id}")
  60.     public Result findOne(@PathVariable Integer id) {
  61.         return Result.success(auditService.getById(id));
  62.     }
  63.     @GetMapping("/username/{username}")
  64.     public Result findByUsername(@PathVariable String username) {
  65.         QueryWrapper<Audit> queryWrapper = new QueryWrapper<>();
  66.         queryWrapper.eq("username", username);
  67.         return Result.success(auditService.getOne(queryWrapper));
  68.     }
  69.     @GetMapping("/page")
  70.     public Result findPage(@RequestParam Integer pageNum,
  71.                            @RequestParam Integer pageSize,
  72.                            @RequestParam(defaultValue = "") String name) {
  73.         QueryWrapper<Audit> queryWrapper = new QueryWrapper<>();
  74.         queryWrapper.orderByDesc("id");
  75.         if (!"".equals(name)) {
  76.             queryWrapper.like("name", name);
  77.         }
  78.         User currentUser = TokenUtils.getCurrentUser();
  79. //        if (RoleEnum.ROLE_USER.toString().equals(currentUser.getRole())) {  // 角色是普通用户
  80. //            queryWrapper.eq("user", currentUser.getUsername());
  81. //        }
  82.         return Result.success(auditService.page(new Page<>(pageNum, pageSize), queryWrapper));
  83.     }
  84. }
复制代码
三、前端调用

1.实现效果


2.核心代码

  1. <el-table-column label="审核" width="240">
  2.   <template v-slot="scope">
  3.     <el-button type="success" @click="changeState(scope.row, '审核通过...师傅正在赶来的路上')" :disabled="scope.row.state !== '待审核'">审核通过</el-button>
  4.     <el-button type="danger" @click="changeState(scope.row, '审核不通过')" :disabled="scope.row.state !== '待审核'">审核不通过</el-button>
  5.   </template>
  6. </el-table-column>
复制代码
3.后台管理


4.后台管理核心代码
  1. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  2. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  3. import com.example.demo.common.Result;
  4. import com.example.demo.entity.Audit;
  5. import com.example.demo.entity.User;
  6. import com.example.demo.mapper.FileMapper;
  7. import com.example.demo.service.IAuditService;
  8. import com.example.demo.utils.TokenUtils;
  9. import org.springframework.web.bind.annotation.*;
  10. import javax.annotation.Resource;
  11. import java.util.List;
  12. @CrossOrigin
  13. @RestController
  14. @RequestMapping("/audit")
  15. public class AuditController {
  16.     @Resource
  17.     private IAuditService auditService;
  18.     @Resource
  19.     private FileMapper fileMapper;
  20. //    //新增或者更新
  21. //    @PostMapping
  22. //    public Result save(@RequestBody Audit audit) {
  23. //        audit.setUser(TokenUtils.getCurrentUser().getUsername());
  24.         audit.setImg(Files.url);
  25. //        return Result.success(auditService.saveOrUpdate(audit));
  26. //    }
  27.     // 新增或者更新
  28.     @PostMapping
  29.     public Result save(@RequestBody Audit audit) {
  30.         if (audit.getId() == null) {
  31.             // 新增
  32.             audit.setUser(TokenUtils.getCurrentUser().getUsername());
  33.         }
  34.         auditService.saveOrUpdate(audit);
  35.         return Result.success();
  36.     }
  37.     //删除
  38. //    @DeleteMapping("/{id}")
  39. //    public Result delete(@PathVariable Integer id) {
  40. //        return Result.success(userService.removeById(id));
  41. //    }
  42.     @PostMapping("/del/batch")
  43.     public Result deleteBatch(@RequestBody List<Integer> ids) {//批量删除
  44.         return Result.success(auditService.removeByIds(ids));
  45.     }
  46.     //查询所有数据
  47.     @GetMapping
  48.     public Result findAll() {
  49.         return Result.success(auditService.list());
  50.     }
  51.     @GetMapping("/{id}")
  52.     public Result findOne(@PathVariable Integer id) {
  53.         return Result.success(auditService.getById(id));
  54.     }
  55.     @GetMapping("/username/{username}")
  56.     public Result findByUsername(@PathVariable String username) {
  57.         QueryWrapper<Audit> queryWrapper = new QueryWrapper<>();
  58.         queryWrapper.eq("username", username);
  59.         return Result.success(auditService.getOne(queryWrapper));
  60.     }
  61.     @GetMapping("/page")
  62.     public Result findPage(@RequestParam Integer pageNum,
  63.                            @RequestParam Integer pageSize,
  64.                            @RequestParam(defaultValue = "") String name) {
  65.         QueryWrapper<Audit> queryWrapper = new QueryWrapper<>();
  66.         queryWrapper.orderByDesc("id");
  67.         if (!"".equals(name)) {
  68.             queryWrapper.like("name", name);
  69.         }
  70.         User currentUser = TokenUtils.getCurrentUser();
  71. //        if (RoleEnum.ROLE_USER.toString().equals(currentUser.getRole())) {  // 角色是普通用户
  72. //            queryWrapper.eq("user", currentUser.getUsername());
  73. //        }
  74.         return Result.success(auditService.page(new Page<>(pageNum, pageSize), queryWrapper));
  75.     }
  76. }
复制代码
5.vue前台完整代码

(1)、前台功能页面
前台负责新增请求,然后保存请求之后,我们管理员审核通过之后就不可以编辑和删除我们的请求,我们会保留数据在前台页面
  1. <template>
  2.   
  3.    
  4.       <el-input  placeholder="请输入报修描述" clearable v-model="name" ></el-input>
  5.       <el-button  type="primary" @click="load"><i  />搜索</el-button>
  6.       <el-button type="warning" @click="reset"><i  />刷新</el-button>
  7.    
  8.    
  9.       <el-button type="primary" @click="handleAdd" ><i  />新增</el-button>
  10.       <el-popconfirm
  11.          
  12.           confirm-button-text='确认'
  13.           cancel-button-text='取消'
  14.           icon="el-icon-info"
  15.           icon-color="red"
  16.           title="确定批量删除这些信息吗?"
  17.           @confirm="delBatch">
  18.         <el-button type="danger" slot="reference" ><i  />删除</el-button>
  19.       </el-popconfirm>
  20.    
  21.     <el-table :data="tableData" border stripe :header-cell-class-name="headerBg"
  22.               @selection-change="handleSelectionChange">
  23.       <el-table-column type="selection" width="55"></el-table-column>
  24.       <el-table-column prop="name" label="报修描述" ></el-table-column>
  25.       <el-table-column prop="user" label="用户" ></el-table-column>
  26.       <el-table-column prop="createTime" label="创建时间" ></el-table-column>
  27.       <el-table-column label="图片">
  28.         <template slot-scope="scope">
  29.           <el-image  :src="scope.row.img" :preview-src-list="[scope.row.img]"></el-image>
  30.         </template>
  31.       </el-table-column>
  32.       <el-table-column prop="state" label="进度"></el-table-column>
  33.       <el-table-column label="操作">
  34.         <template slot-scope="scope">
  35.           <el-button type="success" @click="handleEdit(scope.row)" :disabled="scope.row.state !== '待审核'"><i  />编辑</el-button>
  36.         </template>
  37.       </el-table-column>
  38.     </el-table>
  39.    
  40.       <el-pagination
  41.           @size-change="handleSizeChange"
  42.           @current-change="handleCurrentChange"
  43.           :current-page="pageNum"
  44.           :page-sizes="[ 5, 10, 15]"
  45.           :page-size="pageSize"
  46.           layout="total, sizes, prev, pager, next, jumper"
  47.           :total="total">
  48.       </el-pagination>
  49.    
  50.     <el-dialog title="用户信息" :visible.sync="dialogFormVisible" width="30%">
  51.       <el-form label-width="100px" size="small">
  52.         <el-form-item label="报修描述" >
  53.           <el-input v-model="form.name" autocomplete="off"></el-input>
  54.         </el-form-item>
  55.         <el-form-item label="物品图片">
  56.           <el-upload action="http://localhost:9090/file/upload" ref="img" :on-success="handleImgUploadSuccess">
  57.             <el-button size="small" type="primary">点击上传</el-button>
  58.           </el-upload>
  59.         </el-form-item>
  60.       </el-form>
  61.       
  62.         <el-button @click="dialogFormVisible = false">取 消</el-button>
  63.         <el-button type="primary" @click="save">确 定</el-button>
  64.       
  65.     </el-dialog>
  66.   
  67. </template>
复制代码
(2)、后台管理功能页面
  1. <template>
  2.   
  3.    
  4.       <el-popconfirm
  5.          
  6.           confirm-button-text='确认'
  7.           cancel-button-text='取消'
  8.           icon="el-icon-info"
  9.           icon-color="red"
  10.           title="确定批量删除这些信息吗?"
  11.           @confirm="delBatch">
  12.         <el-button type="danger" slot="reference" ><i  />删除</el-button>
  13.       </el-popconfirm>
  14.    
  15.     <el-table :data="tableData" border stripe :header-cell-class-name="headerBg"
  16.               @selection-change="handleSelectionChange">
  17.       <el-table-column type="selection" width="55"></el-table-column>
  18.       <el-table-column prop="name" label="报修描述" ></el-table-column>
  19.       <el-table-column prop="user" label="用户" ></el-table-column>
  20.       <el-table-column prop="createTime" label="创建时间" ></el-table-column>
  21.       <el-table-column prop="img" label="详情图片" >
  22.         <template slot-scope="scope">
  23.           <el-image  :src="scope.row.img" :preview-src-list="[scope.row.img]"></el-image>
  24.         </template>
  25.       </el-table-column>
  26.       <el-table-column prop="state" label="进度"></el-table-column>
  27.       <el-table-column label="审核" width="240">
  28.         <template v-slot="scope">
  29.           <el-button type="success" @click="changeState(scope.row, '审核通过...师傅正在赶来的路上')" :disabled="scope.row.state !== '待审核'">审核通过</el-button>
  30.           <el-button type="danger" @click="changeState(scope.row, '审核不通过')" :disabled="scope.row.state !== '待审核'">审核不通过</el-button>
  31.         </template>
  32.       </el-table-column>
  33.     </el-table>
  34.    
  35.       <el-pagination
  36.           @size-change="handleSizeChange"
  37.           @current-change="handleCurrentChange"
  38.           :current-page="pageNum"
  39.           :page-sizes="[ 5, 10, 15]"
  40.           :page-size="pageSize"
  41.           layout="total, sizes, prev, pager, next, jumper"
  42.           :total="total">
  43.       </el-pagination>
  44.    
  45.   
  46. </template>
复制代码
重点!!!!图片上传

核心代码
  1. CREATE TABLE `file` (
  2.   `id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',
  3.   `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件名称',
  4.   `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件类型',
  5.   `size` bigint DEFAULT NULL COMMENT '文件大小(kb)',
  6.   `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '下载链接',
  7.   `md5` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件md5',
  8.   `creat_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '时间',
  9.   `is_delete` tinyint(1) DEFAULT '0' COMMENT '是否删除',
  10.   PRIMARY KEY (`id`) USING BTREE
  11. ) ENGINE=InnoDB AUTO_INCREMENT=115 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  12. import cn.hutool.core.io.FileUtil;
  13. import cn.hutool.core.util.IdUtil;
  14. import cn.hutool.core.util.StrUtil;
  15. import cn.hutool.crypto.SecureUtil;
  16. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  17. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  18. import com.example.demo.common.Constants;
  19. import com.example.demo.common.Result;
  20. import com.example.demo.entity.Files;
  21. import com.example.demo.mapper.FileMapper;
  22. import org.springframework.beans.factory.annotation.Autowired;
  23. import org.springframework.beans.factory.annotation.Value;
  24. import org.springframework.data.redis.core.StringRedisTemplate;
  25. import org.springframework.web.bind.annotation.*;
  26. import org.springframework.web.multipart.MultipartFile;
  27. import javax.annotation.Resource;
  28. import javax.servlet.ServletOutputStream;
  29. import javax.servlet.http.HttpServletResponse;
  30. import java.io.File;
  31. import java.io.IOException;
  32. import java.net.URLEncoder;
  33. import java.util.List;
  34. @RestController
  35. @RequestMapping("/file")
  36. public class FileController {
  37.     @Value("${files.upload.path}")
  38.     private String fileUploadPath;
  39.     @Value("${server.ip}")
  40.     private String serverIp;
  41.     @Resource
  42.     private FileMapper fileMapper;
  43.     @Autowired
  44.     private StringRedisTemplate stringRedisTemplate;
  45.     @PostMapping("/upload")
  46.     public String upload(@RequestParam MultipartFile file) throws IOException {
  47.         String originalFilename = file.getOriginalFilename();
  48.         String type = FileUtil.extName(originalFilename);
  49.         long size = file.getSize();
  50.         // 定义一个文件唯一的标识码
  51.         String fileUUID = IdUtil.fastSimpleUUID() + StrUtil.DOT + type;
  52.         File uploadFile = new File(fileUploadPath + fileUUID);
  53.         // 判断配置的文件目录是否存在,若不存在则创建一个新的文件目录
  54.         File parentFile = uploadFile.getParentFile();
  55.         //判断目录是否存在,不存在就新建
  56.         if (!parentFile.exists()) {
  57.              parentFile.mkdirs();
  58.         }
  59.         String url;
  60.         // 获取文件的md5
  61.         String md5 = SecureUtil.md5(file.getInputStream());
  62.         // 从数据库查询是否存在相同的记录
  63.         Files dbFiles = getFileByMd5(md5);
  64.         if (dbFiles != null) {
  65.             url = dbFiles.getUrl();
  66.         } else {
  67.             // 上传文件到磁盘
  68.             file.transferTo(uploadFile);
  69.             // 数据库若不存在重复文件,则不删除刚才上传的文件
  70.             url = "http://" + serverIp + ":9090/file/" + fileUUID;
  71.         }
  72.         //存储到数据库
  73.         Files saveFile = new Files();
  74.         saveFile.setName(originalFilename);
  75.         saveFile.setType(type);
  76.         saveFile.setSize(size/1024);
  77.         saveFile.setUrl(url);
  78.         saveFile.setMd5(md5);
  79.         fileMapper.insert(saveFile);
  80.         return url;
  81. //        String md5 = SecureUtil.md5(file.getInputStream());
  82. //        Files files = getFileByMd5(md5);
  83. //
  84. //        String url;
  85. //        if (files != null) {
  86. //            url = files.getUrl();
  87. //        } else {
  88. //            file.transferTo(uploadFile);
  89. //            url = "http://localhost:9090/file/" + fileUUID;
  90. //        }
  91. //        //存储到数据库
  92. //        Files saveFile = new Files();
  93. //        saveFile.setName(originalFilename);
  94. //        saveFile.setType(type);
  95. //        saveFile.setSize(size/1024);
  96. //        saveFile.setUrl(url);
  97. //        saveFile.setMd5(md5);
  98. //        fileMapper.insert(saveFile);
  99. //        return url;
  100.     }
  101.     @GetMapping("/{fileUUID}")
  102.     public void download(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
  103.         // 根据文件的唯一标识码获取文件
  104.         File uploadFile = new File(fileUploadPath + fileUUID);
  105.         // 设置输出流的格式
  106.         ServletOutputStream os = response.getOutputStream();
  107.         response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUID, "UTF-8"));
  108.         response.setContentType("application/octet-stream");
  109.         // 读取文件的字节流
  110.         os.write(FileUtil.readBytes(uploadFile));
  111.         os.flush();
  112.         os.close();
  113.     }
  114.     /**
  115.      * 通过文件的md5查询文件
  116.      * @param md5
  117.      * @return
  118.      */
  119.     private Files getFileByMd5(String md5) {
  120.         // 查询文件的md5是否存在
  121.         QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
  122.         queryWrapper.eq("md5", md5);
  123.         List<Files> filesList = fileMapper.selectList(queryWrapper);
  124.         return filesList.size() == 0 ? null : filesList.get(0);
  125.     }
  126.     //    @CachePut(value = "files", key = "'frontAll'")
  127.     @PostMapping("/update")
  128.     public Result update(@RequestBody Files files) {
  129.         fileMapper.updateById(files);
  130.         flushRedis(Constants.FILES_KEY);
  131.         return Result.success();
  132.     }
  133.     @GetMapping("/detail/{id}")
  134.     public Result getById(@PathVariable Integer id) {
  135.         return Result.success(fileMapper.selectById(id));
  136.     }
  137.     //清除一条缓存,key为要清空的数据
  138. //    @CacheEvict(value="files",key="'frontAll'")
  139.     @DeleteMapping("/{id}")
  140.     public Result delete(@PathVariable Integer id) {
  141.         Files files = fileMapper.selectById(id);
  142.         files.setIsDelete(true);
  143.         fileMapper.updateById(files);
  144.         flushRedis(Constants.FILES_KEY);
  145.         return Result.success();
  146.     }
  147.     @PostMapping("/del/batch")
  148.     public Result deleteBatch(@RequestBody List<Integer> ids) {
  149.         // select * from sys_file where id in (id,id,id...)
  150.         QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
  151.         queryWrapper.in("id", ids);
  152.         List<Files> files = fileMapper.selectList(queryWrapper);
  153.         for (Files file : files) {
  154.             file.setIsDelete(true);
  155.             fileMapper.updateById(file);
  156.         }
  157.         return Result.success();
  158.     }
  159.     /**
  160.      * 分页查询接口
  161.      * @param pageNum
  162.      * @param pageSize
  163.      * @param name
  164.      * @return
  165.      */
  166.     @GetMapping("/page")
  167.     public Result findPage(@RequestParam Integer pageNum,
  168.                            @RequestParam Integer pageSize,
  169.                            @RequestParam(defaultValue = "") String name) {
  170.         QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
  171.         // 查询未删除的记录
  172.         queryWrapper.eq("is_delete", false);
  173.         queryWrapper.orderByDesc("id");
  174.         if (!"".equals(name)) {
  175.             queryWrapper.like("name", name);
  176.         }
  177.         return Result.success(fileMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper));
  178.     }
  179.     // 删除缓存
  180.     private void flushRedis(String key) {
  181.         stringRedisTemplate.delete(key);
  182.     }
  183. }
复制代码
小结

以上就是对怎么利用SpringBoot实现审核功能简单的概述,让我们更加了解SpringBoot的作用,为我们的知识储备又加上一笔。
来源:blog.csdn.net/weixin_65950231/article/details/128756143
近期热文推荐:
1.1,000+ 道 Java面试题及答案整理(2022最新版)
2.劲爆!Java 协程要来了。。。
3.Spring Boot 2.x 教程,太全了!
4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!
5.《Java开发手册(嵩山版)》最新发布,速速下载!
觉得不错,别忘了随手点赞+转发哦!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

守听

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表