Spring Boot 入門學習筆記

一、概述

1、Spring Boot 的概述

  • Spring Boot的設計是爲了讓您儘快地啓動和運行,而Spring的前期配置最少。Spring Boot以一種自以爲是的觀點構建生產就緒的應用程序。

2、Spring Boot 的優勢

Java一直被人詬病的一點就是臃腫、麻煩。當我們還在辛苦的搭建項目時,可能Python程序員已經把功能寫好了,究其原因注意是兩點:

  • 複雜的配置

    項目各種配置其實是開發時的損耗, 因爲在思考 Spring 特性配置和解決業務問題之間需要進行思維切換,所以寫配置擠佔了寫應用程序邏輯的時間。

  • 一個是混亂的依賴管理

    項目的依賴管理也是件喫力不討好的事情。決定項目裏要用哪些庫就已經夠讓人頭痛的了,你還要知道這些庫的哪個版本和其他庫不會有衝突,這難題實在太棘手。並且,依賴管理也是一種損耗,添加依賴不是寫應用程序代碼。一旦選錯了依賴的版本,隨之而來的不兼容問題毫無疑問會是生產力殺手。
    而SpringBoot讓這一切成爲過去!

Spring Boot 簡化了基於Spring的應用開發,只需要“run”就能創建一個獨立的、生產級別的Spring應用。Spring Boot爲Spring平臺及第三方庫提供開箱即用的設置(提供默認設置,存放默認配置的包就是啓動器),這樣我們就可以簡單的開始。多數Spring Boot應用只需要很少的Spring配置。

3、Spring Boot 的特點

Spring Boot 主要目標是:

  • 爲所有 Spring 的開發者提供一個非常快速的、廣泛接受的入門體驗
  • 開箱即用(啓動器starter-其實就是SpringBoot提供的一個jar包),但通過自己設置參數(.properties),即可快速擺脫這種方式。
  • 提供了一些大型項目中常見的非功能性特性,如內嵌服務器、安全、指標,健康檢測、外部化配置等
  • 絕對沒有代碼生成,也無需 XML 配置。

二、基本案例

1、IDEA 添加依賴
  • spring-boot-starter-parent:裏面已經對各種常用依賴(並非全部)的版本進行了管理,我們的項目需要以這個項目爲父工程,這樣我們就不用操心依賴的版本問題了
  • spring-boot-starter-web:讓SpringBoot幫我們完成各種自動配置,我們必須引入SpringBoot提供的自動配置依賴,我們稱爲 Web啓動器
  • <java.version>1.8</java.version>:maven工程的jdk版本是1.5,而我們開發使用的是1.8,因此這裏我們需要修改jdk版本

pom.xml

<!--spring-boot-starter-parent:(父工程座標)裏面已經對各種常用依賴(並非全部)的版本進行了管理,
我們的項目需要以這個項目爲父工程,這樣我們就不用操心依賴的版本問題了-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
    </parent>
    <!--默認情況下,maven工程的jdk版本是1.5,而我們開發使用的是1.8,因此這裏我們需要修改jdk版本-->
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--添加web啓動器:讓SpringBoot幫我們完成各種自動配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
    </dependencies>
2、編寫啓動類 Application.java
package cn.lemon;

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

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
3、編寫 Controller 控制器

SpringbootController.java

package cn.lemon.controller;

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

@RestController
public class SpringbootController {
    @GetMapping("/boot")
    public String boot(){
        return "Spring Boot ......";
    }
}
4、啓動測試

運行main函數,查看控制檯:
在這裏插入圖片描述
訪問頁面:http://127.0.0.1:8080/boot
在這裏插入圖片描述

三、Java 配置——數據庫

1、常用的註解

  • @Configuration:聲明一個類作爲配置類,代替xml文件
  • @Bean:聲明在方法上,將方法的返回值加入Bean容器,代替<bean>標籤
  • @value:屬性注入
  • @PropertySource:指定外部屬性文件

2、引入 Druid 連接池依賴,並創建 jdbc.properties 配置文件

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/db_springboot
jdbc.username=root
jdbc.password=lemon

3、編寫配置類 JdbcConfig.java

package cn.lemon.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;


