主頁 > 後端開發 > SpringBoot快速入門

SpringBoot快速入門

2022-04-27 06:48:51 後端開發

先說一些廢話

雖然我的作業中更多的是與資料庫打交道,但是作為一個Coder,我覺得掌握前后端的Web技術來說是非常有必要的,

不僅可以幫助我們在作業中更好的理解其他崗位與你對接的人他的作業痛點,也能在公司需要人手的時候成為一個有力的應急幫手,比如之前公司的資料中臺我就參與架構和部分開發任務,更重要的是我私下里可以運用一些快速框架來搭建一些有意思的網站,比如我的個人主頁和個人博客都是我自學javajs所做出來的作品,

所以今天我希望整合一些我以往的經驗和看過的教程檔案,來寫一篇文章,幫助你在一天之內通過這篇文章快速學習SpringBoot框架以及各種開發必備的工具與插件!!!

MVC

什么是MVC

  1. MVC三層架構是指:視圖層 View、服務層 Service,與持久層 Dao,它們分別完成不同的功能
    • View 層:用于接收用戶提交請求的代碼在這里撰寫
    • Service 層:系統的業務邏輯主要在這里完成
    • Dao 層:直接操作資料庫的代碼在這里撰寫
  2. 為了更好的降低各層間的耦合度,在三層架構程式設計中,采用面向抽象編程,即上層對下層的呼叫,是通過介面實作的,而下層對上層的真正服務提供者,是下層介面的實作類
  3. 服務標準(介面)是相同的,服務提供者(實作類)可以更換,這就實作了層間解耦合

MVC 架構程式的作業流程

  1. 用戶通過 View 頁面向服務端提出請求,可以是表單請求、超鏈接請求、AJAX 請求等
  2. 服務端 Controller 控制器接收到請求后對請求進行決議,找到相應的 Model 對用戶請求進行處理
  3. Model 處理后,將處理結果再交給 Controller
  4. Controller 在接到處理結果后,根據處理結果找到要作為向客戶端發回的回應 View 頁面,頁面經渲染(資料填充)后,再發送給客戶端

使用xml還是注解

  1. 應用的基本配置使用xml,比如資料源和資源檔案等
  2. 業務開發使用注解,比如service注入bean
  3. 但是xml越來越多導致越來越臃腫,最終發展到使用完全基于注解開發

注解

宣告Bean注解

@Component 組件沒有明確規定其角色,作用在類級別上宣告當前類為一個業務組件,被Spring IOC 容器維護
@Service 在業務邏輯層(Service)類級別進行宣告
@Registory 在資料訪問層(Dao)類級別進行宣告
@Controller 在展現層(MVC)使用,標注當前類為一個控制器

注入Bean注解

@Autowired 它可以對類成員變數、方法及建構式進行標注,完成自動裝配的作業,通過@Autowired的使用來消除set、get方法
@Inject 作用同上,是JSR-330 標準
@Resource 作用同上,是JSR-250 標準
以上三種注解在Set方法或屬性上宣告,一般情況下更習慣宣告在屬性上,代碼簡潔清晰

配置與獲取Bean注解

@Configuration 將當前類宣告為一個配置類,相當于一個xml組態檔
@ComponentScan 自動掃描包下標注有@Repository @Service @Controller
@Component 注解的類并有Spring IOC 容器進行實體化和維護
@Bean 作用于方法上,宣告當前方法的回傳值是一個Bean物件,相當于xml檔案<bean>宣告當前方法回傳一個bean物件
@Value 獲取properties檔案指定的key/value

pom.xml

作用是添加坐標相關配置,主要是各種依賴jar包

組合注解和元注解

所謂元注解其實就是可以注解到別的注解上的注解,被注解的注解稱之為組合注解,組合注解具備元注解的功能,主要的作用是消除重復注解

自定義注解

個性化的定義自己所需要的功能并宣告一個注解,簡化工程,可以參考文章————SPRINGBOOT自定義注解學習

常用注解

可以參考文章————SpringBoot常用注解集合詳細學習,這里后期會補上說明

@RestController、@ResponseBody、@RequestBody

  1. 相當于@Controller + @ResponseBody兩個注解的結合,回傳JSON資料不需要在方法前面加@ResponseBody注解了,
    但使用@RestController這個注解,就不能回傳jsp、html頁面,視圖決議器無法決議jsp、html頁面v
  2. @ResponseBody表示該方法的回傳結果直接寫入HTTP response body中,一般在異步獲取資料時使用(也就是AJAX),
    在使用@RequestMapping后,回傳值通常決議為跳轉路徑,但是加上@ResponseBody后回傳結果不會被決議為跳轉路徑,而是直接寫入HTTP response body中,
    比如異步獲取JSON資料,加上@ResponseBody后,會直接回傳JSON資料
  3. @RequestBody將 HTTP 請求正文插入方法中,使用適合的 HttpMessageConverter 將請求體寫入某個物件

