1. 程式人生 > >Spring Boot 的實踐與思考

Spring Boot 的實踐與思考

前言

本篇隨筆用於記錄我在學習 Java 和構建 Spring Boot 專案過程中的一些思考,包含架構、元件和部署方式等。下文僅為概要,待閒時逐一整理為詳細文件。

1. 元件

開源社群如火如荼,若在當下我們還要去重複 “造輪子” 那真是罪過罪過(當然也並不意味著所有的一切都可拿來即用,瞭解他,使用他,若有能力,去完善它)。因此,當我們拿到需求的時候首先應當進行拆解,哪些模組在社群中已有比較成熟的解決方案,然後大致羅列一個粗略的所需元件列表(後續根據架構的設計和相容情況再進行調整)。

1.1 ORM

用於解耦實體物件的裝載過程,他讓我們的程式設計過程更關注業務邏輯本身,其重要性毋庸多言。在 Spring Boot 中比較主流的 ORM 框架有 Spring-Data-JPA 和 MyBatis。

JPA 規範的好處是我們幾乎完全專注於業務邏輯本身,JpaRepository 中的介面能夠滿足大部分簡單的操作邏輯了,若要擴充套件,我們也可以再抽離出一個父類,新增自定義的通用 CRUD 操作,如此一來倉儲層的程式碼變得異常優雅和簡潔。以下是一個簡單的實現案例:
application.yml:

spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://mysql:3306/youclk?characterEncoding=utf8&useSSL=false
username: root
password:
youclk jpa: hibernate: ddl-auto: create show-sql: true

BookRespository.java:

public interface BookRespository extends JpaRepository<Book,Integer> {
}

Book.java:

@Data
public class Book  {
    private Long id;

    private String name;

    private Date createTime;

}

BookRespositoryTest.java:

@RunWith
(SpringRunner.class) @SpringBootTest public class BookRespositoryTest { @Autowired private BookRespository repository; @Test publicvoidsaveTest() { Assert.assertEquals(repository.findAll().size(),0); } }

對映得到的 sql 如下:

Hibernate: select book0_.id as id1_0_, book0_.name as name2_0_, book0_.number as number3_0_ from book book0_

如果是幾年前的話我肯定會首選 JPA, 但是期間近兩年的 EFCore 開發經歷讓我的選擇變得謹慎。C# 是 Lambda 和 Linq 的先驅者,因此 .NET + EF 實踐 Code First 著實優雅。然而在遷移 EFCore 的過程中遇到的問題真是不少,比如說 EFCore 1.x 的時候處理 GroupBy 是全表掃描然後拿到記憶體中過濾。對於舊專案的遷移我們一般沒有精力去驗證 ORM 對映生成的每條 SQL 語句,而且本地環境因資料基數少,測試階段很難直觀地體現出來,但部署後就悲劇了,服務和資料庫一起都要死要死的。

由此引發的思考是當進行里程碑版本的升級和遷移的時候,新版本 ORM 框架所生成的 SQL 還能否完全正確體現之前程式碼中的邏輯。

在 .NET Core 中除了 EFCore 還有一個非常優秀的 ORM 框架是 Dapper,這個和 MyBatis 非常像,相當於半自動檔吧,開發者能更好地掌控 SQL,但犧牲了一定的簡潔。介於曾經的入坑經歷,至少在查詢方面我選擇 MyBatis,例項如下:

BookRespository.java:

public interface BookRepository {
    List<Book> findAll();

    @Select("SELECT name FROM book WHERE id = #{id}")
    @Results({
            @Result(property = "name", column = "name")
    })
    String findBookName(Long id);
}

BookRepository.xml:

<?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="com.youclk.demo.repositories.BookRepository">
    <resultMap id="BaseResultMap" type="com.youclk.demo.domain.Book">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <result column="createTime" property="createTime" jdbcType="DATE"/>
    </resultMap>

    <sql id="Base_Column_List">
        id, name, createTime
    </sql>

    <select id="findAll" resultMap="BaseResultMap">
        SELECT
        <include refid="Base_Column_List"/>
        FROM book
    </select>

</mapper>

Application.java 中加一行 MapperScan 註解:

@SpringBootApplication()
@MapperScan("com.youclk.demo.repositories")
public class DemoApplication {

