第2集 SpringBoot一天速成 (SpringBoot)

说明:SpringBoot一天速成不是口号,而在于您的基础。
1.此演示目的就是为了让大家速成。口号:“快快快狠”。
2.具备半年以上"SSM框架+Maven"实战经验的开发人员
3.跟着此系列博文《SpringBoot一天速成》练习一遍
4.这套演练包括工程的:持久层、服务层、web层,采用Intellej idea工具。
5.所有源码和资料免费提供给读者,需要的留言。
6.笔者将实践过程中遇到的问题与大家分享,让大家少走弯路。(请阅读注释部分)

SpringBoot是干嘛的?“简化开发,独立运行”,瞄准的目标:微服务。下面是官方原话:

  Spring Boot makes it easy to create stand-alone, production-grade Spring based 
  Applications  that you can "just run". 
  We take an opinionated view of the Spring platform and third-party libraries     
   so you can get started with minimum fuss. Most Spring Boot applications need very 
   little Spring configuration.

*====>>> 接着第1集,此演练开始编写Web层内容:Controller和视图模板thymeleaf(替代jsp)*……
声明:@author:拈花为何不一笑,“这是一套演练对于细节方面,需要读者自己完善。”
Web层完成后的效果图(包涵笔者拙劣的.css)
在这里插入图片描述

在这里插入图片描述

要完成以上功能,需要编写以下代码
  1. pom.xml引入springmvc和thymeleaf(当然也可以在创建工程时使用Spring Initailizr初始化这两模块)

     <!-- 引入spring-boot-starter-web,那么就提供了SpringMVC支持了 -->
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
    
     <!-- 视图模板使用thymeleaf -->
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
     </dependency>
    

    打开maven依赖,查看下spring-boot-starter-web依赖了哪些jar,如图:
    在这里插入图片描述

    再看看thymeleaf(目前这个模板的性能是相对比较差的)依赖了哪些jar,如下图:
    在这里插入图片描述

    2.在src/main/resources目录下分别创建两个目录:templates和static
    在这里插入图片描述

入口类
===>>> Springboot4Application.java

 package org.it.springboot4;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * SpingBoot(Spring、SpringMVC) + Mybatis 演练
 * 入口类,启动内置Tomcat服务器,初始化等。
 *  配置好文件后,启动服务器报ERROR:
 *      Warning:java: 无法找到类型 'org.junit.jupiter.api.extension.ExtendWith' 的注释方法 'value()':
 *      找不到org.junit.jupiter.api.extension.ExtendWith的类文件
 *  解决方案:    右键-->pom.xml-->Maven-->Reimport即可解决此问题
 */
@MapperScan("org.it.springboot4.mapper")//扫描包(Mybatis对应的mapper包)
@SpringBootApplication
public class Springboot4Application {


    public static void main(String[] args) {
        SpringApplication.run(Springboot4Application.class, args);
    }

}

2.1 templates中放thymeleaf模板文件(.html文件),这个模板的数据通常来源于Controller
响应的数据
2.2 static目录中放.js和.css及图片之类的数据
2.3 编写SpringMVC控制器EmpController.java(位置:org.it.springboot4.controller)
源码如下:

 package org.it.springboot4.controller;

import com.sun.org.apache.xpath.internal.operations.Mod;
import org.it.springboot4.entity.Emp;
import org.it.springboot4.entity.custom.EmpCustom;
import org.it.springboot4.service.EmpService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.rmi.MarshalledObject;
import java.util.List;
import java.util.Map;

/**
 *演示增删改查
 */
@RestController
@RequestMapping("/emp")
public class EmpController {

    private Logger empLog = LoggerFactory.getLogger(EmpController.class);

    @Autowired
    private EmpService empService;

    //访问url: http://localhost:8080/emp/3
    @GetMapping("/{id}")
    public ModelAndView findEmpById(@PathVariable("id") Integer empno){
        ModelAndView modelAndView = new ModelAndView();
        Emp emp = empService.getEmpById(empno);
        modelAndView.addObject("emp",emp);
        modelAndView.setViewName("emp");//springboot中thymeleaf默认后缀.html,服务器转发至/emp.html中
        return modelAndView;
    }