@MapperScan、@Mapper

  1. @Mapper注解:
    • 作用:在介面類上添加了@Mapper,在編譯之后會生成相應的介面實作類
    • 添加位置:介面類上面
    • 如果想要每個介面都要變成實作類,那么需要在每個介面類上加上@Mapper注解,比較麻煩,解決這個問題用@MapperScan注解
  2. @MapperScan注解:
    • 作用:指定要變成實作類的介面所在的包,然后包下面的所有介面在編譯之后都會生成相應的實作類
    • 添加位置:是在Springboot啟動類上面添加
    • 添加@MapperScan("com.winter.da")注解以后,com.winter.dao包下面的介面類,在編譯之后都會生成相應的實作類

習慣大于配置目標

Spring Boot 的目標是快速運行,快速創建web應用,并獨立機型部署(jar包方式,war包方式),相比于Spring框架是全新重寫的框架

核心配置

修改Banner圖示

主要是通過修改/src/main/resources目錄下的banner.txt檔案,如果沒有則默認使用SpringBoot初始Banner
可以個性化制作Banner的網站制定相應的txt檔案

全域配置

默認是application.properties或者application.yml
坐標依賴都配置在pom.xml中,如果添加了依賴以后標紅可以使用Maven -> Reload project即可

入口類依靠組合注解@SpringBootApplication

@SpringBootConfiguration 本身是一個配置類,啟動類啟動的時候會加載
@EnableAutoConfiguration 組合了@AutoConfigurationPackage&@Import(AutoConfigurationImportSelector.class)
@AutoConfigurationPackage 底層是一個@Import(AutoConfigurationPackage.Registrar.class),其會把啟動類的包下組合都掃描到Spring容器中
@AutoConfigurationImportSelector 讀取大量的自動配置類,完成自動配置,其讀取的是classpath下的META-INF/spring.factories下的組態檔

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)

Profile配置————區分生產和開發環境

通過在application.yml中設定spring.profiles.active=test/dev/prod來動態切換不同環境,例如:

# 開發環境組態檔
application-dev.yml
server:
  prot: 8098

# 測驗環境組態檔
application-test.yml
server:
  prot: 8097

# 生產環境組態檔
application-prod.yml
server:
  prot: 8099

# 主組態檔
application.yml
spring:
  profiles:
    active: dev

日志配置

SpringBoot默認使用LogBack日志系統,一般主流的日志都是用log4j日志系統

如果重復啟動Spring專案,可能會有埠占用的報錯

  1. 思路是殺死占用埠的行程即可,主要是下面兩個命令
  2. 使用netstat -aon|findstr "被占用的埠"或者tasklist |findstr "行程名稱"查詢到埠的行程號
  3. 使用taskkill /f /t /im "行程名稱"或者taskkill /f /t /pid "行程PID"殺死行程即可

事務控制

宣告式事務

可以參考文章————SpringBoot宣告式事務的簡單運用詳細學習,這里后期會補上說明
主要應用在新增修改洗掉上,應用注解即可

全域例外

使用@ControllerAdvice配合@ExceptionHandler

可以參考文章————Springboot系列-@ControllerAdvice使用詳細學習,這里后期會補上說明
此注解其實是一個增強的Controller,使用這個Controller,可實作三個方面的功能,因為這是SpringMVC提供的功能,所以可以在springboot中直接使用

  1. 全域例外處理 (@ExceptionHandler)
  2. 全域資料系結 (@InitBinder)
  3. 全域資料預處理 (@ModelAttribute)
package com.fx67ll.springboot.exceptions;