    publicstaticvoidmain(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

以上 BookRepository.java 中分別使用了註解和 xml,雖然在 Spring 中註解是王道,但我還是喜歡 xml 這種方式。一方面介面上寫這麼一堆 SQL 和返回型別看起來很難受,頭重腳輕,而且沒有突出重點,另一方面在於 IDEA 中對 xml 的智慧提示相當友好,效率上也不見得是寫註解快多少。不過採用註解方式少了些配置檔案,專案結構更優。

1.2 日誌

Java 中主流的日誌框架有 JUL(java.util.logging)、Log4j、Log4j2 和 Logback 這四款,JUL 因過於簡陋優先淘汰,剩下的三款都是同一個作者開發,Log4j 太舊速度慢,Log4j2 太新問題多,因此 Logback 就是最優解,對應的介面門面我選擇 SLF4j。需要匯入的包有: slf4j-api、ogback-classic 和 logback-core,以下是我的案例:

logback-spring.xml:

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>log/com.youclk.demo/warm/%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>90</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>log/com.youclk.demo/error/%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>90</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="warn">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE_WARN"/>
        <appender-ref ref="FILE_ERROR"/>
    </root>

</configuration>

LoggerTest.java:

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class LoggerTest {

    @Test
    publicvoidtestOutput() {
        log.error("error");
        log.warn("warn");
        log.info("info");
    }

}

以上將日誌的輸出整理歸類,若要分散式部署,則只要每個 Container 都掛載 log 目錄便可做日誌的集中管理。Logback 更詳細資訊可查閱 “官方文件”

1.3 快取

Memcached 和 Redis 都老生常談了,Redis 支援更多的資料結構和操作,並且二者效能差距不大,因此選他無疑,實現上也極其簡單,如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    publicvoidtestSetCache() {
        ValueOperations<String, Book> operations = redisTemplate.opsForValue();

        operations.set("my-book",new Book(),5, TimeUnit.SECONDS);

        System.out.println(operations.get(
            
           

相關推薦

Spring Boot實踐思考

前言本篇隨筆用於記錄我在學習 Java 和構建 Spring Boot 專案過程中的一些思考,包含架構、元件和部署方式等。下文僅為概要,待閒時逐一整理為詳細文件。1. 元件開源社群如火如荼,若在當下我們還要去重複 “造輪子” 那真是罪過罪過(當然也並不意味著所有的一切都可拿來

Spring Boot Profile Maven Profile 整合實踐

在現代的專案開發中多人協作、多環境部署已經是必不可少的軟體開發方式,筆者目前正在開發的一個基於Spring Boot 專案環境就有四套之多,包括(本地、測試、演練、生產)。尤其是現代的大型專案開發,構建複雜、參與人數眾多等因素,使得高效的構建工具必不可少。而Ma

spring boot 監控管理(actuator)

依賴 操作 上下 -1 star oms blog start 技術分享 Spring POMs 中提供了一個特殊的依賴模塊,即spring-boot-starter-actuator,我們只需要在我們的POM中添加依賴即可 <!-- 監控 管理 --> &l

Spring Boot 部署服務配置

端口 pattern alt getclass utf-8 打包成 interface ber eba Spring Boot 其默認是集成web容器的,啟動方式由像普通Java程序一樣。main函數入口啟動。其內置Tomcat容器或Jetty容器,詳細

Spring Boot實戰原理分析視頻課程

spring boot 視頻課程 實戰與原理分析 1、Spring Boot概述與課程概要介紹2、Spring4 快速入門3、Spring4 擴展分析(一)4、Spring4 擴展分析(二)5、Spring Boot 快速入門6、Spring Boot 配置分析(一)7、Spring Boot 配

十六、Spring Boot 部署服務配置

truct package pen vra 技術分享 時間 gprof ica 情況 spring Boot 其默認是集成web容器的,啟動方式由像普通Java程序一樣,main函數入口啟動。其內置Tomcat容器或Jetty容器,具體由配置來決定(默認Tomcat)。當然

Spring Boot實踐教程(一):Hello,world!

dap con result ret guid gui dea mode 結構 ??本篇會通過完成一個常用的Helloworld示例,來開始我們的Spring Boot旅程 準備工作 15分鐘 開發環境 項目創建 ??項目創建的時候我們可以選擇通過自定義配置Maven文

Spring Boot實踐教程:開篇

mongo code 消息 發布 搭建 jdk1.8 hello 初學者 框架 前言 ??Java項目開發Spring應該是最常被用到的框架了,但是老式的配置方式讓人覺得特別的繁瑣,雖然可以通過註解去簡化xml文件的配置,但是有沒有更簡單的方式來幫我們完成這些重復性的事情呢

001-spring boot概述課程概要

修改 特定 應用 解決方案 ase 分享圖片 安全管理 ring 生成 一、Spring Boot介紹   Spring Boot的目的在於創建和啟動新的基於spring框架的項目。Spring boot會選擇最適合的Spring 子項目和第三方開源庫進行整合。大部分Sp

Java 小記 — RabbitMQ 的實踐思考

oot body 可能 技術 業務場景 www. 一個 ava sync 前言 本篇隨筆將匯總一些我對消息隊列 RabbitMQ 的認識,順便談談其在高並發和秒殺系統中的具體應用。 1. 預備示例 想了下,還是先拋出一個簡單示例,隨後再根據其具體應用場景進行擴展,我覺得這

spring cloud實戰思考(一) spring config全局配置方案設計

功能 IE 基於 比較 此外 fig eureka 搜索 地址 “spring cloud”的配置中心工具“spring cloud config”提供了分布式系統配置文件集中管理解決方案。該工具功能強大,實現也很簡單。網上可以搜索到很多開發教程和用例。本文並不是分享“

spring cloud實戰思考(二) 微服務之間通過fiegn上傳多個文件1

jar 多文件 上傳文件 ret nmap spa 不同 port 問題 需求場景: 微服務之間調用接口一次性上傳多個文件。 上傳文件的同時附帶其他參數。 多個文件能有效的區分開,以便進行不同處理。   Spring cloud的微服務之間接口調用使用Feign。原裝的

spring cloud實戰思考(三) 微服務之間通過fiegn上傳一組文件(下)

ets inf str ceo iter protected let pan ins 需求場景:   用戶調用微服務1的接口上傳一組圖片和對應的描述信息。微服務1處理後,再將這組圖片上傳給微服務2進行處理。各個微服務能區分開不同的圖片進行不同處理。   上一篇博客已經討

Spring Boot實踐——三種攔截器的創建

bsp http etl 當前 出現 規範 not exe () 引用:https://blog.csdn.net/hongxingxiaonan/article/details/48090075 Spring中的攔截器   在web開發中,攔截器是經常用到的功能。它可

Spring Boot實踐——基礎和常用配置

develop google art 容器 .sql pem -i 未定義 eve 借鑒:https://blog.csdn.net/j903829182/article/details/74906948 一、Spring Boot 啟動註解說明 @SpringBoot

Spring Boot實踐——事件監聽

width tar java nco csdn ONBUILD man 初始 ebo 借鑒:https://blog.csdn.net/Harry_ZH_Wang/article/details/79691994    https://blog.csdn.net/igno

2016-06-26 發布 支付系統開發的實踐思考(一)

接口 簡單的 單向 new 成了 異步通知 平臺 應收 技術分享 通常我們在開發手機 app 或網站時都會涉及到支付相關的業務場景,用戶只需要簡單的點擊下按鈕並輸入密碼,就完成了整個支付過程。那麽今天我們就來簡單聊一下一個完整的支

spring boot 實踐學習案例---spring boot 初學者及核心技術鞏固的最佳實踐

    chapter-1-spring-boot-quickstart Spring Boot 入門、Spring Boot 配置、Web 開發、模板引擎、資料儲存、資料快取 案例更新 7 months ago

Android元件化方案實踐思考

Demo地址:https://github.com/751496032/ComponentDemo 效果圖: 背景 Android從誕生到現在,不知不覺的走過十多個年頭了,也產生了很多App,隨著專案的推進不斷的迭代,而App也從最初的單一功能演變成多工功能,各種業務的錯綜

spring boot @Controller@RestController之間的區別

共同點 都是用來表示Spring某個類是否可以接收HTTP請求。 不同點 @Controller標識一個spring類是Spring MVC controller處理器。 @RestController是@Controller和@ResponseBody的結合體。 @Respon