• SpringBoot==>简介


    一、SpringBoot 产生背景

      随着动态语言的流行(Ruby,Groovy,Scala,Node.js),Java 的开发显得格外的笨重:繁多的配置,低下的开发效率,复杂的部署流程以及第三方技术集成难度大。

      在上述环境下,Spring Boot应运而生。它使用 ”习惯优于配置”(项目中存在大量的配置,此外还内置一个习惯性的配置,让你无须进行手动配置)的理念让你的项目快速运行起来。使用Spring Boot很容易创建一个独立运行(运行jar,内嵌Servlet容器),准生产级别的Spring框架的项目,使用Spring Boot你可以不使用或者只需要很少的Spring配置。 

      相比于以往的一些开发框架,Spring Boot不但使用更加简单,而且功能更加丰富,性能更加稳定而健壮。使用Spring Boot开发框架,不仅能提高开发速度,增强生产效率,一定意义上,可以说是解放了程序员的劳动,一种新技术的使用,更能增强系统的稳定性和扩展系统的性能指标。

    二、SpringBoot 简介

      Spring Boot是在Spring框架基础上创建的一个全新的框架,其设计目的是简化 Spring 应用的搭建和开发过程,更加敏捷的开发 Spring应用程序,专注于应用程序的功能, 简化了配置的过程, 甚至不配置。可以通过内嵌Servlet容器(Tomcat/Jetty或Undertow)把 Web 应用程序变成可自执行的JAR文件, 不用部署到传统的容器就能命令行里运行。它不但具有 Spring 的所有优秀特性,而且具有如下四个主要特性,能够改变开发 Spring 应用程序的方式: 

    • Spring Boot Starter:他将常用的依赖分组进行了整合,将其合并到一个依赖中,这样就可以一次性添加到项目的Maven或Gradle构建中;
    • 自动配置:SpringBoot的自动配置特性利用了Spring4对条件化配置的支持,合理地推测应用所需的bean并自动化配置他们;
    • 命令行接口:(Command-line-interface, CLI):SpringBoot的CLI发挥了Groovy编程语言的优势,并结合自动配置进一步简化Spring应用的开发;
    • Actuatir:它为SpringBoot应用添加了一定的管理特性;

      Spring Boot 对于一些第三方的技术的使用,提供了非常完美的整合, 使你在简单的使用中,不知不觉运用了非常高级和先进的技术。

    三、SpringBoot 优点

    • SpringBoot 使编码变得简单,习惯优于配置,大大提高了开发效率;
    • SpringBoot 使配置变得简单,极简的组件依赖,自动发现与装配(在maven中指定一个starter即可);
    • SpringBoot 使部署变得简单,SpringBoot会自动将 tomcat/Jetty 服务器组建内嵌到当前的工程中,随着SpringBoot的启动,tomcat一并提供服务,SpringBoot编译时,不再提供war包,而是Java中标准的jar包,我们可以将jar包批量上传到服务器,通过服务器端的脚本自动启动,无论是一台还是1000台服务器,通过一个命令就可完成自动部署;
    • SpringBoot使监控变得简单,SpringBoot提供了运行时的应用监控(服务器压力,内存占用,数据库负载),在后台可以监控应用程序的运行情况,提前预防宕机;
    • 与云计算和分布式架构天然集成;
    • 学习成本极低;

    四、SpringBoot 环境搭建

    1、创建一个 Gradle 工程

    2、配置 build.gradle 文件并引入依赖包

    buildDir = 'target'
    
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'
    
    buildscript {
        ext {
            springBootVersion = '2.1.6.RELEASE'
        }
        repositories {
            maven {
                url 'https://plugins.gradle.org/m2/'
            }
        }
        dependencies {
            classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        }
    }
    
    sourceSets.main.resources {
        if (project.hasProperty('profile')) {
            srcDir 'src/main/resources-' + project.profile
            srcDir 'src/test/resources-' + project.profile
        } else {
            srcDir 'src/main/resources-test'
            srcDir 'src/test/resources-test'
        }
    }
    
    clean.doLast {
        delete projectDir.path + '/target'
    }
    
    configurations {
    
    }
    
    dependencies {
        implementation('org.springframework.boot:spring-boot-starter-web')
        implementation('org.springframework.boot:spring-boot-devtools')
        implementation('org.springframework.boot:spring-boot-starter-aop')
        testImplementation('org.springframework.boot:spring-boot-starter-test')
    }
    build.gradle

    配置文件中 dependencies 闭环中的内容就是所引入的依赖包

    3、 创建一个入口类

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

    @SpringBootApplication

    • 申明让 SpringBoot 自动给程序进行必要的配置,这个注解等同于 @Configuration 、@EnableAutoConfiguration 和 @ComponentScan 三个注解;
    • @ComponentScan:组件扫描,可自动发现和装配一些Bean
    • @Configuration:等同于spring的XML配置文件;
    • @EnableAutoConfiguration:自动配置;

    4、创建控制器

    @RestController
    @RequestMapping("/ping")
    public class PingController {
    
      /**
       * 自定义配置
       */
      @Value("${info}")
      private String info;
    
      @RequestMapping(path = "/111",method = RequestMethod.GET)
      public String ping1(Integer id, String name, Integer age){
        System.out.println("user info:" + id + "," + name + "," + age);
        return "pong" + info;
      }
    
      @RequestMapping(path = "/222",
              method = {RequestMethod.POST,RequestMethod.GET},
              // "application/json;charset=utf-8"
              consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
      public String ping2(){
        return "pong" + info;
      }
    
      @RequestMapping(path = "/333",
              method = {RequestMethod.POST,RequestMethod.GET})
      public RetMsg ping3(User user){
        System.out.println("user = " + user);
        return RetMsg.buildSuccess();
      }
    }
    PingController 控制器

    @RestController

    • 用于标注控制层组件(如struts中的action);
    • 作用等同于 @Controller + @ResponseBody,表示这个类是个控制器,并且是将函数的返回值直接填入HTTP响应体中,是REST风格的控制器。

    @RequestMapping

    • 提供路由信息,负责URL到Controller中的具体函数的映射;
      • path,:匹配路径;
      • method:匹配请求的方式,GET(RequestMethod.GET),POST;
      • consumes:匹配 content-type;
      • headers:限定请求头;
      • params:一般不用,参数的处理都在代码中进行处理;

    5、启动Application类

    直接运行 Application 类中的 main() 方法即可

    控制台打印了启动日志,展示了一些启动信息,像:启动时间、默认端口等等,我们使工具发一个Get请求,来看一下结果:

    五、application.yml配置

    SpringBoot支持两种配置文件:application.yml 和 application.properties,通常我们使用application.yml,存放在 resources 目录下,下面先记录一些常用配置

    server:
      prot: 8888  #配置访问的端口
      servlet:
        context-path: /xxx  #配置访问时的项目名
    
    spring:
      devtools:      
        restart:
          enabled: true  #这个好像是热加载,每次代码有改动就自动重启,原来的restart ClassLoader 被丢弃,重新创建一个restart ClassLoader,由于需要加载的类相比较少,所以实现了较快的重启时间。
      datasource:
        url: jdbc:mysql://localhost:3306/xxx?useUnicode=true&characterEncoding=UTF-8&useSSL=true  #配置数据库的路径
        username: root  #数据库登录名
        password: root   #登陆密码
        type: com.alibaba.druid.pool.DruidDataSource  #这个可以看一下 https://blog.csdn.net/qq_27191423/article/details/79146855 
        driver-class-name: com.mysql.jdbc.Driver
        filters: stat
        maxActive: 20  #连接池的最大值,同一时间可以从池分配的最多连接数量,0时无限制
        initialSize: 1  #连接初始值,连接池启动时创建的连接数量的初始值
        maxWait: 60000
        minIdle: 1  #最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: select 'x'
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true   #是否对已备语句进行池管理(布尔值),是否对PreparedStatement进行缓存
        maxOpenPreparedStatements: 20
    
        jackson:
          date-format: yyyy-MM-dd HH:mm:ss
          time-zone: GMT+8
    
    mybatis-plus:
      mapper-locations: classpath*:mapper/**/*Mapper.xml
      #实体扫描,多个package用逗号或者分号分隔
      typeAliasesPackage: com.yudao.platform.entity.*
      global-config:
        #主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
        id-type: 0
        #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
        field-strategy: 2
        #驼峰下划线转换
        db-column-underline: false
        #刷新mapper 调试神器
        refresh-mapper: true
        #数据库大写下划线转换
        #capital-mode: true
        # Sequence序列接口实现类配置
        #key-generator: com.baomidou.mybatisplus.incrementer.OracleKeyGenerator
        #逻辑删除配置
        logic-delete-value: 1
        logic-not-delete-value: 0
        #自定义填充策略接口实现
        #meta-object-handler: com.baomidou.springboot.xxx
        #自定义SQL注入器
        # sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector
      configuration:
        map-underscore-to-camel-case: true
        cache-enabled: false
        call-setters-on-nulls: true
    application.yml 配置

    我们将 tomcat 端口配为 9000,再将项目路径配为 /spring-boot 后再次启动

    发送请求时就需要把端口和路径稍作修改

    自定义配置

    我们还可以在 application.yml 中进行一些自定义配置,然后在业务处理的类中进行引用

    六、常用功能

    1、定时任务

    定义 Scheduler 类,并标注成@Component

    定义方法,并标识成 @Scheduled

    @Component
    public class PrintLogScheduler {
    
      @Scheduled(cron = "0 */10 * * * *")
      public void print(){
        System.out.println("springboot");
      }
    }
    PrintLogScheduler

    @Component

    • 用于把当前类对象存入spring容器中;

    @Scheduled

    • 用于执行定时任务;
    • 参数 cron:指定定时任务执行频率,值传一个cron 表达式;
    • 参数 fixedDelay:上一次执行完毕时间点之后多长时间再执行;
    • 参数 fixedRate:上一次开始执行时间点之后多长时间再执行;
    • 参数 initialDelay:第一次延迟多长时间后再执行;

    在入口类中开启scheduler的支持 @EnableScheduling

    @SpringBootApplication
    @EnableScheduling
    public class Application {
    
      public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
      }
    }
    Application

    @EnableScheduling

    • 开启对定时任务的支持;

    cron表达式

    • 秒 分 时 天 月 周
    • 0 0 * * * * 每小时的0分0秒执行
    • */5 * * * * * 每隔5秒执行一次
    • 0 */10 * * * * 每隔10分钟执行一次
    • 0 30 23 * * * 每天23:30执行一次

    2、热部署

    引入依赖

    • implementation('org.springframework.boot:spring-boot-devtools');

    IDEA配置

    • File-Settings-Compiler:勾选 Build Project automatically;
    • ctrl + shift + alt + / --> 选择Registry --> 勾上 Compiler autoMake allow when app running;

    七、整合

    1、Junit

    引入依赖

    • testImplementation('org.springframework.boot:spring-boot-starter-test');

    被测试类

    @Service
    public class FooServiceImpl implements FooService {
    
      @Override
      public String foo() {
        return "foo";
      }
    }

    需要加上 @Service注解

    测试类

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = Application.class)
    public class SpringBootTestUnitDemo {
    
      @Autowired
      private FooService fooService;
    
      @Test
      public void testFoo(){
        String res = fooService.foo();
        System.out.println("res = " + res);
      }
    }

    @RunWith(SpringRunner.class)

    • 就是一个运行器,测试时使用,里面的参数需要传入 .class类对象;
    • @RunWith(SpringRunner.class) 表示让测试运行于 Spring 环境;
    • @RunWith(JUnit4.class) 就是指用 JUnit4 来运行;

    @SpringBootTest(classes = Application.class)

    • 同样是一个用于测试的注解;
    • classes 属性指定启动类;
    • webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT经常和测试类中@LocalServerPort一起在注入属性时使用,会随机生成一个端口号。

    2、Mybatis

    引入依赖

    • implementation('org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.0');
    • compile('mysql:mysql-connector-java:8.0.17')

    配置数据源信息

    在 application.yml 文件进行数据库连接配置

    spring:
      datasource:
        url: jdbc:mysql://192.168.182.131:3306/course
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
    数据库连接配置

    其中,driver-class-name 在 MySQL版本高于 5.x.x 版本后可以不写

    编写 Usermapper 接口

    @Mapper
    public interface UserMapper {
    
      @Insert("INSERT INTO `user`(`id`,`name`,`age`) VALUES(#{id},#{name},#{age})")
      Integer insertUser(User user);
    
      @Delete("Delete FROM `user` where id = #{id}")
      Integer deleteUser(User user);
    
      @Update("UPDATE user SET name=#{name} WHERE id=#{id}")
      Integer updateUser(User user);
    
      @Select("SELECT * FROM `user` WHERE name=#{name}")
      List<User> queryByName(String name);
    
      @Select("SELECT * FROM `user` WHERE id=#{id} AND name=#{name}")
      List<User> queryByIdAndName(@Param("id") String id, @Param("name") String name);
    }
    UserMapper

    需要注意的是,如果方法传的是自定义的对象(如上面的User),我们编写 SQL语句对应的字段会自动匹配 User中的属性。如果是 Java自带的类型(String,Integer等),需要在参数前面加上 @Param注解。

    @Mapper

    • @Mapper注解标记这个接口作为一个映射接口;
    • 这个注解替代了mapper的映射文件,有了它就不用再写 mapper.xml 文件

    注意:

    如果接口中的方法传的参数不是自定义的数据类型,需要用 @Param标注。如果传的是自定义的数据类型就会根据SQL语句的字段名与自定义数据类型的属性自动进行匹配,所以不用标注@Param。

    指定Mapper路径

    @SpringBootApplication
    @EnableScheduling
    @MapperScan("com.jack.course.springboot.mapper")
    public class Application {
    
      public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
      }
    }
    Application

    需要在入口类中指定扫描 Mapper 的包,使用 @MapperScan注解

    @MapperScan

    • 标注要扫描 mapper 类接口的包名;
    • 可以同时扫描多个包;

    编写测试类

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = Application.class)
    public class TestMyBatis {
    
      @Autowired
      private UserMapper userMapper;
    
      @Test
      public void testInsert() {
        User user = new User();
        user.setId(3);
        user.setName("木木");
        user.setAge(22);
        Integer effectRows = userMapper.insertUser(user);
        assert effectRows == 1;
      }
    
      @Test
      public void testDelete() {
        User user = new User();
        user.setId(1);
        Integer effectRows = userMapper.deleteUser(user);
        assert effectRows == 1;
      }
    
      @Test
      public void testUpdate() {
        User user = new User();
        user.setId(1);
        user.setName("牛牛");
        Integer effectRows = userMapper.updateUser(user);
        assert effectRows == 1;
      }
    
      @Test
      public void testSelect() {
        List<User> users = userMapper.queryByName("牛牛");
        for (User user : users) {
          System.out.println("user = " + user);
        }
      }
    
      @Test
      public void testQuery() {
        List<User> users = userMapper.queryByIdAndName("2","牛牛");
        for (User user : users) {
          System.out.println("user = " + user);
        }
      }
    }
    TestMyBatis
  • 相关阅读:
    用带缓冲区的文件流FileStream来实现大文件的拷贝
    委托与事件、匿名方法与Lambda表达式
    C#基础点记录
    C#基础知识06
    用while语句实现用户登陆程序
    TSQL检索电话呼叫员的工作流水信息
    委托
    类型转换、异常、String知识总结
    内网入库单管理系统
    用C#打印出正等腰三角形
  • 原文地址:https://www.cnblogs.com/L-Test/p/11616490.html
Copyright © 2020-2023  润新知