import com.fx67ll.springboot.po.vo.ResultInfo;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class TestGlobalExceptionHandler {
    @ExceptionHandler(value = https://www.cnblogs.com/fx67ll/archive/2022/04/27/Exception.class)
    @ResponseBody
    public ResultInfo exceptionHandler(Exception exception) {
        ResultInfo resultInfo = new ResultInfo();
        resultInfo.setCode(978);
        resultInfo.setMsg("全域例外攔截,操作失敗!");
//        if (exception instanceof ParamsException) {
//            ParamsException paramsException = (ParamsException) exception;
//            resultInfo.setMsg(paramsException.getMsg());
//            resultInfo.setCode(paramsException.getCode());
//        }
        return resultInfo;
    }
}

資料校驗

為什么要進行后端資料校驗

資料的校驗是互動式網站一個不可或缺的功能,前端的js校驗可以涵蓋大部分的校驗職責,如用戶名唯一性,生日格式,郵箱格式校驗等等常用的校驗,
但是一般前端傳來的資料是不可信的,前端校驗過了,后端也應該重新校驗,因為不排除用戶繞過瀏覽器直接通過Http工具向后端請求的情況,
所以服務端的資料校驗也是必要的,可以防止臟資料落到資料庫中,如果資料庫中出現一個非法的郵箱格式,也會讓運維人員頭疼不已,

如何進行后端資料校驗

  1. SpringBoot中一般使用Spring Validation來進行后端資料校驗,它是對Hibernate Validation進行了二次封裝,
    SpringMVC模塊中添加了自動校驗,并將校驗資訊封裝進了特定的類中
  2. 在使用時我們只需要引入spring-boot-starter-web依賴即可,該模塊會自動依賴spring-boot-starter-validation

Spring Validation 常用注解

@Null:被注釋的元素必須為null
@NotNull:被注釋的元素不能為null,可以為空字串
@AssertTrue:被注釋的元素必須為true
@AssertFalse:被注釋的元素必須為false
@Min(value):被注釋的元素必須是一個數字,其值必須大于等于指定的最小值
@Max(value):被注釋的元素必須是一個數字,其值必須小于等于指定的最大值
@DecimalMin(value):被注釋的元素必須是一個數字,其值必須大于等于指定的最小值
@DecimalMax(value):被注釋的元素必須是一個數字,其值必須小于等于指定的最大值
@Size(max,min):被注釋的元素的大小必須在指定的范圍內
@Digits(integer,fraction):被注釋的元素必須是一個數字,其值必須在可接受的范圍內
@Past:被注釋的元素必須是一個過去的日期
@Future:被注釋的元素必須是一個將來的日期
@Pattern(value):被注釋的元素必須符合指定的正則運算式
@Email:被注釋的元素必須是電子郵件地址
@Length:被注釋的字串的大小必須在指定的范圍內
@Range:被注釋的元素必須在合適的范圍內
@URL:被注解的元素必須是一個URL
@NotEmpty:用在集合類上,不能為null,并且長度必須大于0
@NotBlank:只能作用在String上,不能為null,而且呼叫trim()后,長度必須大于0

自定義注解

可以參考文章————Spring自定義注解(validation)詳細學習,這里后期會補上說明

示例代碼

  1. /com/fx67ll/springboot/controller/UserController.java在傳參的位置添加@Vaild注解表示這里的引數需要校驗,需要注意JSON格式和表單格式傳過來的引數例外會有些區別,需要在后面注意
    // 添加用戶
    @PutMapping("/adduser")
    public ResultInfo saveUser(@RequestBody @Valid User user) {
        ResultInfo resultInfo = new ResultInfo();
        userService.saveUser(user);
        return resultInfo;
    }
    
  2. Bean檔案/com/fx67ll/springboot/dao/User.java中私有欄位上使用注解來校驗,不貼所有代碼了,僅貼部分重點代碼
    @NotBlank(message = "用戶名稱不能為空!")
    private String userName;
    
    @NotBlank(message = "用戶密碼不能為空!")
    @Length(min = 6, max = 20, message = "密碼長度最少六位且最多二十位!")
    private String userPwd;
    
  3. 在全域自定義例外攔截中/com/fx67ll/springboot/exceptions/TestGlobalExceptionHandler.java向用戶回傳錯誤代碼和資訊
    package com.fx67ll.springboot.exceptions;
    
    import com.fx67ll.springboot.po.vo.ResultInfo;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @ControllerAdvice
    public class TestGlobalExceptionHandler {
    
    	@ExceptionHandler(value = https://www.cnblogs.com/fx67ll/archive/2022/04/27/Exception.class)
    	@ResponseBody
    	public ResultInfo exceptionHandler(Exception exception) {
    		ResultInfo resultInfo = new ResultInfo();
    		resultInfo.setCode(978);
    		resultInfo.setMsg("全域例外攔截,操作失敗!");
    		// 全域資料校驗,注意!!!使用 json 請求體呼叫介面,校驗例外拋出 MethodArgumentNotValidException
    		if (exception instanceof MethodArgumentNotValidException) {
    			MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) exception;
    			resultInfo.setCode(1023);
    			resultInfo.setMsg(methodArgumentNotValidException.getBindingResult().getFieldError().getDefaultMessage());
    		}
    		return resultInfo;
    	}
    }
    

靜態資源

默認配置下,我們可以在resources資源目錄下存放web應用靜態資源檔案
自定義靜態資源路徑,可以通過在spring.resources.static-locations后面追加一個配置classpath:/你自定義的配置目錄/,例如:

# application.yml
spring:
  resources:
	# 多個目錄使用逗號隔開
    static-loaction: classpath:/public/,classpath:/static/,classpath:/fx67ll/

打包和部署

jar包

  1. 一般用于撰寫依賴工具包
  2. 打包
    • 在IDEARun/Debug ConfigurationsCommand line配置clean complie package -Dmaven.test.skip=true執行打包命令
    • target目錄得到待部署的專案檔案
  3. 部署
    • 在dos視窗中,執行命令java -jar jar包所在的本地目錄

war包

  1. 在生產環境中最為常見的部署方式
  2. 修改pom.xml,設定打包模式為war包
    <groupId>com.fx67ll</groupId>
    <artifactId>springboot-quickstart</artifactId>
    <version>0.1.0</version>
    <!--設定為war包模式-->
    <packaging>war</packaging>
    
  3. 忽略內嵌Tomcat
    <!--設定為外部已提供,表示忽略-->
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-tomcat</artifactId>
    	<scope>provided</scope>
    </dependency>
    
  4. 配置生成的war包名稱
    <build>
    <!--設定war包名稱-->
        <finalName>fx67ll-springboot-quickstart-test</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    
  5. 修改Starter類,添加容器啟動加載檔案(類似讀取web.xml檔案)
    • 這里通過繼承SpringBootServletInitiallizer類并重寫configure方法來實作
    • 在部署專案的時候指定外部Tomcat讀取專案入口方法
    @SpringBootApplication
    public class Starter extends SpringBootServletInitializer {
    	
    	public static void main(String[] args) {
    		SpringApplication.run(Starter.class);
    	}
    	
    	@Override
    	protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
    		return builder.sources(Starter.class);
    	}
    }
    
  6. 打包
    • 在IDEARun/Debug ConfigurationsCommand line配置clean complie package -Dmaven.test.skip=true執行打包命令
    • target目錄得到待部署的專案檔案
  7. 部署并訪問
    • 放置到外部tomcat中,執行bin目錄下start腳本即可