    //1.此方法getEmpByDeptnoSal对应的sql,还可以查询员工列表信息(当不含任何查询条件时),所以这里就不写员工列表方法了
    //2.在templates目录下创建模板empList.html文件,具体内容参阅empList.html
    @GetMapping("/empList")
    public ModelAndView findEmpList(EmpCustom empCustom){
        ModelAndView modelAndView = new ModelAndView();
        //这里使用Map来替换javaBean(比如Emp),用法有点类似于ibtis存储过程或jdbc存储过程 Map作为既作为参数又同时存储返回的结果数据,
        // 这里是一个个的Map.Entry对象,是一种键值对数据,其实返回的javaBean也是通过成员属性来存储值的,键是属性名值是值本身。.
        List<Map> emps = empService.getEmpByDeptnoSal(empCustom);
        modelAndView.addObject("emps",emps);
        modelAndView.setViewName("empList");
        return modelAndView;
    }

    @GetMapping("/deptnosal")//此方法虽然是在restful风格之下,但是仍然可以混用传统Http请求方式,如/deptnosal?deptno=xxx&sal=yyy
    //请在浏览器地址栏输入http://localhost:8080/emp/deptnosal?dname=RESEARCH&sal=6600(DB中的数据,如有需要可分享sql脚本给读者)
    //与前端表单进行参数绑定(即映射到EmpCustom中)时,无需要包装类,而List参数绑定需要包装类包装
     public List<Map> findEmpByDeptnoSal(EmpCustom empCustom){
        List<Map> list = empService.getEmpByDeptnoSal(empCustom);
        return list;
    }

    //添加员工页面
    @GetMapping("/addEmpUI")//注解漏掉不写,或者写错成@PostMapping都会报String不能转化成Integer异常
    public ModelAndView addEmpUI(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("addEmpUI");
        return  modelAndView;
        //采用String 返回return "forward:/addEmpUI.html"; json化无法进行服务器转发,因为类上标的是@RestController
    }

    //添加一名新员工
    @PostMapping("/addEmp")//玩一个工具PostMan,模拟视图层的Http请求,现在禁用了
    public ModelAndView addEmp(Emp emp){
        ModelAndView modelAndView = new ModelAndView();
        Integer num = 0;
        if(emp != null){
            num = this.empService.insertEmp(emp);
        }
        //modelAndView.addObject("iRecord",num);//设置重定向所带参数,供其它业务使用
        modelAndView.setViewName("redirect:/emp/empList");//重定向,查询员工列表
        return modelAndView;
    }


    //创建并映射Emp,由mysql数据库生成的empno映射到当前对象e.empno中,这种用法通常用于级联增加或删除。
    @GetMapping("/addGetEmp")
    @ResponseBody
    public Emp addGetEmp(Emp emp){
        //简单模拟前端数据
        //empname,hiredate,job,mgr,sal,comm,deptno
        Emp e = new Emp();
        e.setEname("刘宇夫");
        e.setHiredate(java.sql.Date.valueOf("2016-3-2"));
        e.setJob("SALES");
        e.setMgr(3);
        e.setSal(6500f);
        e.setComm(200f);
        e.setDeptno(20);
        //创建并映射Emp,由mysql数据库生成的empno映射到当前对象e.empno中
        this.empService.insertGetEmp(e);
        return e;
    }


    //删除员工(对于增删改,mybatis默认会返回影响表的记录条数)
    //由于使用Map作为参数绑定,黑盒子效果,没有empno键: http://localhost:8080/emp/deleteEmp?empno=8 删除不成功
    @GetMapping("/deleteEmp")
    public ModelAndView deleteEmp(@RequestParam Map paramMap){//Map参数绑定,莫要忘记@RequestParam,否则绑定不成功
        ModelAndView modelAndView = new ModelAndView();
        //如果没有指定删除条件,那是万万不能执行删除DB中的数据的,除非数据大清洗即便如此还要必须先进行备份。(谨慎!切记!)
        //使用Map作为参数,对外就是个黑盒子,其他人并不清楚传递怎样的参数,不建议使用,只作演示。
        if(paramMap != null  && paramMap.get("currentEmpno") != null){
            empLog.debug("empno:" + paramMap.get("currentEmpno"));

            Integer iRecord = this.empService.deleteEmp(paramMap);
            //modelAndView.addObject("iRecord",iRecord);设置数据,重定向可以作为参数
            modelAndView.setViewName("redirect:/emp/empList");//重定向,查询员工列表
        }
        return modelAndView;
    }

