SpringBoot【笔记】

概述

SpringBoot提供了一种快速使用Spring的方式,基于约定优于配置的思想

Spring缺点

  • 配置繁琐
  • 依赖繁琐

SpringBoot功能

  • 自动配置
    • Spring配置应该用那个,不该用那个,该过程是SpringBoot自动完成的
  • 起步依赖
  • 辅助功能
    • 提供了一些大型项目中常见的非功能特性,如嵌入式服务器、安全、指标、健康检测、外部配置等

SpringBoot并不是对Spring功能上的增强,而是提供了一种快速使用Spinrg的方式

快速入门

  • 创建Maven项目
  • 导入SpringBoot起步依赖
<!--SpringBoot工程需要继承的父工程-->
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.2.6.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
  • 定义Controller
package com.ht.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String hello(){
        return "hello Spring boot!";
    }
}

  • 编写引导类
package com.ht;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 引导类。SpringBoot项目的入口
 */
@SpringBootApplication
public class HelloApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class);
    }
}

  • 启动测试

小结

  • SpringBoot在创建项目时,使用jar的打包方式
  • SpringBoot的引导类,是项目入口,运行main方法就可以启动项目
  • 使用SpringBoot和Spring构建的项目,业务代码编写方式完全一样

快速构建SpringBoot工程

通过Idea快速构建

起步依赖原理分析

spring-boot-starter-parent

定义了各种技术的版本信息,组全了一套最优搭配的技术版本

spring-boot-starter-web

在各种starter中,定义了完成该功能需要的坐标合计,其中大部分版本信息来自父工程。

我们的工程继承parent,引入starter后,通过依赖传递,就可以简单方便获得需要的jar包,并且不会存在版本冲突等问题

配置

分类

SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用application.properties或者application.yml(application.yaml)进行配置

  • SpringBoot提供了两种配置文件类型:properties和yml/yaml
  • 默认配置文件名称:application
  • 在同一级目录下优先级为:properties>yml>yaml

Yaml

介绍

Yaml是一种直观的能够被电脑识别的数据序列化格式,并且容易被人类阅读,容易和脚本预言交互的,可以被支持yaml库的不同的编程语言程序导入,yml文件是以数据为核心的,比传统的xml方式更加简洁

yaml文件的扩展名可以使用.yml或.yaml

语法

  • 大小写敏感
  • 数据值前边必须有空格,作为分隔符
  • 使用缩进表示层级关系
  • 缩进时不允许使用Tab键,只允许使用空格(各个系统tab对应的空格数目可能不同,导致层次混乱)
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • #表示注释,从这个字符一直到行尾,都会被解析器忽略。

数据格式

  • 对象(map):键值对的集合
person:
	name:zhangsan
#行内写法
person:{name,zhangsan}
  • 数组:一组按次序排列的值
address:
	-beijing
	-shanghai
#行内写法
address:[beijing,shanghai]
  • 纯量:单个的,不可再分的值。
msg1:'hello \n world' #单引忽略转义字符
msg2:"hello \n world" #双引识别转义字符

参数引用:${key}

读取配置文件

  • @Value
@Value("${name}")
private String name;
name:1234
  • Environment
@Autowired
private Enviroment env;

@RequstMapping("/hello")
public String hello2(){
    System.out.println(env.getProperty("name"))
    return "hello";
}
name:1234
  • @ConfigurationProperties
@Component
@ConfigurationProperties(prefix = "person")
public class person{
    private String name;
    private int age;
    
    。。。(get/set/toString)
}
person:
	name:1234
	age:123
@Autowired
private Person person;

@RequestMapping("/hello")
public String hello(){
    System.out.println(person);
    return "hello";
}

profile动态配置文件

简介

我们在开发SpringBoot应用时,通常同一套程序会被安装到不同环境,比如:开发、测试、生产等其中数据库地址、服务器端口等等配置不同,如果每次打包时,都要修改配置文件,那么非常麻烦,profile功能就是来进行动态配置切换的。

配置方式
  • 多profile文件方式

多profile文件方式–properties

spring.profiles.active=pro
spring.profiles.active=dev
server:8000
server:8001