熱部署

熱部署,就是在應用正在運行的時候升級軟體,卻不需要重新啟動應用,主要應用在開發程序中

熱部署原理

  1. spring-boot-devtools是一個為開發者服務的一個模塊,其中最重要的功能就是自動應用代碼更改到最新的App上面去,
    原理是在發現代碼有更改之后,重新啟動應用,但是速度比手動停止后再啟動還要更快,更快指的不是節省出來的手工操作的時間
  2. 其深層原理是使用了兩個ClassLoader,一個Classloader加載那些不會改變的類(第三方Jar包),另一個ClassLoader加載會更改的類,稱為restart ClassLoader
    這樣在有代碼更改的時候,原來的restart ClassLoader被丟棄,重新創建一個restart ClassLoader,由于需要加載的類相比較少,所以實作了較快的重啟時間,大概在5秒以內

devtools原理

  1. devtools會監聽classpath下的檔案變動,并且會立即重啟應用(發生在保存時機)注意:因為其采用的虛擬機機制,該項重啟是很快的
  2. devtools可以實作頁面熱部署(即頁面修改后會立即生效,這個可以直接在application檔案中配置spring.thymeleaf.cache=false來實作 注意:不同的模板配置不一樣

熱部署主要步驟

  1. pom.xml中添加依賴,同時添加devtools生效標志插件
    <!--熱部署插件devtools-->
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-devtools</artifactId>
    	<!--表示當前這個專案被繼承之后,這個不向下傳遞-->
    	<optional>true</optional>
    </dependency>
    
    <plugin>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-maven-plugin</artifactId>
    	<!--在原有的基礎上添加-->
    	<configuration>
    		<!--如果沒有該配置,熱部署插件devtools不生效-->
    		<fork>true</fork>
    	</configuration>
    </plugin>
    
  2. 修改application.yml全域組態檔,在application.yml中配置spring.devtools.restart.enable=false,此時restart類加載器還會初始化,但不會監視檔案更新
    spring:
      # 熱部署配置
      devtools:
    	restart:
    	  enabled: true
    	  # 設定重啟的目錄,添加目錄的檔案需要restart
    	  additional-paths: src/main/java
    	  # 解決專案啟動重新編譯后介面報404的問題
    	  poll-interval: 3000
    	  quiet-period: 1000
    
  3. 修改 IDEA 配置
    • 修改了java類之后,IDEA 默認是不自動編譯的,而spring-boot-devtools又是監測classpath下的檔案發生變化才會重啟應用,所以需要設定 IDEA 的自動編譯
    • 設定自動配置 File -> Settings -> Build -> Complier -> Build Project automatically
    • 修改Register屬性,執行快捷鍵ctrl + shift + alt + /,選擇Register,勾上Complier autoMake allow when app running
    • 注意 IDEA 2021.2.3 版本中沒有上面的選項,遷移到了File -> Settings -> Tools -> Advanced Settings -> Complier -> Allow auto-make to start......
  4. 配置完需要重啟一下,然后有修改的話專案會自動更新,但是如果是自動觸發的話,會造成頻繁更新,對硬體有一定的負擔,所以可以改成手動觸發模式
    • 點擊右上角 Run/Debug Configurations
    • 選擇下拉 Configuration -> Spring Boot -> Running Application Update Policies -> On 'Update' action
    • 選擇 Update classes and resources
    • 如果有更新可以,使用快捷鍵 Ctrl + F10 重新編譯
  5. 快捷鍵Ctrl + F9,使用熱部署重新啟動

單元測驗

依賴

<!--單元測驗-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
</dependency>

Service業務層————業務邏輯方法測驗

需要注意的是:

  1. 如果在和main檔案夾平級的test檔案夾下新建了java檔案夾,但是無法新建java class檔案
  2. 那么就需要右鍵檔案夾 Mark Directory as -> Test Sources Root之后,檔案夾變綠即可
# 示例代碼
package com.fx67ll.springboot.service;

import com.fx67ll.springboot.Starter;
import com.fx67ll.springboot.po.User;
import com.fx67ll.springboot.query.UserQuery;
import com.fx67ll.springboot.srevice.UserService;
import com.github.pagehelper.PageInfo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

/**
 * Service業務方法測驗
 *
 * Junit中的RunWith注解 表示該類是單元測驗的執行類
 * SpringRunner 是 spring-test 提供的測驗執行單元類(是Spring單元測驗中SpringJUnit4ClassRunner的新名字)
 * SpringBootTest注解 是執行測驗程式的引導類
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Starter.class})
public class TestUserService {

    // 日志的使用
    private Logger logger = LoggerFactory.getLogger(TestUserService.class);

    @Resource
    private UserService userService;

    @Before
    public void before() {
        logger.info("單元測驗開始......");
    }

    @Test
    public void testQueryUserById() {
        logger.info("測驗根據用戶id查詢......");

        User user = userService.queryUserById(1);
        logger.info("用戶記錄: {}", user.toString());
    }

    @Test
    public void testSelectUserListByParams() {
        logger.info("測驗根據分頁條件查詢用戶串列......");

        UserQuery userQuery = new UserQuery();
        PageInfo<User> pageInfo = userService.selectUserListByParams(userQuery);
        logger.info(pageInfo.toString());
    }

    @After
    public void after() {
        logger.info("單元測驗結束......");
    }
}

controller控制層————介面方法測驗

使用MockMVC進行測驗

MockMvc是由spring-test包提供,實作了對Http請求的模擬,能夠直接使用網路的形式,轉換到Controller的呼叫,使得測驗速度快、不依賴網路環境,
同時提供了一套驗證的工具,結果的驗證十分方便

什么是Mock

在面向物件的程式設計中,模擬物件mock object是以可控的方式模擬真實物件行為的假物件,
在編程程序中,通常通過模擬一些輸入資料,來驗證程式是否達到預期結果

介面MockMvcBuilder

提供一個唯一的build方法,用來構造MockMvc
主要有兩個實作:StandaloneMockMvcBuilderDefaultMockMvcBuilder,分別對應兩種測驗方式,
即獨立安裝和集成Web環境測驗(并不會集成真正的web環境,而是通過相應的Mock API進行模擬測驗,無須啟動服務器),
MockMvcBuilders提供了對應的創建方法standaloneSetup方法和webAppContextSetup方法,在使用時直接呼叫即可,

# 示例代碼
# PS:雖然提示測驗通過,但是控制臺一直沒有列印出回傳資訊的記錄,后期有空看看
package com.fx67ll.springboot.controller;

import com.fx67ll.springboot.Starter;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Starter.class})
@AutoConfigureMockMvc
public class TestUserController {

    // 日志的使用
    private Logger logger = LoggerFactory.getLogger(TestUserController.class);

    @Autowired
    private MockMvc mockMvc;

    /**
     * 模擬測驗用戶串列查詢
     * 其實就在模擬真實環境下前端對后端發起的請求
     */
    @Test
    public void apiTestSelectUserListByParams() throws Exception {

        logger.info("開始模擬發送查詢用戶串列的請求......");

        // 構建請求
        MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/user/list")
                .contentType("text/html") // 設定請求頭資訊
                .accept(MediaType.APPLICATION_JSON); // 設定請求Accept頭資訊

        // 發送請求
        ResultActions perform = mockMvc.perform(requestBuilder);

        // 校驗請求結果
        perform.andExpect(MockMvcResultMatchers.status().isOk());

        // 獲取執行完成后回傳的結果
        MvcResult mvcResult = perform.andReturn();

        // 得到執行后的回應
        MockHttpServletResponse response = mvcResult.getResponse();

        // 列印結果
        logger.info(String.valueOf(response.getContentLength()));
        logger.info("回應狀態: ", response.getStatus());
        logger.info("回應資訊: ", response.getContentAsString());

        logger.info("結束模擬發送查詢用戶串列的請求......");
    }

    @Test
    public void apiTestQueryUserByUsername() throws Exception {

        logger.info("開始模擬根據用戶名查詢用戶記錄的請求......");

        // 構建請求并發送
        MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/user/name/admin"))
                .andExpect(MockMvcResultMatchers.status().isOk()).andReturn();

        // 列印結果
        logger.info("回應狀態: ", mvcResult.getResponse().getStatus());
        logger.info("回應資訊: ", mvcResult.getResponse().getContentAsString());

        logger.info("結束模擬根據用戶名查詢用戶記錄的請求......");
    }
}