    //更新员工页面
    @GetMapping("/updateEmpUI/{empno}")
    public ModelAndView addEmpUI(@PathVariable("empno") Integer empno){
        ModelAndView modelAndView = new ModelAndView();

        //查询需要更新的员工信息,展示更新面板updateEmpUI.html中
        if(empno != null){
            Emp emp = this.empService.getEmpById(empno);
            modelAndView.addObject("emp",emp);
            modelAndView.setViewName("updateEmpUI");
        }
        return  modelAndView;
    }


    //更新员工
    @PostMapping("/updateEmp")
    public ModelAndView updateEmp(Emp emp){
        ModelAndView modelAndView = new ModelAndView();

        //如果没有需要更新的数据,何必还要访问数据库,直接返回
        if(emp != null && emp.getEmpno() != null){
            //这里遇到一个异常:笔者大意了在EmpMapper.xml中,拿日期跟空字符串进行了比较
            //java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
            //导致下面的更新sql抛出异常
            // <if test="hiredate != null and hiredate !=''">,解决方案:去掉 and hiredate !=''
            Integer iRecord = this.empService.updateEmp(emp);
            //modelAndView.addObject("iRecord",iRecord);
            modelAndView.setViewName("redirect:/emp/empList");//重定向,查询员工列表
        }
        return modelAndView;
    }

    /**
     * 1.类比一下JPA或hibernate它们操作DB的思想是面向对象和对象缓存:先把记录从DB中查询出来映射到对象,再操作对象,
     *      当然咯,它们分别还提供了自己的JPQL,HQL以及原生SQL,估计设计之初就想到框架本身在与DB交互时不可能包罗万象。
     * 2.mybatis虽然是一个非标准的ORM,它的思想是面向sql和对象缓存:
     *      通过sql直接与DB交互,然后借助自身缓存或它提供的二级缓存与Redis之类工具组合实现java对象进行缓存的效果。
     * 3.优缺点对象:
     *      (3.1)mybatis的优点是sql调优方便,更加适应敏捷开发,适合大中小型互联网项目(需求变化大),
     *          而hiberante贯彻的是DB皆对象,它的开发效率和可移植性非常强,适应于中小型且需求变化少的企业项目比如OA项目。
     *      (3.2)mybatis缺点,对高性能sql门槛比较高,hibernate入门门槛比较高且不支持数据库中某些方言,在性能优化方面相对比较差,
     *          不论如何hibernate曾经辉煌过且创始人被邀入Sun公司成为其中重要成员之一。
     */

}

2.4编写thymeleaf模板文件(empList.html, emp.html, addEmpUI.html, updateEmpUI.html),这里面包含thymeleaf大部分日常用法。

====>>>empList.html

 <!DOCTYPE html>
<!-- 引入thymeleaf命名空间 -->
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8">
    <!--简单样式表 -->
    <style type="text/css">
       td{
            background-color: #FFEBCD;
            margin-left: 5px;
            margin-bottom: 20px;
            border: 1px solid blue;
            border-collapse: collapse;
        }
    </style>

    <title>员工信息列表</title>