多profile文件方式—yml

spring:
  profiles:
    #active: pro
    active: dev
激活方式
  • 配置文件

项目内部配置文件加载顺序

Springboot程序启动时,会从以下位置加载配置文件:

  1. file:./config/:当前项目下的/config目录下
  2. file:./ :当前项目的根目录
  3. classpath:/config/:classpath的/config目录
  4. classpath:/ :classpath的根目录(常用即resources)

加载顺序为上文的排列顺序,高优先级配置的属性会生效

整合

整合Junit

  1. 搭建SpringBoot工程
  2. 引入starter-test起步依赖
  3. 编写测试类
  4. 添加测试相关注解
    • @RunWith(SpringRunner.class)
    • @SpringbootTest(classes = 启动类.class)
  5. 编写测试方法

整合redis

  • 搭建SpringBoot工程
  • 引入redis起步依赖
  • 配置redis相关属性
  • 注入RedisTemplate模板
@Autowired
private RedisTemplate redisTemplate;

@Test
public void testSet(){
    //存入数据
    redisTemplate.boundValueOps("name").set("zhangsan");
}
@Test
public void testGet(){
    //获取对象
    Object name = redisTemplate.boundValueOps("name").get();
    System.out.println(name);
}
  • 编写测试方法,测试

整合mybatis

  • 核心配置:数据库连接相关信息(连什么?连谁?什么权限)
  • 映射配置:SQL映射(XML/注解)

步骤:

1、创建一个新的springboot工程

2、选择当前模块需要使用的技术集(MyBatis、MySQL)

3、设置数据源参数

4、定义数据层借口和映射配置

5、测试

整合mybatis时的常见问题

时区设置问题

1、给mysql设置时区(url后面加serverTimezone=UTC)

整合MyBatis-Plus

  • MyBatis-Plus与MyBatis区别
    • 导入坐标不同
    • 数据层实现简化

快速

使用阿里云的方式创建spring-boot

正式(官方)

1、手动添加SpringBoot整合MyBatis-Plus的坐标,可以通过mvnrepository获取

2、定义数据层接口与映射,继承BaseMapper

整合Druid

1、导入坐标

2、添加配置信息

spring:
	datasource:
		druid:
			url:
			username:
			password:
			

整合第三方技术

  • 导入对应的starter
  • 配置对应的设置或采用默认配置

整合案例

模块搭建

1、勾选SpringMVC与MySQL坐标

2、修改配置文件为yml格式

3、设置端口号

实体类开发

  • Lombok:一个java类库,提供了一组注解,简化POJO实体类开发
<!--lombok-->
		<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方法等

数据层标准开发

  • 技术实现方案

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

<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.4.2</version>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
			<version>1.2.8</version>
		</dependency>
  • 配置数据源与MyBatisPlus对应的基础配置(id生成策略使用数据库自增策略)
spring:
  datasource:
    druid:
      driver-class-name: com.mysql.jdbc.Driver
      url:jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
      username:root
      password:root
mybatis-plus:
  global-config:
    db-config:
      table-prefix: tb1_
      id-type: auto
  • 继承BaseMapper并指定泛型
@Mapper
public interface BookDao extends BaseMapper<Book> {
}

MP开始日志

  • 为了方便调试可以开启MyBatisPlus的日志
mybatis-plus:
	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(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

数据层-按条件查询

  • 使用QueryWrapper对象封装查询条件,推荐使用LambdaQueryWrapper对象,所有查询操作封装成方法调用
@Test
void testGetByCondition(){
    Ipage page = new page(1,10);
    LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
    lqw.like(Book::getName,"Spring");
    bookDao.selectPage(page,lqw);
}
@Test
void testGetByCondition(){
	QueryWrapper<Book> qw = new QueryWrapper<Book>();
	qw.like("name","Spring");
	bookDao.selectList(qw);
}
  • 支持动态拼写查询条件
@Test
void testGetByCondition(){
    String name = "Spring";
    Ipage page = new page(1,10);
    LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
    lqw.like(Strings.isNotEmpty(name),Book::getName,"Spring");
    bookDao.selectPage(page,lqw);
}

业务层开发

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

    • selectByUserNameAndPassword(String username,String password);
    • login(String username,String password);
  • 接口定义

public interface BookService {
    Boolean save(Book book);
    Boolean update(Book book);
    Boolean delete(Integer id);
    Book getById(Integer id);
    List<Book> getAll();
}
  • 实现类定义
@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao bookDao;

    @Override
    public Boolean save(Book book) {
        return bookDao.insert(book)>0;
    }

    @Override
    public Boolean update(Book book) {
        return bookDao.updateById(book)>0;
    }

    @Override
    public Boolean delete(Integer id) {
        return bookDao.deleteById(id)>0;
    }

    @Override
    public Book getById(Integer id) {
        return bookDao.selectById(id);
    }

    @Override
    public List<Book> getAll() {
        return bookDao.selectList(null);
    }
}

