• SpringBoot SSMP整合案例


     简而言之:

     具体步骤如下:

    一、创建项目

    1、创建新模块,并勾选web与sql技术集:

    2、手动导入所需的额外依赖:

    1. <dependency>
    2. <groupId>com.baomidougroupId>
    3. <artifactId>mybatis-plus-boot-starterartifactId>
    4. <version>3.5.1version>
    5. dependency>
    6. <dependency>
    7. <groupId>com.alibabagroupId>
    8. <artifactId>druid-spring-boot-starterartifactId>
    9. <version>1.2.6version>
    10. dependency>
    11. <dependency>
    12. <groupId>org.projectlombokgroupId>
    13. <artifactId>lombokartifactId>
    14. dependency>

    3、修改配置文件:

    1. server:
    2. port: 80
    3. spring:
    4. datasource:
    5. druid:
    6. driver-class-name: com.mysql.cj.jdbc.Driver
    7. url: jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
    8. username: root
    9. password: mypassword
    10. mybatis-plus:
    11. configuration:
    12. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

    4、表:

    5、构建实体类:

    1. @Data
    2. @NoArgsConstructor
    3. @AllArgsConstructor
    4. @TableName("boot_book")
    5. public class Book extends Model {
    6. @TableId(type = IdType.AUTO)
    7. private Integer id;
    8. private String type;
    9. private String name;
    10. private String description;
    11. }

    二、数据层开发

    1、构建mapper接口:

    1. @Mapper
    2. public interface BookMapper extends BaseMapper {
    3. }

    2、配置文件中开启日志,并设置为标准输出:

    1. mybatis-plus:
    2. configuration:
    3. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

    3、配置MP分页插件:

    由于没有applicationContext.xml,配置方法与传统MP不同

    1. package com.kvno.config;
    2. import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    3. import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    4. import org.springframework.context.annotation.Bean;
    5. import org.springframework.context.annotation.Configuration;
    6. @Configuration
    7. public class MPConfig {
    8. //分页插件
    9. @Bean
    10. public MybatisPlusInterceptor mybatisPlusInterceptor(){
    11. MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    12. interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
    13. return interceptor;
    14. }
    15. }

    4、编写测试类:

    1. @SpringBootTest
    2. public class MapperTestCase {
    3. @Autowired
    4. BookMapper bookMapper;
    5. @Test
    6. public void testGetById() {
    7. System.out.println(bookMapper.selectById(1));
    8. }
    9. @Test
    10. public void testInsert() {
    11. Book book = new Book();
    12. book.setName("海绵宝宝");
    13. book.setType("CH");
    14. book.setDescription("yellow");
    15. boolean result = book.insert();
    16. System.out.println(result);
    17. }
    18. @Test
    19. public void testUpdate() {
    20. Book book = new Book();
    21. book.setId(3);
    22. book.setName("海绵宝宝");
    23. book.setType("CH");
    24. book.setDescription("square");
    25. boolean result = book.updateById();
    26. System.out.println(result);
    27. }
    28. @Test
    29. public void testGetAll() {
    30. List books = bookMapper.selectList(null);
    31. for (Book book: books) {
    32. System.out.println(book);
    33. }
    34. }
    35. @Test
    36. public void testGetPage() {
    37. IPage page = new Page<>(1,1);
    38. bookMapper.selectPage(page,null);
    39. System.out.println(page.getCurrent());
    40. System.out.println(page.getSize());
    41. System.out.println(page.getTotal());
    42. System.out.println(page.getPages());
    43. System.out.println(page.getRecords());
    44. }
    45. @Test
    46. public void testWrapper() {
    47. QueryWrapper userQueryWrapper = new QueryWrapper<>();
    48. userQueryWrapper.eq("type","CH");
    49. bookMapper.selectList(userQueryWrapper);
    50. }
    51. }

    三、业务层开发

     1、定义接口并编写实现类:

    1. public interface BookService {
    2. Boolean insert(Book book);
    3. Boolean update(Book book);
    4. Boolean delete(Integer id);
    5. Book getById(Integer id);
    6. List getAll();
    7. IPage getPage(Integer currentpage,Integer sizePage);
    8. }
    1. @Service
    2. public class BookServiceImpl implements BookService {
    3. @Autowired
    4. private BookMapper bookMapper;
    5. @Override
    6. public Boolean insert(Book book) {
    7. return book.insert();
    8. }
    9. @Override
    10. public Boolean update(Book book) {
    11. return book.updateById();
    12. }
    13. @Override
    14. public Boolean delete(Integer id) {
    15. return bookMapper.deleteById(id) > 0;
    16. }
    17. @Override
    18. public Book getById(Integer id) {
    19. return bookMapper.selectById(id);
    20. }
    21. @Override
    22. public List getAll() {
    23. return bookMapper.selectList(null);
    24. }
    25. @Override
    26. public IPage getPage(Integer currentpage, Integer sizePage) {
    27. IPage page = new Page(currentpage,sizePage);
    28. return bookMapper.selectPage(page,null);
    29. }
    30. }

    2、编写测试类:

    1. @SpringBootTest
    2. public class ServiceTestCase {
    3. @Autowired
    4. private BookService bookService;
    5. @Test
    6. void testGetById() {
    7. System.out.println(bookService.getById(1));
    8. }
    9. @Test
    10. public void testInsert() {
    11. Book book = new Book();
    12. book.setName("test");
    13. book.setType("CH");
    14. book.setDescription("service");
    15. bookService.insert(book);
    16. }
    17. @Test
    18. void testUpdate(){
    19. Book book = new Book();
    20. book.setId(4);
    21. book.setDescription("测试数据service");
    22. bookService.update(book);
    23. }
    24. @Test
    25. void testDelete(){
    26. bookService.delete(4);
    27. }
    28. @Test
    29. void testGetAll(){
    30. bookService.getAll();
    31. }
    32. @Test
    33. public void testGetPage() {
    34. IPage page = bookService.getPage(2,1);
    35. System.out.println(page.getCurrent());
    36. System.out.println(page.getSize());
    37. System.out.println(page.getTotal());
    38. System.out.println(page.getPages());
    39. System.out.println(page.getRecords());
    40. }
    41. }

    快速开发方案

    • 使用MyBatisPlus提供有业务层通用接口(ISerivce)快速开发service接口,使用业务层通用实现类(ServiceImpl)快速开发service实现类;

    • 在通用类基础上做功能重载或功能追加;

    • 可以编写额外方法,注意重载时不要覆盖原始操作,避免原始提供的功能丢失。

    与MP提供的BaseMapper类似,封装了各种业务层方法。简化了开发过程。

    1、接口与实现类:

    1. public interface IBookService extends IService {
    2. boolean saveBook(Book book);
    3. IPage getPage(int currentPage, int pageSize, Book book);
    4. }
    1. @Service
    2. public class QuickBookServiceImp extends ServiceImpl implements IBookService {
    3. @Autowired
    4. private BookMapper bookMapper;
    5. @Override
    6. public boolean saveBook(Book book) {
    7. return bookMapper.insert(book) > 0;
    8. }
    9. @Override
    10. public IPage getPage(int currentPage, int pageSize, Book book) {
    11. LambdaQueryWrapper wrapper = new LambdaQueryWrapper();
    12. wrapper.like(Strings.isNotEmpty(book.getType()),Book::getType,book.getType());
    13. wrapper.like(Strings.isNotEmpty(book.getName()),Book::getName,book.getName());
    14. wrapper.like(Strings.isNotEmpty(book.getDescription()),Book::getDescription,book.getDescription());
    15. IPage page = new Page(currentPage,pageSize);
    16. bookMapper.selectPage(page,wrapper);
    17. return page;
    18. }
    19. }

    2、测试:

    1. @SpringBootTest
    2. public class QuickServiceTestCase {
    3. @Autowired
    4. private IBookService bookService;
    5. @Test
    6. void testGetById() {
    7. System.out.println(bookService.getById(1));
    8. }
    9. @Test
    10. public void testSave() {
    11. Book book = new Book();
    12. book.setName("test");
    13. book.setType("CH");
    14. book.setDescription("service");
    15. bookService.save(book);
    16. }
    17. @Test
    18. void testUpdate(){
    19. Book book = new Book();
    20. book.setId(4);
    21. book.setDescription("测试数据service");
    22. bookService.updateById(book);
    23. }
    24. @Test
    25. void testDelete(){
    26. bookService.removeById(4);
    27. }
    28. @Test
    29. void testGetAll(){
    30. bookService.list();
    31. }
    32. @Test
    33. public void testGetPage() {
    34. IPage page = new Page(2,1);
    35. bookService.page(page);
    36. System.out.println(page.getCurrent());
    37. System.out.println(page.getSize());
    38. System.out.println(page.getTotal());
    39. System.out.println(page.getPages());
    40. System.out.println(page.getRecords());
    41. }
    42. }

    四、表现层开发

    • 基于Restful进行表现层接口开发
    • 使用Postman测试接口功能

    表现层业务接口测试

    1、编写controller:

    注:@RequestBody:接收前端传递给后端的请求体中的数据。

    1. /*
    2. 表现层 测试业务层接口
    3. @RequestBody:接收前端传递给后端的请求体中的数据
    4. */
    5. //@RestController
    6. @RequestMapping("/books")
    7. public class BookControllerTest {
    8. @Autowired
    9. private IBookService bookService;
    10. @GetMapping
    11. public List getAll() {
    12. return bookService.list();
    13. }
    14. @PostMapping
    15. public Boolean save(@RequestBody Book book) { //@RequestBody
    16. return bookService.save(book);
    17. }
    18. @PutMapping
    19. public Boolean update(@RequestBody Book book) {
    20. return bookService.updateById(book);
    21. }
    22. @DeleteMapping("/{id}")
    23. public Boolean delete(@PathVariable(value = "id") Integer id) {
    24. return bookService.removeById(id);
    25. }
    26. @GetMapping("/{id}")
    27. public Book getById(@PathVariable(value = "id") Integer id) {
    28. return bookService.getById(id);
    29. }
    30. @GetMapping("/{currentPage}/{pageSize}")
    31. public IPage getPage(@PathVariable int currentPage, @PathVariable int pageSize){
    32. IPage page = new Page(currentPage,pageSize);
    33. return bookService.page(page);
    34. }
    35. }

    2、测试:

    表现层消息一致性处理

    返回数据类型不一致会给前端带来不便:

     单纯地封装数据又会造成误解,如数据为null时:

     故采用以下格式:

    优点:

    示例:

    1、设计表现层返回结果的模型类,用于后端与前端进行数据格式统一,也称为前后端数据协议:

    1. /*
    2. 统一表现层响应的数据返回值类型
    3. */
    4. @Data
    5. @NoArgsConstructor
    6. @AllArgsConstructor
    7. public class R { //Result
    8. private Boolean flag;
    9. private Object data;
    10. public R(Boolean flag) {
    11. this.flag = flag;
    12. }
    13. }

    2、编写controller:

    1. /*
    2. 统一了返回值类型的正式版表现层
    3. */
    4. @RestController
    5. @RequestMapping("/books")
    6. public class BookController {
    7. @Autowired
    8. private IBookService bookService;
    9. @GetMapping
    10. public R getAll() {
    11. return new R(true,bookService.list());
    12. }
    13. @PostMapping
    14. public R save(@RequestBody Book book) { //@RequestBody:接收前端传递给后端的请求体中的数据
    15. return new R(bookService.save(book));
    16. }
    17. @PutMapping
    18. public R update(@RequestBody Book book) {
    19. return new R(bookService.updateById(book));
    20. }
    21. @DeleteMapping("/{id}")
    22. public R delete(@PathVariable(value = "id") Integer id) {
    23. return new R(bookService.removeById(id));
    24. }
    25. @GetMapping("/{id}")
    26. public R getById(@PathVariable(value = "id") Integer id) {
    27. return new R(true,bookService.getById(id));
    28. }
    29. @GetMapping("/{currentPage}/{pageSize}")
    30. public R getPage(@PathVariable int currentPage, @PathVariable int pageSize){
    31. return new R(true,bookService.page(new Page(currentPage,pageSize)));
    32. }
    33. }

    3、测试:

     

     

    异常消息一致性处理

    1、使用注解@RestControllerAdvice定义SpringMVC异常处理器,异常处理器必须被扫描加载,否则无法生效;对异常消息进行统一处理,出现异常后返回指定类型:

    1. @RestControllerAdvice
    2. public class ProjectExceptionAdvice {
    3. //拦截所有的异常信息
    4. @ExceptionHandler(Exception.class)
    5. public R doException(Exception ex){
    6. //记录日志
    7. //通知运维
    8. //通知开发
    9. ex.printStackTrace(); //控制台仍然要显示异常
    10. return new R(false,"服务器故障,请稍后再试!");
    11. }
    12. }

    2、修改表现层返回结果的模型类,封装出现异常后对应的信息:

    1. @Data
    2. @NoArgsConstructor
    3. @AllArgsConstructor
    4. public class R { //Result
    5. private Boolean flag;
    6. private Object data;
    7. private String msg;
    8. public R(Boolean flag) {
    9. this.flag = flag;
    10. }
    11. public R(Boolean flag,Object data) {
    12. this.flag = flag;
    13. this.data = data;
    14. }
    15. public R(Boolean flag,String msg) {
    16. this.flag = flag;
    17. this.msg = msg;
    18. }
    19. }

    五、前端页面开发

    前后端分离结构设计中页面归属前端服务器,但本案例是但服务器结构,故将页面放在项目工程resources 目录下的 static 目录中,建议放置完后执行Maven的clean命令:

    页面html:

    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <title>SpringBoot整合SSM案例title>
    7. <meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport">
    8. <link rel="stylesheet" href="../plugins/elementui/index.css">
    9. <link rel="stylesheet" href="../plugins/font-awesome/css/font-awesome.min.css">
    10. <link rel="stylesheet" href="../css/style.css">
    11. head>
    12. <body class="hold-transition">
    13. <div id="app">
    14. <div class="content-header">
    15. <h1>图书管理h1>
    16. div>
    17. <div class="app-container">
    18. <div class="box">
    19. <div class="filter-container">
    20. <el-input placeholder="图书类别" v-model="pagination.type" style="width: 200px;" class="filter-item">el-input>
    21. <el-input placeholder="图书名称" v-model="pagination.name" style="width: 200px;" class="filter-item">el-input>
    22. <el-input placeholder="图书描述" v-model="pagination.description" style="width: 200px;" class="filter-item">el-input>
    23. <el-button @click="getAll()" class="dalfBut">查询el-button>
    24. <el-button type="primary" class="butT" @click="handleCreate()">新建el-button>
    25. div>
    26. <el-table size="small" current-row-key="id" :data="dataList" stripe highlight-current-row>
    27. <el-table-column type="index" align="center" label="序号">el-table-column>
    28. <el-table-column prop="type" label="图书类别" align="center">el-table-column>
    29. <el-table-column prop="name" label="图书名称" align="center">el-table-column>
    30. <el-table-column prop="description" label="描述" align="center">el-table-column>
    31. <el-table-column label="操作" align="center">
    32. <template slot-scope="scope">
    33. <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑el-button>
    34. <el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除el-button>
    35. template>
    36. el-table-column>
    37. el-table>
    38. <div class="pagination-container">
    39. <el-pagination
    40. class="pagiantion"
    41. layout="total, prev, pager, next, jumper"
    42. @current-change="handleCurrentChange"
    43. :current-page.sync="pagination.currentPage"
    44. :page-size="pagination.pageSize"
    45. :total="pagination.total">
    46. el-pagination>
    47. div>
    48. <div class="add-form">
    49. <el-dialog title="新增图书" :visible.sync="dialogFormVisible">
    50. <el-form ref="dataAddForm" :model="formData" :rules="rules" label-position="right" label-width="100px">
    51. <el-row>
    52. <el-col :span="12">
    53. <el-form-item label="图书类别" prop="type">
    54. <el-input v-model="formData.type"/>
    55. el-form-item>
    56. el-col>
    57. <el-col :span="12">
    58. <el-form-item label="图书名称" prop="name">
    59. <el-input v-model="formData.name"/>
    60. el-form-item>
    61. el-col>
    62. el-row>
    63. <el-row>
    64. <el-col :span="24">
    65. <el-form-item label="描述">
    66. <el-input v-model="formData.description" type="textarea">el-input>
    67. el-form-item>
    68. el-col>
    69. el-row>
    70. el-form>
    71. <div slot="footer" class="dialog-footer">
    72. <el-button @click="cancel()">取消el-button>
    73. <el-button type="primary" @click="handleAdd()">确定el-button>
    74. div>
    75. el-dialog>
    76. div>
    77. <div class="add-form">
    78. <el-dialog title="编辑检查项" :visible.sync="dialogFormVisible4Edit">
    79. <el-form ref="dataEditForm" :model="formData" :rules="rules" label-position="right" label-width="100px">
    80. <el-row>
    81. <el-col :span="12">
    82. <el-form-item label="图书类别" prop="type">
    83. <el-input v-model="formData.type"/>
    84. el-form-item>
    85. el-col>
    86. <el-col :span="12">
    87. <el-form-item label="图书名称" prop="name">
    88. <el-input v-model="formData.name"/>
    89. el-form-item>
    90. el-col>
    91. el-row>
    92. <el-row>
    93. <el-col :span="24">
    94. <el-form-item label="描述">
    95. <el-input v-model="formData.description" type="textarea">el-input>
    96. el-form-item>
    97. el-col>
    98. el-row>
    99. el-form>
    100. <div slot="footer" class="dialog-footer">
    101. <el-button @click="cancel()">取消el-button>
    102. <el-button type="primary" @click="handleEdit()">确定el-button>
    103. div>
    104. el-dialog>
    105. div>
    106. div>
    107. div>
    108. div>
    109. body>
    110. <script src="../js/vue.js">script>
    111. <script src="../plugins/elementui/index.js">script>
    112. <script type="text/javascript" src="../js/jquery.min.js">script>
    113. <script src="../js/axios-0.18.0.js">script>
    114. <script>
    115. var vue = new Vue({
    116. el: '#app',
    117. data:{
    118. dataList: [],//当前页要展示的列表数据
    119. dialogFormVisible: false,//添加表单是否可见
    120. dialogFormVisible4Edit:false,//编辑表单是否可见
    121. formData: {},//表单数据
    122. rules: {//校验规则
    123. type: [{ required: true, message: '图书类别为必填项', trigger: 'blur' }],
    124. name: [{ required: true, message: '图书名称为必填项', trigger: 'blur' }]
    125. },
    126. pagination: {//分页相关模型数据
    127. currentPage: 1,//当前页码
    128. pageSize:10,//每页显示的记录数
    129. total:0,//总记录数
    130. //条件查询
    131. type: "",
    132. name: "",
    133. description: ""
    134. },
    135. },
    136. //钩子函数,VUE对象初始化完成后自动执行,效果为每次打开页面都会执行该操作
    137. created() {
    138. this.getAll();
    139. },
    140. methods: {
    141. // //列表
    142. // getAll() {
    143. // //发送异步请求
    144. // axios.get("/books").then((res)=>{
    145. // // console.log(res.data);
    146. // this.dataList = res.data.data;
    147. // });
    148. // },
    149. //分页查询
    150. getAll() {
    151. //组织条件查询参数,拼接url请求地址
    152. param = "?type="+this.pagination.type;
    153. param +="&name="+this.pagination.name;
    154. param +="&description="+this.pagination.description;
    155. //发送异步请求
    156. axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+param).then((res)=>{
    157. this.pagination.pageSize = res.data.data.size;
    158. this.pagination.currentPage = res.data.data.current;
    159. this.pagination.total = res.data.data.total;
    160. this.dataList = res.data.data.records;
    161. });
    162. },
    163. //切换页码
    164. handleCurrentChange(currentPage) {
    165. //修改页码值为当前选中的页码值
    166. this.pagination.currentPage = currentPage;
    167. //执行查询
    168. this.getAll();
    169. },
    170. //弹出添加窗口
    171. handleCreate() {
    172. this.dialogFormVisible = true;
    173. this.resetForm(); //重置表单
    174. },
    175. //重置表单
    176. resetForm() {
    177. this.formData = {};
    178. },
    179. //添加
    180. handleAdd () {
    181. axios.post("/books",this.formData).then((res)=>{
    182. //判断当前操作是否成功
    183. if(res.data.flag){
    184. //1.关闭弹层
    185. this.dialogFormVisible = false;
    186. this.$message.success(res.data.msg);
    187. }else{
    188. this.$message.error(res.data.msg);
    189. }
    190. }).finally(()=>{
    191. //2.重新加载数据
    192. this.getAll();
    193. });
    194. },
    195. //取消
    196. cancel(){
    197. this.dialogFormVisible = false;
    198. this.dialogFormVisible4Edit = false;
    199. this.$message.info("当前操作取消");
    200. },
    201. // 删除
    202. handleDelete(row) {
    203. this.$confirm("此操作永久删除当前信息,是否继续?","提示",{type:"info"}).then(()=>{
    204. axios.delete("/books/"+row.id).then((res)=>{
    205. if(res.data.flag){
    206. this.$message.success("删除成功");
    207. }else{
    208. this.$message.error("数据同步失败,自动刷新");
    209. }
    210. }).finally(()=>{
    211. //2.重新加载数据
    212. this.getAll();
    213. });
    214. }).catch(()=>{
    215. this.$message.info("取消操作");
    216. });
    217. },
    218. //弹出编辑窗口
    219. handleUpdate(row) {
    220. axios.get("/books/"+row.id).then((res)=>{
    221. if(res.data.flag && res.data.data != null ){
    222. this.dialogFormVisible4Edit = true;
    223. this.formData = res.data.data;
    224. }else{
    225. this.$message.error("数据同步失败,自动刷新");
    226. }
    227. }).finally(()=>{
    228. //2.重新加载数据
    229. this.getAll();
    230. });
    231. },
    232. //修改
    233. handleEdit() {
    234. axios.put("/books",this.formData).then((res)=>{
    235. //判断当前操作是否成功
    236. if(res.data.flag){
    237. //1.关闭弹层
    238. this.dialogFormVisible4Edit = false;
    239. this.$message.success("修改成功");
    240. }else{
    241. this.$message.error("修改失败");
    242. }
    243. }).finally(()=>{
    244. //2.重新加载数据
    245. this.getAll();
    246. });
    247. },
    248. }
    249. })
    250. script>
    251. html>

    整合需求后的controller:

    1. @RestController
    2. @RequestMapping("/books")
    3. public class BookController {
    4. @Autowired
    5. private IBookService bookService;
    6. @GetMapping
    7. public R getAll() {
    8. return new R(true,bookService.list());
    9. }
    10. @PostMapping
    11. public R save(@RequestBody Book book) throws IOException { //@RequestBody:接收前端传递给后端的请求体中的数据
    12. //测试异常消息一致性处理
    13. /*if(book.getName().equals("123")) {
    14. throw new IOException();
    15. }*/
    16. Boolean flag = bookService.save(book);
    17. return new R(flag,flag ? "添加成功" : "添加失败");
    18. }
    19. @PutMapping
    20. public R update(@RequestBody Book book) {
    21. return new R(bookService.updateById(book));
    22. }
    23. @DeleteMapping("/{id}")
    24. public R delete(@PathVariable(value = "id") Integer id) {
    25. return new R(bookService.removeById(id));
    26. }
    27. @GetMapping("/{id}")
    28. public R getById(@PathVariable(value = "id") Integer id) {
    29. return new R(true,bookService.getById(id));
    30. }
    31. @GetMapping("/{currentPage}/{pageSize}")
    32. public R getPage(@PathVariable int currentPage, @PathVariable int pageSize,Book book){
    33. IPage page = bookService.getPage(currentPage, pageSize,book);
    34. //如果当前页码值大于了总页码值,那么重新执行查询操作,使用最大页码值作为当前页码值
    35. if( currentPage > page.getPages()){
    36. page = bookService.getPage((int)page.getPages(), pageSize,book);
    37. }
    38. return new R(true, page);
    39. }
    40. }

    效果:

    六、总结

    至此,SpringBoot基础篇学习完毕。

  • 相关阅读:
    vscode - 环境准备 - 修改缓存路径
    基于SqlSugar的开发框架循序渐进介绍(20)-- 在基于UniApp+Vue的移动端实现多条件查询的处理
    003. 电话号码的字母组合——回溯算法
    作为物联网技术最重要的数据采集入口,传感器将迎来巨大的发展良机?
    ARM异常处理(4):SVC和PendSV的作用详解
    Spring Boot之AJAX异步发送帖子
    公有云攻击案例
    简单总结下近期遇到的网络概念gcp、anycast IP、vlan
    insertAdjacentHTML() 作用
    使用IntelliJ Idea必备的插件!
  • 原文地址:https://blog.csdn.net/qq_57389269/article/details/126149458