Swagger2檔案工具

依賴

pom.xml中添加以下代碼

<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger2</artifactId>
	<version>2.9.2</version>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger-ui</artifactId>
	<version>2.9.2</version>
</dependency>

常用注解

可以參考文章————swagger2 注解說明詳細學習,這里后期會補上說明

@Api

主要是用在請求類上,用于說明該類的作用

# 示例
@Api(tags = "xx模塊")

@ApiOperation

主要是用在請求的方法上,說明方法的作用

# 示例
@ApiOperation(value = "https://www.cnblogs.com/fx67ll/archive/2022/04/27/xx方法的作用", notes = "xx方法的備注說明")

@ApiImplicitParams、@ApiImplicitParam

主要是用在請求的方法上,說明方法的引數

# 詳細引數說明
@ApiImplicitParams:用在請求的方法上,包含一組引數說明
	@ApiImplicitParam:對單個引數的說明	    
	    name:引數名
	    value:引數的說明、描述
	    required:引數是否必須必填
	    paramType:引數放在哪個地方
	        · query --> 請求引數的獲取:@RequestParam
	        · header --> 請求引數的獲取:@RequestHeader	      
	        · path(用于restful介面)--> 請求引數的獲取:@PathVariable
	        · body(請求體)-->  @RequestBody User user
	        · form(普通表單提交)	   
	    dataType:引數型別,默認String,其它值dataType="Integer"	   
	    defaultValue:引數的默認值
	