业务层–快速开发

  • 快速开发方案

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

public interface IBookService extends IService<Book>{
    
}
public interface IBookService extends IService<Book>{
    //追加的操作与原始操作通过名称区分,功能类似
    Boolean delete(Integer id);
    
    Boolean insert(Book book);
    
    Boolean modify(Book book);
    
    Book get(Integer id);
}
  • 实现类定义
@Service
public class BookServiceImpl2 extends ServiceImpl<BookDao,Book> implements IBookService{
    
}

表现层

  • 基于Restful制作表现层接口
    • 新增:POST
    • 删除:DELETE
    • 修改:PUT
    • 查询:GET
  • 接收参数:
    • 实体数据:@RequestBody
    • 路径变量:@PathVariable

表现层消息一致性处理

  • 设计表现层返回结果的模型类,用于后端与前端进行数据格式统一,也称为前后端数据协议
@Data
public class R {
    private Boolean flag;
    private Object data;

    public R(){

    }
    public R(Boolean flag){
        this.flag=flag;
    }

    public R(Boolean flag,Object data){
        this.flag=flag;
        this.data=data;
    }
}
@RestController
@RequestMapping("/books")
public class BookController {
    @Autowired
    private IBookService bookService;

    @GetMapping
    public R getAll(){
        return new R(true,bookService.list());
    }

    @PostMapping
    public R save(@RequestBody Book book){
//        R r = new R();
//        boolean flag = bookService.save(book);
//        r.setFlag(flag);


        return new R(bookService.save(book));
    }

    @PutMapping
    public R update(@RequestBody Book book){
        return new R(bookService.saveOrUpdate(book));
    }

    @DeleteMapping("{id}")
    public R delete(@PathVariable Integer id){
        return new R(bookService.removeById(id));
    }

    @GetMapping("{id}")
    public R getById(@PathVariable Integer id){

        return new R(true,bookService.getById(id));

    }

    @GetMapping("{currentPage}/{pageSize}")
    public R getPage(int currentPage,int pageSize){
        return new R(true,bookService.getPage(currentPage,pageSize));
    }

}
  • 设计统一的返回值结果类型便于前端开发读取数据
  • 返回值结果类型可以根据需求自行设定,没有固定格式
  • 返回值结果模型类用于后端与前端进行数据格式统一,也称为前后端数据协议

前后端协议联调

  • 前后端分离结构设计中页面归属前端服务器
  • 单体工程中页面放置在resources目录下的static目录中(建议执行clean)

异常处理

  • 对异常进行统一处理,出现异常后,返回指定信息
//作为springmvc的异常处理器
@RestControllerAdvice
public class ProjectExceptionAdvice {
    //拦截所有的异常信息
    @ExceptionHandler(Exception.class)
    public R doException(Exception ex){
        //记录日志
        //发送消息给运维
        //发送邮件给开发人员,ex对象发送给开发人员
        ex.printStackTrace();
        return new R("服务器故障,请稍后");
    }
}
@Data
public class R {
    private Boolean flag;
    private Object data;
    private String msg;

    public R(){

    }
    public R(Boolean flag){
        this.flag=flag;
    }

    public R(Boolean flag,Object data){
        this.flag=flag;
        this.data=data;
    }

    public R(String msg){
        this.flag=false;
        this.msg=msg;
    }
}
  • 24
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值