@Configuration/*說明這是一個配置類*/
@PropertySource("classpath:/jdbc.properties")/*讀取配置文件*/
public class JdbcConfig {
    @Value("${jdbc.driverClassName}")/* @Value : 爲屬性值注入 */
    private String driverClassName;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean/*通過@Bean將 dataSource()方法聲明爲一個註冊Bean的方法,Spring會自動調用該方法,將方法的返回值加入Spring容器中*/
    public DataSource dataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(driverClassName);
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        return druidDataSource;
    }
}

4、在 SpringbootController.java 中通過@Autowired注入DataSource 測試

package cn.lemon.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.sql.DataSource;

@RestController
public class SpringbootController {
    @Autowired
    private DataSource dataSource;

    @GetMapping("/boot")
    public String boot() {
        return "Spring Boot ......" + dataSource;
    }
}

四、SpringBoot的屬性注入

使用的@Value註解屬性注入不夠強大,因爲它只能注入基本類型值。在SpringBoot中,提供了一種新的屬性注入方式,支持各種java基本數據類型及複雜類型的注入。

第一步:新建 JdbcProperties.java 類

package cn.lemon.config;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * 在類上通過@ConfigurationProperties註解聲明當前類爲屬性讀取類,默認讀取 application.properties 屬性文件
 * prefix="jdbc" 讀取屬性文件中,前綴爲jdbc的值
 * 在類上定義各個屬性,名稱必須與屬性文件中 jdbc.後面部分一致
 */
@ConfigurationProperties(prefix = "jdbc")
public class JdbcProperties {
    private String driverClassName;
    private String url;
    private String username;
    private String password;

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

第二步:新建 application.properties 配置文件

需要注意的是,這裏我們並沒有指定屬性文件的地址,所以我們需要把jdbc.properties名稱改爲application.properties,這是SpringBoot默認讀取的屬性文件名

第三步:新建 JdbcConfig.java 配置類

package cn.lemon.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
@EnableConfigurationProperties(JdbcProperties.class)/*通過`@EnableConfigurationProperties(JdbcProperties.class)`來聲明要使用`JdbcProperties`這個類的對象*/
public class JdbcConfig {
    @Bean
    public DataSource dataSource(JdbcProperties jdbcProperties) {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(jdbcProperties.getDriverClassName());
        druidDataSource.setUrl(jdbcProperties.getUrl());
        druidDataSource.setUsername(jdbcProperties.getUsername());
        druidDataSource.setPassword(jdbcProperties.getPassword());
        return druidDataSource;
    }
}

五、自動配置原理

查看啓動類(也就是main函數)
在這裏插入圖片描述

1、註解:@SpringBootApplication

在這裏插入圖片描述

1-1、@SpringBootConfiguration
  • 通過這段我們可以看出,在這個註解上面,又有一個@Configuration註解。通過上面的註釋閱讀我們知道:這個註解的作用就是聲明當前類是一個配置類,然後Spring會自動掃描到添加了@Configuration的類,並且讀取其中的配置信息。而@SpringBootConfiguration是來聲明當前類是SpringBoot應用的配置類,項目中只能有一個。所以一般我們無需自己添加。
1-2、@EnableAutoConfiguration
  • 註解@EnableAutoConfiguration,告訴SpringBoot基於你所添加的依賴,去“猜測”你想要如何配置Spring。比如我們引入了spring-boot-starter-web,而這個啓動器中幫我們添加了tomcatSpringMVC的依賴。此時自動配置就知道你是要開發一個web應用,所以就幫你完成了web及SpringMVC的默認配置了!

總結:SpringBoot內部對大量的第三方庫或Spring內部庫進行了默認配置,這些配置是否生效,取決於我們是否引入了對應庫所需的依賴,如果有那麼默認配置就會生效。
所以,我們使用SpringBoot構建一個項目,只需要引入所需框架的依賴,配置就可以交給SpringBoot處理了。除非你不希望使用SpringBoot的默認配置,它也提供了自定義配置的入口。

1-3、@ComponentScan
  • 配置組件掃描的指令。提供了類似與<context:component-scan>標籤的作用
    通過basePackageClasses或者basePackages屬性來指定要掃描的包。如果沒有指定這些屬性,那麼將從聲明這個註解的類所在的包開始,掃描包及子包
    而我們的@SpringBootApplication註解聲明的類就是main函數所在的啓動類,因此掃描的包是該類所在包及其子包。因此,一般啓動類會放在一個比較前的包目錄中。

2、默認配置原理

