快速入門全棧 - 08 SpringBoot

一、SpringBoot基礎介紹

SpringBoot是基於Spring Framework框架上擴展而來的,是爲了快速構建Spring應用程序的工具。SpringBoot嵌入了Tomcat、Jetty、Undertow等容器,無需部署WAR包,簡化了Maven配置。SpringBoot實現了自動化配置Spring,無代碼生成和xml配置。

啓動過程
SpringBoot容器是通過Java的main方法開始的。分爲以下幾步:

  1. 註解掃描、載入自動配置bean,將所有符合自動配置條件的bean定義加載到IoC容器
  2. 調用SpringApplication.run()具體容器啓動流程
    • 獲取監聽器SpringApplicationRunListeners
    • listeners.starting(),觸發ApplicationStartedEvent事件
    • 準備好環境,觸發ApplicationEnvironmentPreparedEvent事件
    • 打印啓動提示符,默認Spring的字符圖
    • 實例化一個可配置應用上下文ConfigurableApplicationContext
    • 準備上下文listeners,出發ApplicationPreparedEvent事件
    • 刷新上下文 AbstractApplicationContext.Refresh()
    • 刷新上下文後;執行啓動執行器ApplicationRunner/CommandLineRunner用戶可擴展接口
    • 成功觸發事件ApplicationReadyEvent,遇到異常出發ApplicationFailedEvent

多環境配置文件
SpringBoot的多環境配置文件需要使用application-{profile}.properties的格式,這裏的{profile}是環境標誌,例如dev, test, prod。我們需要在application.properties中添加配置項spring.profiles.active=def,也可以在IDEA的Run/Debug Configuration中添加SpringBoot應用,選擇main類並選擇對應的Active Profiles。

配置文件語法
SpringBoot有兩種配置文件,一種是properties文件,另一種是yml文件。yml文件的好處是層次結構比較清晰,但對格式和縮進的要求比較高,否則加載會失敗。一般情況下,建議使用yml文件。

常用啓動器
SpringBoot有非常多的啓動器,它們負責把我們需要的依賴打包好下載下來,省去我們自己配置的麻煩。

名稱 用途
spring-boot-starter-web 嵌入Tomcat和Web開發需要的Servlet和JSP
spring-boot-starter-thymeleaf Thymeleaf視圖構建MVC Web應用程序
spring-boot-starter-data-redis 緩存redis操作支持
spring-boot-starter-data-jpa 數據庫JPA操作支持
spring-boot-starter-data-elasticsearch Elasticsearch搜索和分析引擎和Spring Data Elasticsearch支持
spring-boot-starter-data-mongodb MongoDB數據庫操作支持
spring-boot-starter-test 單元測試
spring-boot-starter-jdbc JDBC數據庫操作支持
spring-boot-starter-aop AOP切面編程支持
spring-boot-starter-security Spring Security安全控制支持者
spring-boot-starter-actuator 健康監控支持
spring-boot-starter-tomcat Tomcat作爲默認的嵌入式容器,其他的還有Jetty和Undertow
mybatis-spring-boot-starter 第三方MyBatis操作數據庫支持

常用註解
SpringBoot有一些常用的註解,有些是來自Spring和SpringMVC的

註解 用途
@SprigBootApplication 複合註解,包括@ComponentScan,@SpringBootConfiguration,@EnableAutoConguration
@ResponseBody 直接將返回結果寫入HTTP Response Body,一般在異步獲取數據時使用
@Controller 定義控制類,通常需要配合@RequestMapping
@RestController 相當於@ResponseBody + @Controller
@Service 用於修飾服務層組件
@Repository 用於修飾數據持久層組件
@Bean 用@Bean標註等價於Xml中配置bean
@Value 注入SpringBoot Application.properties配置的屬性的值

二、SpringBoot開發實踐

在IDEA中,新建項目,選擇Spring Initializr,其中已經內嵌了Maven 3。在該項目中,初始環境選擇了Web下的Spring Web選項和lombok工具包來使用log。

我們首先看一下項目的結構,Application對應的是主函數,也就是負責啓動的類。在resources下的static包和templates包放的是靜態文件,static包放的是js/css/images等文件,templates包下放的是HTML文件。application.properties是SpringBoot的配置文件。

我們再查看一下Maven的pom.xml文件,其中的依賴項已經配置好了

1. HelloWorld

當前項目已經可以啓動了,Tomcat的監聽端口是8080。我們首先寫一個Controller,Controller通常使用的有@RestController註解和@RequestMapping註解

@RestController
@RequestMapping("/api/demo/")
public class HelloController {

    @RequestMapping(value = "/hello")
    public String hello(HttpServletRequest req, HttpServletResponse resp){
        return "Hello World! Welcome to SpringBoot";
    }
}

啓動Application後,訪問http://localhost:8080/api/demo/hello即可訪問到輸出的內容

2. 更換容器

SpringBoot默認的容器爲Tomcat,但實際還上使用Undertow或者其他框架作爲容器。因此我們嘗試着更換一下容器。我們首先要把SpringBoot依賴中的Tomcat排除掉,並添加Undertow依賴。

我們首先把spring-boot-starter-web依賴項添加<exclusion>選項來排除Tomcat

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

此時我們的項目沒有容器可以使用了,現在我們在<dependencies>中添加Undertow依賴。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
3. 整合MyBatis做CRUD

