SpringBoot基础

一、快速上手SpringBoot

1.1 SpringBoot入门程序开发

  • SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程
  • Spring程序缺点
    • 依赖设置繁琐
    • 配置繁琐
  • SpringBoot程序优点
    • 起步依赖(简化依赖配置)
    • 自动配置(简化常用工程相关配置)
    • 辅助功能(内置服务器等)

1.1.1 基于Idea创建SpringBoot工程

  1. 创建新模块,选择Spring Initializr,并配置模块相关基础信息

  2. 选择当前模块需要使用的技术

  3. 开发控制器类

    // Rest模式
    @RestController
    @RequestMapping("/books")
    public class BookController {
    
        @GetMapping
        public String getById(){
            System.out.println("springboot is running...");
            return "springboot is running...";
        }
    }
    
  4. 运行自动生成的Application类

类/配置文件SpringSpringBoot
pom文件中的坐标手工添加勾选添加
web3.0配置类手工制作
Spring/SpringMVC配置类手工制作
控制器手工制作手工制作
  • 基于idea开发SpringBoot程序需要确保联网且能够加载到程序框架结构

1.1.2 基于官网创建SpringBoot工程

  1. 打开springboot官网,选择Quickstart Your Project
  2. 创建工程,并保存项目
  3. 解压项目,通过IDE导入项目

1.1.3 基于阿里云创建SpringBoot工程

  • 打开springboot官网,选择Quickstart Your Project

1.1.4 手工创建Maven工程修改为SpringBoot工程

1.3 入门案例解析

1.3.1 parent

  1. 定义一系列的常用坐标版本
  2. 定义一系列的常用坐标组合
  3. 直接使用组合
  • 开发SpringBoot程序要继承spring-boot-starter-parent
  • spring-boot-starter-parent中定义了若干个依赖管理
  • 继承parent模块可以避免多个依赖使用相同技术时出现依赖版本冲突
  • 继承parent的形式也可以采用引入依赖的形式实现效果

1.3.2 starter

  • SpringBoot中常见项目名称,定义了当前项目使用的所有依赖坐标,以达到减少依赖配置的目的

  • spring-boot-starter-web.pom

    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    

1.3.3 引导类

  • 启动方式

    @SpringBootApplication
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class);
        }
    }
    
  • SpringBoot的引导类是Boot工程的执行入口,运行main方法就可以启动项目

  • SpringBoot工程运行后初始化Spring容器,扫描引导类所在包加载bean

1.3.4 内嵌tomcat

  • 内嵌Tomcat服务器是SpringBoot辅助功能之一

  • 内嵌Tomcat工作原理是将Tomcat服务器作为对象运行,并将该对象交给Spring容器管理

  • 变更内嵌服务器思想是去除现有服务器,添加全新的服务器

  • 内置服务器

    • tomcat(默认):apache出品,应用面广,负载了若干较重的组件
    • jetty:更轻量级,负载型能远不及tomcat
    • unsertow:undertow,负载性能勉强跑赢tomcat

二、SpringBoot基础配置

2.1 属性配置

  • SpringBoot默认配置文件application.properties,通过键值对配置对应属性

    server.port=80
    spring.main.banner-mode=off
    spring.banner.image.location=logo.png
    logging.level.root=info(error,debug)
    
  • SpringBoot内置属性查询

    • 官方文档中参考文档第一项:Application Properties

2.2 配置文件分类

  • SpringBoot提供了多种属性配置方式

    • application.properties

      server.port=80
      
    • application.yml

      server:
      	port:81
      
    • application.yaml

      server:
      	port:82
      
  • SpringBoot配置文件加载顺序:application.properties > application.yml > application.yaml

  • 指定SpringBoot配置文件

    • Setting -> Project Structure -> Facets
    • 选中对应项目/工程
    • Customize Spring Boot
    • 选择配置文件

