第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)
第2集 SpringBoot一天速成 (SpringBoot)_第1张图片

第2集 SpringBoot一天速成 (SpringBoot)_第2张图片

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

     
     
         org.springframework.boot
         spring-boot-starter-web
     
    
     
     
         org.springframework.boot
         spring-boot-starter-thymeleaf
     
    

    打开maven依赖,查看下spring-boot-starter-web依赖了哪些jar,如图:
    第2集 SpringBoot一天速成 (SpringBoot)_第3张图片

    再看看thymeleaf(目前这个模板的性能是相对比较差的)依赖了哪些jar,如下图:
    第2集 SpringBoot一天速成 (SpringBoot)_第4张图片

    2.在src/main/resources目录下分别创建两个目录:templates和static
    第2集 SpringBoot一天速成 (SpringBoot)_第5张图片

入口类
===>>> 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 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 findEmpByDeptnoSal(EmpCustom empCustom){
        List 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抛出异常
            // ,解决方案:去掉 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

 



    
    
    

    员工信息列表



    
员工列表 添加员工
序列号 员工编号 员工姓名 员工岗位 入职日期 员工月薪 员工补贴 所在部门 操作
[[${emp.empno}]] [[${emp.ename}]] [[${emp.job}]] [[${#dates.format(emp.hiredate,'yyyy年MM月dd日')}]] [[${emp.sal}]] [[${emp.comm}]] 科研部 销售部 运维部 测试部 财务部 查看详情 | 删除 | 更新

====>>>emp.html

 



    
    
    

    员工详情


    
员工详情
[[${#dates.format(emp.hiredate,'yyyy年MM月dd日')}]]

====>>>addEmpUI.html

 


    
    
    
    新增员工


添加员工
返回

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

第2集 SpringBoot一天速成 (SpringBoot)_第6张图片

====>>> updateEmpUI.html

 


    
    
    
    更新员工信息


更新员工信息
返回
===>>>大家有没有发现一个问题,就是SpringMVC的四大器件(前端控制器、映射器、处理器适配器和视图解析器),
本人一个都没有配置,全部由SpringBoot来管理了。是不是在Web层给开发人员进行了简化呢?是的!

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

你可能感兴趣的:(第2集 SpringBoot一天速成 (SpringBoot))