當然,剛纔的例子比較簡單。下面我們實現一個通過MyBatis和SpringBoot實現對數據庫進行增刪改查的操作。首先我們來添加依賴項

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>8.0.12</version>
</dependency>
<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid-spring-boot-starter</artifactId>
   <version>1.1.10</version>
</dependency>
<dependency>
   <groupId>org.mybatis.spring.boot</groupId>
   <artifactId>mybatis-spring-boot-starter</artifactId>
   <version>1.1.1</version>
</dependency>

我們使用MyBatis的Generator插件,因此還要添加插件。MyBatis Generator可以直接生成Bean類和Mapper,無需自己手動添加。在<plugins>…<\plugins>中添加

<plugin>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-maven-plugin</artifactId>
    <version>1.3.6</version>
</plugin>

還需要在resources中添加MyBatis Generator的配置文件,這一部分網上教程有很多,不再贅述了。在配置好後,選擇Maven - Plugin - MyBatis Generator - mybatis-generator: generate,運行後顯示BUILD SUCCESS即爲成功。

我們使用MyBatis Generator的另一個目的是使用Example,由06和07兩篇文章我們瞭解到MyBatis的動態SQL支持動態語句查詢,但效率比較慢,因此我們使用Example來實現相同的功能。

我們需要在SpringBoot的application.properties中添加關於數據庫的配置

spring.datasource.url=jdbc:mysql://localhost:3306/boss?characterEncoding=utf-8&amp;serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

另外記得要在Application類中添加註解@MapperScan(),其中要寫mapper類的地址,我們寫根目錄即可。

下面編寫一個Controller

@RestController
@RequestMapping("/api/user")
public class UserController {

    @Autowired
    TUserMapper tUserMapper;

    @RequestMapping(value = "/{id}",method = RequestMethod.GET)
    public TUser findById(HttpServletRequest req, HttpServletResponse resp,
                          @PathVariable("id") int userId){
        return tUserMapper.selectByPrimaryKey(userId);
    }
}

如果無法Autowired的話記得要給Mapper類添加@Service註解

4. AOP實現添加日誌

我們還可以使用前面提到過的切面編程來實現對操作添加日誌。首先添加aop相關的依賴

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

我們來實現切面功能類

@Component
@Aspect
@Slf4j
public class WebRequestLog {

    @Pointcut("execution(public * com.dai.learning.springboot.controller..*.*(..))")
    public void pointcut(){
        // 切入點
    }

    @Before("pointcut()")
    public void doBefore(JoinPoint joinPoint) throws Exception{
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        log.info("URL: "+request.getRequestURL().toString());
        log.info("Http Method:" + request.getMethod());
        log.info("IP: "+request.getRemoteAddr());
        log.info("Class Method:" + joinPoint.getSignature().getDeclaringTypeName());
    }

    @AfterReturning(returning = "result", pointcut = "pointcut()")
    public void doAfterReturning(Object result){
        log.info("Return of the method: "+result.toString());
        
    }
}

之後調用其他Controller方法時就會返回對應的日誌了。

三、SpringBoot應用部署

下面我們來看看如何進行SpringBoot的應用部署,讓其他用戶可以訪問到。我們首先在Maven中執行clean,在執行package打包,看到BUILD SUCCESS即爲打包成功。在項目路徑的target下可以看到打包完畢的jar包。

我們新建一個deploy目錄,並將jar包放在其中。我們新建一個啓動腳本

在Windows下需要新建一個bat文件,在Linux下需要新建一個.sh文件

java -jar demo-0.0.1.jar

注意,添加的是打包成功的對應的jar包名稱。之後我們執行啓動腳本文件,在加載成功後,SpringBoot的應用即可正常使用。

當然,這是最基礎的部署方式,還可以使用Docker和K8s來進行部署,在這裏不做介紹。

隨着項目的發展,項目的規模會越來越大,其中的配置文件也需要進行調整。當我們需要更新的時候,如果我們可以只把更新的部分部署就好了,因此下面我們來看看如何自定義結構來進行打包。

打開Maven的pom.xml文件,我們首先需要在<build>下添加<resources>節點,並將裏面的內容進行排除

<build>
	<resources>
		<resource>
			<directory>src/main/resources</directory>
			<exclude>*</exclude>
		</resource>
	</resources>
</build>

我們再添加maven的插件

<plugins>
	<plugin>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-maven-plugin</artifactId>
		<configuration>
			<layout>zip</layout>
			<excludeGroupIds>
				[運行mvn dependency:tree的結果]
			</excludeGroupIds>
			<executions>
				<execution>
					<goal>repackage</goal>
				</execution>
			</executions>
		</configuration>
	</plugins>
</plugins>

其中需要注意的是<excludeGroupIds>需要添加不被打包的依賴項,複製mvn dependency:tree的運行結果即可。這樣打包後我們該如何部署呢?

我們新建一個文件夾叫做mini-deploy,把第三方依賴放在commLibs下,把工程jar包放在appLibs下,新建一個conf文件夾放配置文件,新建一個bin文件夾存放運行腳本。把resources下的所有內容放在conf下面。

在bin下新建一個run.bat

title "SpringBoot Application"
cd ..
java -Dloader.path="commonLibs/" -jar appLib/demo-0.0.1.jar --spring.config.location=file:conf/application.properties
pause

注意,要根據自己工程的實際情況修改工程名和配置文件名,還要將配置文件中的classpath:修改爲conf/


我和幾位大佬建立了一個微信公衆號,歡迎關注後查看更多技術乾貨文章
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章