2.3 yaml文件

  • YAML(YAML Ain’t Markup Language),一种数据序列化格式
  • 优点
    • 容易阅读
    • 容易与脚本语言交互
    • 以数据为核心,重数据轻格式
  • YAML
    • .yml(主流)
    • .yaml
  • YAML语法规则
    • 大小写敏感
    • 属性层级关系使用多行描述,每行结尾使用冒号结束
    • 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tab键)
    • 属性值前面添加空格(属性名与属性值之间使用冒号+空格作为分隔)
    • (#)表示注释

2.4 yaml数据读取

  • 使用@Value读取单个数据,属性名引用方式:${一级属性名.二级属性名…}

  • 在配置文件中可以使用属性名引用方式引用属性

  • 属性值中如果出现转义字符,需要使用双引号包裹

  • 封装全部数据到Environment对象

  • 自定义对象封装指定数据

    @Component
    @ConfigurationProperties(prefix = "enterprise")
    public class Enterprise {
        private String name;
        private Integer age;
        private String[] subject;
    }
    

三、基于SpringBoot实现SSM整合

3.1 整合JUnit

  • SpringBoot整合JUnit

    @SpringBootTest
    class Springboot04JunitApplicationTests {
        // 1、注入要测试的对象
        @Autowired
        private BookDao bookDao;
        @Test
        void contextLoads() {
            // 2、执行要测试的对象对应的方法
            bookDao.save();
        }
    }
    

3.2 整合Mybatis

  • 核心配置:数据库连接相关信息
  • 映射配置:SQL映射(XML/注解)
  • 步骤
    1. 创建新模块,选择Spring初始化,并配置模块相关基础信息
    2. 选择当前模块需要使用的技术集(MyBatis、MySQL)
    3. 设置数据源参数(application.yaml)
    4. 定义数据层接口与映射配置
    5. 测试类中注入dao接口,测试功能

3.3 整合Druid

  1. 导入Druid对应的starter
  2. 根据Druid提供的配置方式进行配置

3.4 整合第三方技术通用方式

  • 导入对应的starter
  • 根据提供的配置格式,配置非默认值对应的配置项

3.5 SSM整合案例

image-20220413194133347

3.5.1 模块创建

  1. 勾选SpringMVC与MySQL坐标
  2. 修改配置文件为yml格式
  3. 设置端口为80方便访问

3.5.2 实体类开发

  • Lombok,一个Java类库,提供了一组注解,简化POJO实体类开发

    <dependency>
    	<groupId>org.projectlombok</groupId>
    	<artifactId>lombok</artifactId>
    </dependency>
    
  • lombok版本由SpringBoot提供,无需指定版本

  • 常用注解@Data

    @Data
    public class Book {
        private Integer id;
        private String type;
        private String name;
        private String description;
    }
    
  • 为当前实体类在编译期设置对应的get/set方法,toString方法,hashCode方法,equals方法等

3.5.2 数据层开发

  • 技术实现方案

    • MyBatisPlus
    • Druid
  • 导入MyBatisPlus与Druid对应的starter

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.1</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.8</version>
    </dependency>
    <dependency>
    
  • 配置数据源与MyBatisPlus对应的基础配置(id生成策略使用数据库自增策略)

    spring:
      datasource:
        druid:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/ssm_db
          username: root
          password: 1234
    
    mybatis-plus:
      global-config:
        db-config:
          table-prefix: tbl_
          id-type: auto
    
  • 继承BaseMapper并指定泛型

    @Mapper
    public interface BookDao extends BaseMapper<Book> {
    }
    
  • 制作测试类测试结果

    @Test
    void testUpdate() {
    	Book book = new Book();
    	book.setId(15);
    	book.setName("测试数据abc");
    	book.setDescription("测试数据a");
    	bookDao.updateById(book);
    }
    @Test
    void testDelete() {
    	bookDao.deleteById(15);
    }
    
  • 为方便调试可以开启MyBatisPlus的日志

    mybatis-plus:
      global-config:
        db-config:
          table-prefix: tbl_
          id-type: auto
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    
  • 分页功能

    • 分页操作需要设定分页对象IPage

      @Test
      void testGetPage(){
          IPage page = new Page(1,5);
          bookDao.selectPage(page,null);
      }
      
    • IPage对象中封装了分页操作中的所有数据

      • 数据
      • 当前页码值
      • 每页数据总量
      • 最大页码值
      • 数据总量
    • 分页操作实在MyBatisPlus的常规操作基础上增强得到,内部是动态的拼写SQL语句,因此需要增强对应的功能,使用MyBatisPlus拦截器实现

      @Configuration
      public class MPConfig {
          @Bean
          public MybatisPlusInterceptor mybatisPlusInterceptor(){
              // 1、定义MP拦截器
              MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
              // 2、添加具体的拦截器
              interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
              return interceptor;
          }
      }
      

3.5.3 业务层开发

  • Service层接口定义与数据层接口定义具有较大差别,不要混用

    • selectByUsernameAndPassword(Steing username,String password)
    • login(Steing username,String password)
  • 测试类定义

    @SpringBootTest
    public class BookServiceTestCase {
        @Autowired
        private BookService bookService;
        @Test
        void testGetById(){
            System.out.println(bookService.getById(4));
        }
        @Test
        void testDelete() {
            bookService.delete(15);
        }
        @Test
        void testGetAll() {
            bookService.getAll();
        }
    }
    
  • 业务层快速开发方案

    • 使用MyBatisPlus提供有业务层通用接口(IService)与业务层通用实现类(ServiceImpl<M,T>)
    • 在通用类基础上做功能重载或功能追加
    • 注意重载时不要覆盖原始操作,避免原始提供的功能丢失

3.5.4 表现层开发

  • 基于Restful进行表现层接口开发
    • 新增:POST
    • 删除:DELETE
    • 修改:PUT
    • 查询:GET
    • 接收参数:@Request
    • 路径变量:@PathVariable
  • 使用Postman测试表现层接口功能

3.5.5 表现层消息一致性处理

  • 修改前数据格式统一

    • 增删改

      true
      
    • 查单条

      {
          "id": 3,
          "type": "计算机理论",
          "name": "3",
          "description": "3"
      }
      
    • 查全部

      [
          {
              "id": 1,
              "type": "计算机理论",
              "name": "1",
              "description": "1"
          },
          {
              "id": 2,
              "type": "计算机理论",
              "name": "2",
              "description": "2"
          },
          {
              "id": 3,
              "type": "计算机理论",
              "name": "3",
              "description": "3"
          }
      ]
      
  • 设计表现层返回结果的模型类,用于后端与前端进行数据格式统一,也成为前后端数据协议

    @Data
    public class R{
        private Boolean flag;
        private Object data;
    }
    

3.5.6 前后端协议联调

  • 前后端分离结构设计中页面归属前端服务器

  • 单体工程中页面放置在resources目录下的static目录中(出问题先执行clean)

  • created钩子函数用于初始化页面时发起调用

  • 前端发送异步请求,调用后端接口

    getAll() {
        axios.get("/books").then((res)=>{
            console.log(res.data);
        });
    }
    
  • 弹出添加窗口

    handleCreate() {
        this.dialogFormVisible = true;
    }
    
  • 添加

    //添加
    handleAdd () {
        axios.post("/books",this.formData
            //判断当前操作是否成功
            if(res.data.flag){
                //1、关闭弹层
                this.dialogFormVisible = 
                this.$message.success("添加
            }else{
                this.$message.error("添加失败
            }
        }).finally(()=>{
            //2、重新加载数据
            this.getAll();
        });
    },
    
  • 删除

    // 删除
    handleDelete(row) {
        console.log(row);
        this.$confirm("此操作永久删除当前信息,是否继续?","提示",{type:"info"}).then(()=>{
            axios.delete("/books/"+row.id).then((res)=>{
                //判断当前操作是否成功
                if(res.data.flag){
                    this.$message.success("删除成功");
                }else{
                    this.$message.error("删除失败");
                }
            }).finally(()=>{
                //2、重新加载数据
                this.getAll();
            });
        }).catch(()=>{
            this.$message.info("取消操作");
        });
    },
    
  • 修改

    handleUpdate(row) {
        // 发送异步请求
        axios.get("/books/" + row.id).then((res)=>{
            if(res.data.flag && res.data.data != null){
                this.dialogFormVisible4Edit = true;
                this.formData = res.data.data;
            }else{
                this.$message.error("数据同步失败,自动刷新");
            }
        }).finally(()=>{
            //2、重新加载数据
            this.getAll();
        });
    },
    

3.5.7 业务消息一致性处理

  • 对异常进行统一处理,出现异常后,返回指定信息

    //作为springmvc的异常处理器
    @RestControllerAdvice
    public class ProjectExceptionAdvice {
        //拦截所有
        @ExceptionHandler(Exception.class)
        public R doException(Exception ex){
            //记录日志
            //通知运维
            //通知开发
            ex.printStackTrace();
            return new R("服务器故障,请稍后再试");
        }
    }
    
  • 页面消息处理,没有传递消息加载默认消息,传递消息后加载指定消息

    handleAdd() {
        axios.post("/books", this.formData).then((res) => {
            //判断当前操作是否成功
            if (res.data.flag) {
                //1、关闭弹层
                this.dialogFormVisible = false;
                this.$message.success(res.data.msg);
            } else {
                this.$message.error(res.data.msg);
            }
        }).finally(() => {
            //2、重新加载数据
            this.getAll();
        });
    },
    
  • 可以在表现层Controller中进行消息统一处理

    @PostMapping
    public R save(@RequestBody Book book) throws IOException {
        if(book.getName().equals("123")) throw new IOException();
        boolean flag = bookService.save(book);
        return new R(flag,flag ? "添加成功!" : "添加失败!");
    }
    

3.5.8 分页功能

  • 页面使用el分页组件添加分页功能

    <!--分页组件-->
    <div class="pagination-container">
        <el-pagination
                class="pagiantion"
                @current-change="handleCurrentChange"
                :current-page="pagination.currentPage"
                :page-size="pagination.pageSize"
                layout="total, prev, pager, next, jumper"
                :total="pagination.total">
        </el-pagination>
    </div>
    
  • 定义分页组件需要使用的数据并将数据绑定到分页组件

    data:{
        pagination:{ 				//分页相关模型数据
            currentPage:1,          //当前页码   
            pageSize:10,            //每页显示的记录数  
            total:1,				//总记录数
        }
    }
    
  • 替换查询全部功能为分页功能

    getAll(){
        axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res) => {
    }
    

3.5.9 删除功能维护

  • 对查询结果进行校验,如果当前页码值大于最大页码值,使用最大页码值作为当前页码值重新查询

    @GetMapping("{currentPage}/{pageSize}")
    public R getPage(@PathVariable int currentPage, @PathVariable int pageSize){
        IPage<Book> page = bookService.getPage(currentPage, pageSize);
        //如果当前页码值大于了总页码值,那么重新执行查询操作,使用最大页码值作为当前页码值
        if (currentPage > page.getPages()){
            page = bookService.getPage((int)page.getPages(), pageSize);
        }
        return new R(true,page);
    }
    

3.5.10 条件查询功能

  • 页面数据模型绑定

    <div class="filter-container">
        <el-input placeholder="图书类别" v-model="pagination.type" style="width: 200px;" class="filter-item"></el-input>
        <el-input placeholder="图书名称" v-model="pagination.name" style="width: 200px;" class="filter-item"></el-input>
        <el-input placeholder="图书描述" v-model="pagination.description" style="width: 200px;" class="filter-item"></el-input>
        <el-button @click="getAll()" class="dalfBut">查询</el-button>
        <el-button type="primary" class="butT" @click="handleCreate()">新建</el-button>
    </div>
    
  • 组织数据成为get请求发送到数据

    getAll() {
        //组织参数,拼接url请求地址
        console.log(this.pagination.type);
        param = "?type="+this.pagination.type;
        param += "&name="+this.pagination.name;
        param += "&description="+this.pagination.description;
        console.log(param);
        // 发送异步请求
        axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+param).then((res) => {
            this.pagination.pageSize = res.data.data.size;
            this.pagination.currentPage = res.data.data.current;
            this.pagination.total = res.data.data.total;
            this.dataList = res.data.data.records;
        });
    },
    
  • Controller接收参数

    @GetMapping("{currentPage}/{pageSize}")
    public R getAll(@PathVariable int currentPage, @PathVariable int pageSize,String name,Book book){
        IPage<Book> page = bookService.getPage(currentPage, pageSize,book);
        //如果当前页码值大于了总页码值,那么重新执行查询操作,使用最大页码值作为当前页码值
        if (currentPage > page.getPages()){
            page = bookService.getPage((int)page.getPages(), pageSize,book);
        }
        return new R(true,page);
    }
    
  • 业务层接口功能开发

    @Override
    public IPage<Book> getPage(int currentPage, int pageSize, Book book) {
        LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
        lqw.like(Strings.isNotEmpty(book.getType()),Book::getType,book.getType());
        lqw.like(Strings.isNotEmpty(book.getName()),Book::getName,book.getName());
        lqw.like(Strings.isNotEmpty(book.getDescription()),Book::getDescription,book.getDescription());
        IPage page = new Page(currentPage,pageSize);
        bookDao.selectPage(page,lqw);
        return page;
    }
    

3.5.11 总结

  1. pom.xml:配置起步依赖
  2. application.yam:设置数据源、端口、框架技术相关配置等
  3. dao:继承BaseMapper、设置@Mapper
  4. dao测试类
  5. service:调试数据层接口或MyBatis-Plus提供的接口快速开发
  6. service测试类
  7. controller:基于Restful开发,使用Postman测试跑通功能
  8. 页面:放置在resources目录下的static目录中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值