</head>
<body>
    <div>
        <span>员工列表</span>
        <span style="margin-left: 50%;"><a href="/emp/addEmpUI">添加员工</a></span>
    </div>
    <div>
        <!-- th:style="'样式内容'",注意里面有两个单引号,可以是使用冒号。 -->
        <table th:style="'border:1px solid blue;'">
            <tr>
                <th>序列号</th>
                <th>员工编号</th>
                <th>员工姓名</th>
                <th>员工岗位</th>
                <th>入职日期</th>
                <th>员工月薪</th>
                <th>员工补贴</th>
                <th>所在部门</th>
                <th>操作</th>
            </tr>
            <!-- thymeleaf list 迭代 -->
            <tr th:each="emp,stat:${emps}" >
                <td th:text="${stat.index + 1}"></td>
                <td><a th:href="@{'/emp/'+${emp.empno}}">[[${emp.empno}]]</a></td>
                <td><a th:href="@{'/emp/'+${emp.empno}}">[[${emp.ename}]]</a></td>
                <td>[[${emp.job}]]</td>
                <!-- 日期格式化 -->
                <td>[[${#dates.format(emp.hiredate,'yyyy年MM月dd日')}]]</td>
                <td>[[${emp.sal}]]</td>
                <td>[[${emp.comm}]]</td>

                <td th:switch="${emp.dname}">
                    <span th:case="RESEARCH">科研部</span>
                    <span th:case="SALES">销售部</span>
                    <span th:case="RESEARCH">运维部</span>
                    <span th:case="TESTING">测试部</span>
                    <span th:case="ACCOUNTING">财务部</span>
                </td>
                <td>
                    <a th:href="@{'/emp/'+${emp.empno}}">查看详情</a> |
                    <a href="#" th:onclick="'confirmDeleteEmp('+${emp.empno}+')'">删除</a> |
                    <a th:href="@{'/emp/updateEmpUI/'+${emp.empno}}">更新</a>
                </td>
            </tr>
        </table>

    </div>

<!-- js -->
<script>
    function confirmDeleteEmp(empno) {
        if(confirm('确认删除?'))
        {//这里设置的currentEmpno不能更改,是Map指定的key,笔者玩的是Map进行参数绑定
            window.location.href="/emp/deleteEmp?currentEmpno=" + empno;
        }
    }
</script>
</body>
</html>

====>>>emp.html

 <!DOCTYPE html>
<!-- 引入thymeleaf命名空间 -->
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8">
    <!--简单样式表 -->
    <style type="text/css">
        table{
            border:1px solid blue;
        }
        td{
            background-color: #FFEBCD;
            margin-left: 5px;
            margin-bottom: 20px;
            border: 1px solid blue;
            border-collapse: collapse;
        }
    </style>

    <title>员工详情</title>
</head>
<body>
    <div>员工详情</div>
    <div>
        <table>
            <tr>
                <td><label>员工编号</label></td>
                <td th:text="${emp.empno}"></td>
            </tr>
            <tr>
                <td><label>员工姓名</label></td>
                <td th:text="${emp.ename}"></td>
            </tr>
            <tr>
                <td><label>员工岗位</label></td>
                <td th:text="${emp.job}"></td>
            </tr>
            <tr>
                <td><label>入职日期</label></td>
                <td>[[${#dates.format(emp.hiredate,'yyyy年MM月dd日')}]]</td>
            </tr>
            <tr>
                <td><label>员工薪资</label></td>
                <td th:text="${emp.sal}"></td>
            </tr>
            <tr>
                <td><label>员工津贴</label></td>
                <td th:text="${emp.comm}"></td>
            </tr>
        </table>
    </div>
    <div>
        <a  href="/emp/empList" style="margin-left:150px;"> 返回 </a>
    </div>
   </body>
</html>

====>>>addEmpUI.html

 <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8">
    <!--简单样式表 -->
    <style type="text/css">
        table{
            border:1px solid blue;
        }
        td{
            background-color: #FFEBCD;
            margin-left: 5px;
            margin-bottom: 20px;
            border: 1px solid blue;
            border-collapse: collapse;
        }
    </style>
    <title>新增员工</title>
</head>
<body>
<div><span>添加员工</span></div>
<div>
    <!-- 这里不要使用th:action和th:method,转发过来时报模板解析异常 -->
    <form action="/emp/addEmp" method="post" onsubmit="return nonEmpty()">
    <table>
        <tr>
            <td><label for="empno">员工编号</label></td>
            <td><input th:name="empno" id="empno" th:disabled="true"></td>
        </tr>
        <tr>
            <td><label for="ename">员工姓名</label></td>
            <td><input th:name="ename" id="ename"></td>
        </tr>
        <tr>
            <td><label for="job">员工岗位</label></td>
            <td><input th:name="job" id="job"></td>
        </tr>
        <tr>
            <td><label for="hiredate">入职日期</label></td>
            <!-- SpringMVC自定义数据类型转换器,这里读者自己实现来支持的格式,默认如下 -->
            <td><input th:name="hiredate" id="hiredate" th:placeholder="格式2016-6-5"></td>
        </tr>
        <tr>
            <td><label for="sal">员工薪资</label></td>
            <td><input th:name="sal" id="sal"></td>
        </tr>
        <tr>
            <td><label>员工津贴</label></td>
            <td><input th:name="comm" id="comm"></td>
        </tr>
        <tr>
            <td><label for="deptno">所在部门</label></td>
            <!--演示简单实现,读者自己使用下拉框实现-->
            <td><input th:name="deptno" id="deptno" placeholder="10,20,30,40,50其中之一"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input th:type="submit" th:value="添加">
                <a  href="/emp/empList" style="margin-left:150px;"> 返回 </a>
            </td>
        </tr>

    </table>
    </form>
</div>

<!-- js ,不采用实体校验(不灵活),直接通过写js来检验非空-->
<script>
    function nonEmpty() {
        debugger;
        var validateValue = true;

        //部门非空校验,数据库中数据完整性约束--非空
        var deptno = document.getElementById("deptno").value;
        console.info(deptno);
        if(deptno === null || deptno == ""){
            validateValue = false;
            document.getElementById("deptno").parentNode.innerHTML="<input name='deptno' id='deptno'><label>deptno不能为空!</label>";
        }else{
            document.getElementById("deptno").parentNode.innerHTML="<input name='deptno' id='deptno' value='"+deptno+"'>";
        }

        //名字非空校验
        var ename = document.getElementById("ename").value;
        if(ename === null || ename == ""){
            validateValue = false;
            document.getElementById("ename").parentNode.innerHTML="<input name='ename' id='ename'><label>ename不能为空!</label>";
        }else{
            document.getElementById("ename").parentNode.innerHTML="<input name='ename' id='ename' value='"+ename+"'>";
        }
        return validateValue;
    }
</script>
</body>
</html>

上一张addEmpUI.html中的js调试图,Intellj idea自动提示js函数,本来是取value值的,被提示一误导选择了valueof()函数。调试工具(chrome,firefox,IE都可以调试觉得还是chrome方便一点)。

在这里插入图片描述

====>>> updateEmpUI.html

 <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8">
    <!--简单样式表 -->
    <style type="text/css">
        table{
            border:1px solid blue;
        }
        td{
            background-color: #FFEBCD;
            margin-left: 5px;
            margin-bottom: 20px;
            border: 1px solid blue;
            border-collapse: collapse;
        }
    </style>
    <title>更新员工信息</title>
</head>
<body>
<div><span>更新员工信息</span></div>
<div>
    <!-- 这里不要使用th:action和th:method,转发过来时报模板解析异常 -->
    <form action="/emp/updateEmp" method="post" onsubmit="return nonEmpty()">
        <table>
            <tr>
                <td><label for="empno">员工编号</label></td>
                <!-- 注意取值th:value,使用的是thymeleaf来取数据,前缀"th:"不能少-->
                <td><input th:name="empno" id="empno" th:readonly="true" th:value="${emp.empno}"></td>
            </tr>
            <tr>
                <td><label for="ename">员工姓名</label></td>
                <td><input th:name="ename" id="ename" th:value="${emp.ename}"></td>
            </tr>
            <tr>
                <td><label for="job">员工岗位</label></td>
                <td><input th:name="job" id="job" th:value="${emp.job}"></td>
            </tr>
            <tr>
                <td><label for="hiredate">入职日期</label></td>
                <!-- SpringMVC自定义数据类型转换器,这里读者自己实现来支持的格式,默认如下 -->
                <td><input th:name="hiredate" id="hiredate" th:value="${#dates.format(emp.hiredate,'yyyy-MM-dd')}"></td>
            </tr>
            <tr>
                <td><label for="sal">员工薪资</label></td>
                <td><input th:name="sal" id="sal" th:value="${emp.sal}"></td>
            </tr>
            <tr>
                <td><label>员工津贴</label></td>
                <td><input th:name="comm" id="comm" th:value="${emp.comm}"></td>
            </tr>
            <tr>
                <td><label for="deptno">所在部门</label></td>
                <!--演示简单实现,读者自己使用下拉框实现-->
                <td><input th:name="deptno" id="deptno" placeholder="10,20,30,40,50其中之一" th:value="${emp.deptno}"></td>
            </tr>
            <tr>
                <td colspan="2">
                    <input th:type="submit" th:value="更新">
                    <a  href="/emp/empList" style="margin-left:150px;"> 返回 </a>
                </td>
            </tr>

        </table>
    </form>
</div>

<!-- js ,不采用实体校验(不灵活),直接通过写js来检验非空-->
<script>
    function nonEmpty() {
        debugger;
        var validateValue = true;

        //部门非空校验,数据库中数据完整性约束--非空
        var deptno = document.getElementById("deptno").value;
        console.info(deptno);
        if(deptno === null || deptno == ""){
            validateValue = false;
            document.getElementById("deptno").parentNode.innerHTML="<input name='deptno' id='deptno'><label>deptno不能为空!</label>";
        }else{
            document.getElementById("deptno").parentNode.innerHTML="<input name='deptno' id='deptno' value='"+deptno+"'>";
        }

        //名字非空校验
        var ename = document.getElementById("ename").value;
        if(ename === null || ename == ""){
            validateValue = false;
            document.getElementById("ename").parentNode.innerHTML="<input name='ename' id='ename'><label>ename不能为空!</label>";
        }else{
            document.getElementById("ename").parentNode.innerHTML="<input name='ename' id='ename' value='"+ename+"'>";
        }
        return validateValue;
    }
</script>
</body>
</html>
===>>>大家有没有发现一个问题,就是SpringMVC的四大器件(前端控制器、映射器、处理器适配器和视图解析器),
本人一个都没有配置,全部由SpringBoot来管理了。是不是在Web层给开发人员进行了简化呢?是的!

玩Mybatis的都知道,sql日志是多么的重要,第3集笔者(拈花为何不一笑)将演示slf4j-logback日志的配置和遇到的坑,及热部署、打包等。希望能够帮助大家少走弯路……

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
SpringBoot是一个基于Idea开发的框架,它提供了快速和简化的操作,并且为通用Spring项目提供了许多非功能性特性。它能够确保联网并能够加载到程序框架结构。 速成SpringBoot的步骤主要包括以下几个方面: 1. 首先,你需要了解SpringBoot的基本概念和特点,比如它的简介和作用。这可以帮助你对SpringBoot有一个整体的认识。 2. 接下来,你可以开始学习SpringBoot的入门知识,学习如何在Idea中创建一个SpringBoot项目,并配置好相关的依赖和配置文件。这可以让你快速上手并开始使用SpringBoot。 3. 一旦你熟悉了SpringBoot的基本使用方法,你可以学习如何整合其他技术,比如MyBatis和Thymeleaf,以实现更复杂的功能。比如,你可以学习如何使用MyBatis来访问数据库,以及如何使用Thymeleaf来进行页面渲染。 4. 最后,你可以尝试使用SpringBoot来开发一个简单的员工管理系统,实现一些基本的CRUD功能。 通过以上步骤,你可以初步掌握SpringBoot的开发和使用,并且能够快速构建出一个简单的应用程序。当然,要深入学习和应用SpringBoot还需要进一步的学习和实践。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Spring Boot 速学](https://blog.csdn.net/weixin_46603441/article/details/127622402)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [一天学完SpringBoot](https://blog.csdn.net/weixin_44953152/article/details/125141124)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [SpringBoot实现员工管理系统](https://download.csdn.net/download/m0_52380556/87087252)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值