  • 我們知道@EnableAutoConfiguration會開啓SpringBoot的自動配置,並且根據你引入的依賴來生效對應的默認配置。
  • 在我們的項目中,已經引入了一個依賴:spring-boot-autoconfigure,其中定義了大量自動配置類:
    在這裏插入圖片描述
    例如SpringMVC,查看mvc 的自動配置類:
    在這裏插入圖片描述
    打開WebMvcAutoConfiguration:
    在這裏插入圖片描述
  • @Configuration:聲明這個類是一個配置類
  • @ConditionalOnWebApplication(type = Type.SERVLET) ConditionalOn,翻譯就是在某個條件下,此處就是滿足項目的類是是Type.SERVLET類型,也就是一個普通web工程,顯然我們就是
  • @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) 這裏的條件是OnClass,也就是滿足以下類存在:Servlet、DispatcherServlet、WebMvcConfigurer,其中Servlet只要引入了tomcat依賴自然會有,後兩個需要引入SpringMVC纔會有。這裏就是判斷你是否引入了相關依賴,引入依賴後該條件成立,當前類的配置纔會生效!
  • @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) 這個條件與上面不同,OnMissingBean,是說環境中沒有指定的Bean這個才生效。其實這就是自定義配置的入口,也就是說,如果我們自己配置了一個WebMVCConfigurationSupport的類,那麼這個默認配置就會失效!
總結

SpringBoot爲我們提供了默認配置,而默認配置生效的條件一般有兩個:

  • 你引入了相關依賴
  • 你自己沒有配置

1)啓動器
所以,我們如果不想配置,只需要引入依賴即可,而依賴版本我們也不用操心,因爲只要引入了SpringBoot提供的stater(啓動器),就會自動管理依賴及版本了。
因此,玩SpringBoot的第一件事情,就是找啓動器,SpringBoot提供了大量的默認啓動器

2)全局配置
另外,SpringBoot的默認配置,都會讀取默認屬性,而這些屬性可以通過自定義application.properties文件來進行覆蓋。這樣雖然使用的還是默認配置,但是配置中的值改成了我們自定義的。
因此,玩SpringBoot的第二件事情,就是通過application.properties來覆蓋默認屬性值,形成自定義配置。我們需要知道SpringBoot的默認屬性key。

六、Spring Boot 整合 SpringMVC

1、訪問靜態資源

Spring Boot中每 webapp 目錄,回顧我們上面看的源碼,有一個叫做ResourceProperties的類,裏面就定義了靜態資源的默認查找路徑:
在這裏插入圖片描述
默認的靜態資源路徑爲:

  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/
  • classpath:/public

在這裏插入圖片描述

2、添加攔截器

在SpringBoot官方文檔中有這麼一段說明:

  • 如果你想要保持Spring Boot 的一些默認MVC特徵,同時又想自定義一些MVC配置(包括:攔截器,格式化器, 視圖控制器、消息轉換器 等等),你應該讓一個類實現WebMvcConfigurer,並且添加@Configuration註解,但是千萬不要@EnableWebMvc註解。如果你想要自定義HandlerMappingHandlerAdapterExceptionResolver等組件,你可以創建一個WebMvcRegistrationsAdapter實例 來提供以上組件。如果你想要完全自定義SpringMVC,不保留SpringBoot提供的一切特徵,你可以自己定義類並且添加@Configuration註解和@EnableWebMvc註解

首先我們定義一個攔截器:

package cn.lemon.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginInterceptor implements HandlerInterceptor {

    private Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        logger.debug("處理器執行之前打印該方法");
        return true;//返回 false 不會跳轉到處理器
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        logger.debug("處理器執行之後打印該方法");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        logger.debug("完成頁面跳轉後打印該方法");
    }
}

然後,我們定義配置類,註冊攔截器:

package cn.lemon.config;

import cn.lemon.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
/*定義配置類,註冊攔截器*/
public class MvcConfig implements WebMvcConfigurer {
    /**
     * 通過@Bean註解,將我們定義的攔截器註冊到Spring容器
     *
     * @return
     */
    @Bean
    public LoginInterceptor loginInterceptor() {
        return new LoginInterceptor();
    }