# 單個引數示例	
@ApiImplicitParam(name = "xxx", value = "https://www.cnblogs.com/fx67ll/archive/2022/04/27/xxx", required = true, paramType = "path", dataType = "String", defaultValuehttps://www.cnblogs.com/fx67ll/archive/2022/04/27/= "")

# 多個引數示例
@ApiImplicitParams({
	@ApiImplicitParam(name = "xxxa", value = "https://www.cnblogs.com/fx67ll/archive/2022/04/27/xxxa", required = true, paramType = "body", dataType = "String", defaultValuehttps://www.cnblogs.com/fx67ll/archive/2022/04/27/= ""),
	@ApiImplicitParam(name = "xxxb", value = "https://www.cnblogs.com/fx67ll/archive/2022/04/27/xxxb", required = true, paramType = "body", dataType = "String", defaultValuehttps://www.cnblogs.com/fx67ll/archive/2022/04/27/= ""),
})

@ApiResponses、@ApiResponse

主要是用在請求的方法上,說明錯誤回應的資訊

# 詳細引數說明
@ApiResponses:回應狀態的說明,是個陣列,可包含多個 @ApiResponse
	@ApiResponse:每個引數的說明
	    code:數字,例如400
	    message:資訊,例如"請求引數沒填好"
	    response:拋出例外的類
	
# 多個引數示例,一般回應都是多個code,所以不寫單個引數的示例了
@ApiResponses({
		@ApiResponse(code = 200, message = "請求成功"),
		@ApiResponse(code = 578, message = "請求引數錯誤"),
		@ApiResponse(code = 404, message = "請求路徑沒有或頁面跳轉路徑不對")
})

@ApiModel、@ApiModelProperty

  1. @ApiModel 經常用于請求的入參物件和回應回傳值物件的描述
    • 入參是物件,即 @RequestBody 時, 用于封裝請求(包括資料的各種校驗)資料
    • 回傳值是物件,即 @ResponseBody 時,用于回傳值物件的描述
  2. @ApiModelProperty 用于每個屬性上面,說明屬性的含義
# 示例
@ApiModel(description = "用戶物體類")
public class User {
    @ApiModelProperty(value = "https://www.cnblogs.com/fx67ll/archive/2022/04/27/用戶名", required = true, example = "0")
    private Integer id;
    
	@ApiModelProperty(value = "https://www.cnblogs.com/fx67ll/archive/2022/04/27/用戶ID", required = true, example = "fx67ll")
    private String userName;
    
	@ApiModelProperty(value = "https://www.cnblogs.com/fx67ll/archive/2022/04/27/用戶密碼", required = true, example = "xxxxxxxx")
    private String userPwd;
}

分布式快取工具Ehcache

什么是Ehcache

EhCache是一個純Java的行程內快取框架,具有快速、精干等特點,是Hibernate中默認CacheProvider
Ehcache是一種廣泛使用的開源Java分布式快取,主要面向通用快取,Java EE輕量級容器
它具有記憶體和磁盤存盤,快取加載器,快取擴展,快取例外處理程式,一個gzip快取servlet過濾器,支持REST APISOAP API等特點,

SpringCache相關注解

SpringBoot快取實作內部使用SpringCache實作快取控制,這里集成Ehcache實際上是對SpringCache抽象的一種實作
可以參考文章————Spring Cache 簡介詳細學習,這里后期會補上說明

@EnableCaching

開啟快取功能,一般放在啟動類上

@CacheConfig

當我們需要快取的地方越來越多,你可以使用@CacheConfig(cacheNames = {"cacheName"})注解在Class之上來統一指定value的值,
這時可省略value,如果你在你的方法依舊寫上了value,那么依然以方法的value值為準

@Cacheable

根據方法對其回傳結果進行快取,下次請求時,如果快取存在,則直接讀取快取資料回傳;如果快取不存在,則執行方法,并把回傳的結果存入快取中,一般用在查詢方法上
注意value后面要使用ehcache.xml檔案中所列的cache.name

# 單個引數示例代碼
@Cacheable(value = "https://www.cnblogs.com/fx67ll/archive/2022/04/27/fx67llCache", key = "#xxx")

# 多個引數示例,采用拼接的方式
@Cacheable(value = "https://www.cnblogs.com/fx67ll/archive/2022/04/27/fx67llCache", key = "#xxx.xxx + '-' + #xxx.xxx + '-' + #xxx.xxx")

@CachePut

使用該注解標志的方法,每次都會執行,并將結果存入指定的快取中,其他方法可以直接從回應的快取中讀取快取資料,而不需要再去查詢資料庫,一般用在新增方法上

# 示例代碼
@CachePut(value = "https://www.cnblogs.com/fx67ll/archive/2022/04/27/fx67llCache", key = "#xxx.xxx")

@CacheEvict

使用該注解標志的方法,會清空指定的快取,一般用在更新或者洗掉方法上

# 示例代碼
@CacheEvict(value = "https://www.cnblogs.com/fx67ll/archive/2022/04/27/fx67llCache", key = "#xxx")

@Caching

該注解可以實作同一個方法上同時使用多種注解

Ehcache的使用

  1. pom.xml添加依賴
    <!--Ehcache工具依賴-->
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <dependency>
    	<groupId>net.sf.ehcache</groupId>
    	<artifactId>ehcache</artifactId>
    </dependency>
    
  2. 添加ehcache.xml檔案
    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache name="fx67llCache">
    	<!--
    	   diskStore:為快取路徑,ehcache分為記憶體和磁盤兩級,此屬性定義磁盤的快取位置,引數解釋如下:
    	   user.home – 用戶主目錄
    	   user.dir  – 用戶當前作業目錄
    	   java.io.tmpdir – 默認臨時檔案路徑
    	 -->
    	<diskStore path="D:\Java\test-ehcache-cache"/>
    
    	<!--
    	   defaultCache:默認快取策略,當ehcache找不到定義的快取時,則使用這個快取策略,只能定義一個,
    	 -->
    
    	<!--
    	  name:快取名稱,
    	  maxElementsInMemory:快取最大數目
    	  maxElementsOnDisk:硬碟最大快取個數,
    	  eternal:物件是否永久有效,一但設定了,timeout將不起作用,
    	  overflowToDisk:是否保存到磁盤,當系統當機時
    	  timeToIdleSeconds:設定物件在失效前的允許閑置時間(單位:秒),僅當eternal=false物件不是永久有效時使用,可選屬性,默認值是0,也就是可閑置時間無窮大,
    	  timeToLiveSeconds:設定物件在失效前允許存活時間(單位:秒),最大時間介于創建時間和失效時間之間,僅當eternal=false物件不是永久有效時使用,默認是0.,也就是物件存活時間無窮大,
    	  diskPersistent:是否快取虛擬機重啟期資料 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
    	  diskSpoolBufferSizeMB:這個引數設定DiskStore(磁盤快取)的快取區大小,默認是30MB,每個Cache都應該有自己的一個緩沖區,
    	  diskExpiryThreadIntervalSeconds:磁盤失效執行緒運行時間間隔,默認是120秒,
    	  memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理記憶體,默認策略是LRU(最近最少使用),你可以設定為FIFO(先進先出)或是LFU(較少使用),
    	  clearOnFlush:記憶體數量最大時是否清除,
    	  memoryStoreEvictionPolicy:可選策略有:LRU(最近最少使用,默認策略)、FIFO(先進先出)、LFU(最少訪問次數),
    		   FIFO,first in first out,這個是大家最熟的,先進先出,
    		   LFU, Less Frequently Used,就是上面例子中使用的策略,直白一點就是講一直以來最少被使用的,如上面所講,快取的元素有一個hit屬性,hit值最小的將會被清出快取,
    		   LRU,Least Recently Used,最近最少使用的,快取的元素有一個時間戳,當快取容量滿了,而又需要騰出地方來快取新的元素的時候,那么現有快取元素中時間戳離當前時間最遠的元素將被清出快取,
       -->
    	<defaultCache
    			maxElementsInMemory="10000"
    			eternal="false"
    			timeToIdleSeconds="120"
    			timeToLiveSeconds="120"
    			maxElementsOnDisk="10000000"
    			diskExpiryThreadIntervalSeconds="120"
    			memoryStoreEvictionPolicy="LRU"/>
    
    	<cache
    			name="fx67llCache"
    			eternal="false"
    			maxElementsInMemory="100"
    			overflowToDisk="false"
    			diskPersistent="false"
    			timeToIdleSeconds="0"
    			timeToLiveSeconds="300"
    			memoryStoreEvictionPolicy="LRU"/>
    
    </ehcache>
    
  3. application.yml添加快取配置
    # Ehcache 快取配置
    cache:
      ehcache:
        config: classpath:ehcache.xml
    
  4. 在入口類添加@EnableCaching注解,表示開啟快取
  5. Java Bean 物件實作序列化,public class User implements Serializable
  6. 在需要使用的地方使用現關注解,實作快取可以減少從資料庫查詢的次數

定時調度工具Quartz

可以參考文章————Quartz定時調度詳細學習,這里后期會補上說明

什么是Quartz

在日常專案運行中,我們總會有需求在某一時間段周期性的執行某個動作,比如每天在某個時間段匯出報表,或者每隔多久統計一次現在在線的用戶量等,
在SpringBoot中有Java自帶的java.util.Timer類,也可以在啟動類添加@EnableScheduling注解引入定時任務環境

Quartz的使用

  1. pom.xml添加依賴
    <!--Quartz工具依賴-->
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>
    
  2. 添加job包并撰寫job任務,實作job介面,并在execute方法中實作自己的業務邏輯
    package com.fx67ll.springboot.jobs;
    
    import org.quartz.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class TestQuartzJob implements Job {
    
    	private Logger logger = LoggerFactory.getLogger(TestQuartzJob.class);
    
    	@Override
    	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
    
    		// 獲取整理好的日期時間
    		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    		// 查詢觸發器名稱和觸發器屬于哪個分組
    		TriggerKey triggerKey = jobExecutionContext.getTrigger().getKey();
    
    		//列印日志
    		logger.info("當前觸發器是: " + triggerKey.getName() + ",它所屬的組別是: " + triggerKey.getGroup() +
    				"----------觸發時間: " + simpleDateFormat.format(new Date()) +
    				"-->" + "Hello fx67ll Spring Boot Quartz......");
    	}
    }
    
  3. 構建調度配置類,創建JobDetail實體并定義Trigger注冊到scheduler,啟動scheduler開啟調度
    package com.fx67ll.springboot.conf;
    
    import com.fx67ll.springboot.jobs.TestQuartzJob;
    import org.quartz.*;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class QuartzCOnf {
    	@Bean
    	/**
    	 * 具體的可以被執行的調度程式
    	 */
    	public JobDetail jobDetailTestQuartz(){
    		return JobBuilder.newJob(TestQuartzJob.class).storeDurably().build();
    	}
    
    	@Bean
    	/**
    	 * 第一個測驗觸發器,主要是配置引數提示什么時候呼叫
    	 * 應用場景有比如定時發送郵件之類的
    	 */
    	public Trigger triggerTestQuartzFirst(){
    		SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
    				// 每五秒執行一次
    				.withIntervalInSeconds(1)
    				// 永久重復,一直執行下去
    				.repeatForever();
    		return TriggerBuilder.newTrigger()
    				// 設定觸發器名稱和分組
    				.withIdentity("triggerTestQuartzFirst","groupTestQuartz")
    				.withSchedule(simpleScheduleBuilder)
    				.forJob(jobDetailTestQuartz())
    				.build();
    	}
    
    	@Bean
    	/**
    	 * 第二個測驗觸發器
    	 */
    	public Trigger triggerTestQuartzSecond(){
    		return TriggerBuilder.newTrigger()
    				// 設定觸發器名稱和分組
    				.withIdentity("triggerTestQuartzSecond","groupTestQuartz")
    				// 這里是通過定義運算式來表示每5秒執行一次,后續再深入研究下
    				.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ? *"))
    				.forJob(jobDetailTestQuartz())
    				.build();
    	}
    }
    

附錄

操作代碼目錄說明

springboot-quickstart springboot-mybatis springboot-mybatis-crud springboot-mybatis-crud-prod
快速入門 整合mybatis 整套crud操作 生產環境開發

操作代碼資源地址

  1. springboot-quickstart
  2. springboot-mybatis
  3. springboot-mybatis-crud
  4. springboot-mybatis-crud-prod

參考資料

  1. 參考教程 ———— 兩天搞定SpringBoot框架
  2. 參考檔案 ———— JavaSpringBoot 中 @Autowired用法
  3. 參考檔案 ———— SpringBoot - @Configuration、@Bean注解的使用詳解(配置類的實作)
  4. 參考檔案 ———— 【Spring Boot】Spring基礎 —— 組合注解與元注解
  5. 參考檔案 ———— @RestController 和 @Controller 的區別
  6. 參考檔案 ———— MapperScan注解詳解
  7. 參考檔案 ———— Mapper.xml詳解
  8. 參考檔案 ———— MVC三層架構(詳解)
  9. 參考檔案 ———— 配置devtools熱部署
  10. 參考檔案 ———— (十三)SpringBoot2.0熱部署Devtools原理
  11. 參考檔案 ———— 2021版IDEA沒有compiler.automake.allow.when.app.running
  12. 參考檔案 ———— SpringBoot基礎之MockMvc單元測驗
  13. 參考檔案 ———— Ehcache詳細解讀
  14. 參考檔案 ———— spring boot接入ehcache
  15. 參考檔案 ———— SpringBoot(十二): validation常用注解
  16. 參考檔案 ———— SpringBoot之——Validator校驗相關的注解
  17. 參考檔案 ———— 強悍的Spring之spring validation
  18. json格式校驗并顯示錯誤_使用 Spring Validation 優雅地進行引數校驗

我是 fx67ll.com,如果您發現本文有什么錯誤,歡迎在評論區討論指正,感謝您的閱讀!
如果您喜歡這篇文章,歡迎訪問我的 本文github倉庫地址,為我點一顆Star,Thanks~ ??
轉發請注明參考文章地址,非常感謝!!!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/465019.html

標籤:其他

上一篇:Java面試題資料合集

下一篇:一次不規范HTTP請求引發的nginx回應400問題分析與解決

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more