    /**
     * 重寫接口中的addInterceptors方法,添加自定義攔截器
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 通過registry來註冊攔截器,通過addPathPatterns來添加攔截路徑
        registry.addInterceptor(this.loginInterceptor()).addPathPatterns("/**");
    }
}

配置日誌級別

#修改端口爲 ;1000,系統默認端口爲:8080
server.port=1000

#如果想在控制檯打印日誌是需要配置的,因爲我們記錄的log級別是debug,默認是顯示info以上
#SpringBoot通過`logging.level.*=debug`來配置日誌級別,*填寫包名
logging.level.cn.lemon=debug

#數據庫連接配置
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_springboot
jdbc.username=root
jdbc.password=lemon

七、Spring Boot 整合 JDBC 和事務

1、整合JDBC,只需要找到SpringBoot提供的啓動器,也就是引入 jar 包即可:spring-boot-starter-jdbcmysql-connector-java
2、SpringBoot中通過註解來控制事務。也就是用@Transactional註解

八、Spring Boot 整合 連接池

1、引入jdbc啓動器的時候,SpringBoot已經自動幫我們引入了一個連接池:HikariCP
連接池配置文件:

# 連接四大參數
spring.datasource.url=jdbc:mysql://localhost:3306/db_springboot
spring.datasource.username=root
spring.datasource.password=lemon
# 可省略,SpringBoot自動推斷
spring.datasource.driverClassName=com.mysql.jdbc.Driver

spring.datasource.hikari.idle-timeout=60000
spring.datasource.hikari.maximum-pool-size=30
spring.datasource.hikari.minimum-idle=10

2、Druid連接池
引入 jar 包:druid-spring-boot-starter ,並配置

# 連接四大參數
spring.datasource.url=jdbc:mysql://localhost:3306/db_springboot
spring.datasource.username=root
spring.datasource.password=lemon
# 可省略,SpringBoot自動推斷
spring.datasource.driverClassName=com.mysql.jdbc.Driver

#初始化連接數
spring.datasource.druid.initial-size=1
#最小空閒連接
spring.datasource.druid.min-idle=1
#最大活動連接
spring.datasource.druid.max-active=20
#獲取連接時測試是否可用
spring.datasource.druid.test-on-borrow=true
#監控頁面啓動
spring.datasource.druid.stat-view-servlet.allow=true

九、Spring Boot 整合 MyBatis

1、引入 jar 包:mybatis-spring-boot-starter
2、在 application.properties 中添加
# mybatis 別名掃描
mybatis.type-aliases-package=cn.lemon.domain
# mapper.xml文件位置,如果沒有映射文件,請註釋掉
mybatis.mapper-locations=classpath:mappers/*.xml
3、數據訪問層以及映射文件
package cn.lemon.dao;

import cn.lemon.domain.User;

import java.util.List;

public interface UserDao{
    public List<User> findAll();
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.lemon.dao.UserDao">
    <select id="findAll" resultType="user">
        select * from tb_user
    </select>
</mapper>
4、在Spring Boot 啓動類中添加註解 @MapperScan

在這裏插入圖片描述

5、測試類

引入測試包:spring-boot-starter-test

package cn.lemon.dao;

import cn.lemon.domain.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserDaoTest {
    @Autowired
    private UserDao userDao;

    @Test
    public void testFindAll() {
        List<User> list = userDao.findAll();
        for (User user : list) {
            System.out.println(user);
        }
    }
}

十、Spring Boot 整合通用 mapper(MyBatis)

本質:可以簡化MyBatis的開發,可以省略映射文件
1、通用Mapper的作者也爲自己的插件編寫了啓動器,我們直接引入即可 mapper-spring-boot-starter
2、修改實體類
package cn.lemon.domain;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
@Table(name = "tb_user")
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")/*可以省略*/
    private Long id;

    // 用戶名
    //自動轉換下換線到駝峯命名user_name -> userName
    private String userName;

    // 密碼
    private String password;

    // 姓名
    private String name;

    // 年齡
    private Integer age;

    // 性別,1男性,2女性
    private Integer sex;

    // 出生日期
    private Date birthday;

    // 創建時間
    private Date created;

    // 更新時間
    private Date updated;

    // 備註
    private String note;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Date getUpdated() {
        return updated;
    }

    public void setUpdated(Date updated) {
        this.updated = updated;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }
}
3、修改數據訪問層,要繼承 Mapper
package cn.lemon.dao;

import cn.lemon.domain.User;
import tk.mybatis.mapper.common.Mapper;

import java.util.List;

public interface UserDao extends Mapper<User> {
    public List<User> findAll();
}
4、修改啓動類

在這裏插入圖片描述

5、刪除映射文件
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章