Springboot 配置屬性綁定實(shí)現(xiàn)方式詳解
配置屬性綁定詳解
@ConfigurationProperties
導(dǎo)入配置文件處理器,在配置文件進(jìn)行數(shù)據(jù)綁定時(shí)就會(huì)有提示
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐configuration‐processor</artifactId>
<optional>true</optional>
</dependency>編寫實(shí)體類,Person 和 Dog 的 JavaBean
package com.qcby.springboot.domain;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private boolean boss;
private Date birth;
private Map<String,String> maps;
private List<String> list;
private Dog dog;
public Person() {
}
public Person(String lastName, Integer age, boolean boss, Date birth, Map<String, String> maps, List<String> list, Dog dog) {
this.lastName = lastName;
this.age = age;
this.boss = boss;
this.birth = birth;
this.maps = maps;
this.list = list;
this.dog = dog;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public boolean isBoss() {
return boss;
}
public void setBoss(boolean boss) {
this.boss = boss;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, String> getMaps() {
return maps;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "Person{" +
"lastName='" + lastName + '\'' +
", age=" + age +
", boss=" + boss +
", birth=" + birth +
", maps=" + maps +
", list=" + list +
", dog=" + dog +
'}';
}
}@ConfigurationProperties 注解用于告知 Spring Boot 將當(dāng)前類的所有字段與配置文件中相關(guān)前綴對(duì)應(yīng)的配置項(xiàng)進(jìn)行批量綁定;
prefix = “person” 用于明確綁定配置文件中以 person 為前綴的所有子屬性,與當(dāng)前類字段進(jìn)行一一映射;
關(guān)鍵前提是只有當(dāng)當(dāng)前組件是 Spring 容器中的 Bean(通過 @Component 注解注冊(cè)),才能使用容器提供的@ConfigurationProperties屬性綁定功能。
package com.qcby.springboot.domain;
public class Dog {
private String name;
private Integer age;
public Dog() {
}
public Dog(String name, Integer age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}application.yml 是 Spring Boot 全局固定名稱的配置文件(與 application.properties 功能一致),以數(shù)據(jù)為核心,語法簡(jiǎn)潔、層級(jí)清晰,比 JSON/XML 更適合作為配置文件。
關(guān)鍵語法規(guī)則
縮進(jìn)控制層級(jí):必須用空格(不能用 Tab),縮進(jìn)量不固定,同一層級(jí)左對(duì)齊即可;
大小寫敏感:屬性名、值的大小寫嚴(yán)格區(qū)分;
鍵值分隔:屬性名和值之間用 : 分隔,且 : 后必須加空格;
YAML 核心值類型寫法
- 字面量(數(shù)字、字符串、布爾)
字面量是最基礎(chǔ)的配置值,直接對(duì)應(yīng) Java 中的基本類型
數(shù)字 / 布爾:直接寫值,無需引號(hào);
字符串:默認(rèn)無引號(hào),特殊字符(如 \n)會(huì)被當(dāng)作普通字符;
雙引號(hào)(“”):不轉(zhuǎn)義特殊字符,按原含義生效;
單引號(hào)(‘’):轉(zhuǎn)義特殊字符,特殊字符僅作為普通字符串; - 對(duì)象 / Map(鍵值對(duì)集合)
對(duì)應(yīng) Java 中的 Map 或自定義實(shí)體類;
嵌套式通過縮進(jìn)表示層級(jí),鍵值之間用 : 分隔(key: value);
行內(nèi)式用 {key1: value1, key2: value2, …} 包裹,逗號(hào)分隔; - 數(shù)組 / List / Set
元素支持字面量、對(duì)象等任意類型;
縮進(jìn)式元素前加 - (橫杠 + 空格)開頭表示列表項(xiàng),縮進(jìn)一致;
行內(nèi)式用 [值1, 值2, …] 包裹,逗號(hào)分隔; - 占位符使用(動(dòng)態(tài)賦值)
引用已配置的屬性:${屬性名};
生成隨機(jī)值:${random.value}、${random.int}、${random.int(10)}、${random.int[1024,65536]};
默認(rèn)值:${屬性名:默認(rèn)值}(屬性不存在時(shí)用默認(rèn)值)。

將配置文件中 person 前綴下的所有屬性,自動(dòng)映射到 Person 類的對(duì)應(yīng)字段中,包括基本類型、日期、集合(List/Map)、嵌套對(duì)象等,最終通過容器 Bean 在項(xiàng)目中直接使用配置值。
需要注意的是測(cè)試單元的三級(jí)包與代碼的三級(jí)包名稱需要保持一致
package com.qcby.springboot;
import com.qcby.springboot.domain.Person;
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;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootTest {
@Autowired
private Person person;
@Test
public void contextLoads(){
System.out.println(person);
}
}運(yùn)行 contextLoads() 測(cè)試方法時(shí),JUnit 會(huì)先讀取 @RunWith(SpringRunner.class),使用 Spring 提供的 SpringRunner 運(yùn)行器(其中 SpringRunner 是 SpringJUnit4ClassRunner 的簡(jiǎn)化別名),SpringRunner 識(shí)別到 @SpringBootTest 注解,觸發(fā) SpringBoot 的自動(dòng)配置,啟動(dòng) Spring Boot 應(yīng)用上下文(容器),容器啟動(dòng)過程中會(huì)進(jìn)行掃描組件和屬性綁定,掃描項(xiàng)目中的 @Configuration 配置類,找到 Person 類上的 @Component 將其注冊(cè)為容器 Bean,通過 @ConfigurationProperties(prefix = “person”) 讀取配置文件中 person 前綴的屬性,注入 Person Bean 的字段。容器啟動(dòng)完成后,@Autowired Person person 從容器中找到并注入測(cè)試類的 Person Bean,執(zhí)行 contextLoads() 方法,打印 person 對(duì)象,調(diào)用 toString() 輸出結(jié)果,測(cè)試結(jié)束后,Spring 容器自動(dòng)銷毀,釋放資源。

若測(cè)試單元的三級(jí)包與代碼的三級(jí)包名稱不一致,會(huì)出現(xiàn) Spring Boot 測(cè)試啟動(dòng)時(shí)找不到核心配置類報(bào)錯(cuò)

Spring 測(cè)試默認(rèn)只掃描測(cè)試類所在的包(com.qcby.qcbyjy)及其子包,但主配置類在 com.qcby.springboot,不在掃描范圍內(nèi),所以找不到。
驗(yàn)證YAML 字符串類型寫法
雙引號(hào)(“”)不轉(zhuǎn)義特殊字符,按原含義生效,單引號(hào)(‘’)轉(zhuǎn)義特殊字符,特殊字符僅作為普通字符串


java.util.Date 傳統(tǒng)日期類型默認(rèn)支持斜杠分隔(yyyy/MM/dd)不默認(rèn)支持橫杠分隔(yyyy-MM-dd)格式

驗(yàn)證占位符的使用

@Value 屬性注入
@Value 是一個(gè)核心注解,用于給 Spring 管理的 Bean 屬性注入值
第一種常見注入場(chǎng)景:直接注入常量值
如果屬性值是固定的常量,可以直接用 @Value(“常量”) 注入屬性值(字符串需加引號(hào),數(shù)字 / 布爾無需,不支持復(fù)雜類型的注入),無需配置文件。
package com.qcby.springboot.domain;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Component
public class Person1 {
@Value("zhangsan@123.com")
private String Email;
@Value("zhangsan")
private String lastName;
@Value("#{11*2}")
private Integer age;
@Value("true")
private Boolean boss;
@Value("2025/11/12")
private Date birth;
private Map<String,Object> maps;
private List<Object> list;
private Dog dog;
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getBoss() {
return boss;
}
public void setBoss(Boolean boss) {
this.boss = boss;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getLists() {
return list;
}
public void setLists(List<Object> lists) {
this.list = lists;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "Person1{" +
"Email='" + Email + '\'' +
", lastName='" + lastName + '\'' +
", age=" + age +
", boss=" + boss +
", birth=" + birth +
", maps=" + maps +
", lists=" + list +
", dog=" + dog +
'}';
}
}
第二種注入配置文件(application.properties/yaml)中的值
package com.qcby.springboot.domain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Component
public class Person2 {
@Value("${person.Email}")
private String Email;
@Value("${person.lastName}")
private String lastName;
@Value("${person.age}")
private Integer age;
@Value("${person.boss}")
private Boolean boss;
@Value("${person.birth}")
private Date birth;
private Map<String,Object> maps;
private List<Object> list;
@Autowired
private Dog1 dog1;
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getBoss() {
return boss;
}
public void setBoss(Boolean boss) {
this.boss = boss;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getList() {
return list;
}
public void setList(List<Object> list) {
this.list = list;
}
public Dog1 getDog1() {
return dog1;
}
public void setDog1(Dog1 dog1) {
this.dog1 = dog1;
}
@Override
public String toString() {
return "Person2{" +
"Email='" + Email + '\'' +
", lastName='" + lastName + '\'' +
", age=" + age +
", boss=" + boss +
", birth=" + birth +
", maps=" + maps +
", list=" + list +
", dog1=" + dog1 +
'}';
}
}package com.qcby.springboot.domain;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Dog1 {
@Value("${person.dog.name}")
private String name;
@Value("${person.dog.age}")
private Integer age;
public Dog1() {
}
public Dog1(String name, Integer age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Dog1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

@Validated 數(shù)據(jù)校驗(yàn)
Spring Boot 2.3.0 之前,spring-boot-starter-web 會(huì)默認(rèn)傳遞依賴 spring-boot-starter-validation,而該 starter 已包含 Hibernate Validator(數(shù)據(jù)校驗(yàn)實(shí)現(xiàn)核心)。
Spring Boot 2.3.0 發(fā)布后,官方將 spring-boot-starter-validation 從 spring-boot-starter-web/spring-boot-starter-webflux 的默認(rèn)傳遞依賴中移除,因此,若需使用 @Validated 實(shí)現(xiàn)參數(shù)校驗(yàn),必須手動(dòng)引入 spring-boot-starter-validation,否則僅能使用注解標(biāo)記,校驗(yàn)邏輯不會(huì)執(zhí)行(無報(bào)錯(cuò),僅不生效)。
<!-- 2.3.0 之后的版本需手動(dòng)引入校驗(yàn) starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>package com.qcby.springboot.domain;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person3 {
@javax.validation.constraints.Email
@Value("${person.Email}")
private String Email;
@NotNull
@Value("${person.lastName}")
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> list;
private Dog dog;
public Person3() {
}
public Person3(@javax.validation.constraints.Email String email, Integer age, Boolean boss, Date birth, Map<String, Object> maps, List<Object> list, Dog dog) {
Email = email;
this.age = age;
this.boss = boss;
this.birth = birth;
this.maps = maps;
this.list = list;
this.dog = dog;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getBoss() {
return boss;
}
public void setBoss(Boolean boss) {
this.boss = boss;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getList() {
return list;
}
public void setList(List<Object> list) {
this.list = list;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "Person3{" +
"Email='" + Email + '\'' +
", lastName='" + lastName + '\'' +
", age=" + age +
", boss=" + boss +
", birth=" + birth +
", maps=" + maps +
", list=" + list +
", dog=" + dog +
'}';
}
}package com.qcby.springboot.domain;
public class Dog {
private String name;
private Integer age;
public Dog() {
}
public Dog(String name, Integer age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Email 被 @Email 注解修飾,配置文件輸入的屬性 Email 郵箱不合法時(shí)會(huì)報(bào)錯(cuò)

lastName 被 @NotNull 注解修飾,配置文件輸入的屬性 lastName 為空時(shí)會(huì)報(bào)錯(cuò)

@javax.validation.constraints.Email
@Value(“zhangsan”)
連個(gè)注解同時(shí)使用的時(shí)候郵箱校驗(yàn)就不生效了

@Value獲取值和@ConfigurationProperties獲取值比較

驗(yàn)證松散綁定的區(qū)別
package com.qcby.springboot.domain;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Component
@ConfigurationProperties(prefix = "person")
//@Validated
public class Person4 {
private String Email;
//@Value("${person.last_name}")
private String last_name;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> list;
private Dog dog;
public Person4() {
}
public Person4(String email, Integer age, Boolean boss, Date birth, Map<String, Object> maps, List<Object> list, Dog dog) {
Email = email;
this.age = age;
this.boss = boss;
this.birth = birth;
this.maps = maps;
this.list = list;
this.dog = dog;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getBoss() {
return boss;
}
public void setBoss(Boolean boss) {
this.boss = boss;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getList() {
return list;
}
public void setList(List<Object> list) {
this.list = list;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "Person4{" +
"Email='" + Email + '\'' +
", last_name='" + last_name + '\'' +
", age=" + age +
", boss=" + boss +
", birth=" + birth +
", maps=" + maps +
", list=" + list +
", dog=" + dog +
'}';
}
}
@ConfigurationProperties 支持配置名與 Java 屬性名的格式自動(dòng)轉(zhuǎn)換

@Value 不支持配置名與 Java 屬性名的格式自動(dòng)轉(zhuǎn)換,必須嚴(yán)格匹配配置名(大小寫、分隔符完全一致)

加載指定的配置文件
@PropertySource 加載自定義配置文件
加載非默認(rèn)的配置文件 person.properties,補(bǔ)充 Spring 環(huán)境中的配置屬性,加載后的配置屬性可通過 @Value 或 @ConfigurationProperties 直接獲取。
@ImportResource 導(dǎo)入傳統(tǒng)的 Spring XML 配置文件 spring-bean.xml,讓 XML 中定義的 Bean 被 Spring 容器管理。Spring Boot 默認(rèn)不掃描 XML 配置文件,這個(gè)注解是為了兼容舊項(xiàng)目。
示例代碼:

package com.qcby.springboot;
import com.qcby.springboot.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:config.properties")
@ImportResource(locations = "classpath:spring-bean.xml")
public class MyAppConfig {
}package com.qcby.springboot.service;
import org.springframework.beans.factory.annotation.Value;
public class HelloService {
@Value("${hello.service.version}")
private String version;
public void sayHello() {
System.out.println("HelloService 業(yè)務(wù)版本:" + version);
}
}<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloService" class="com.qcby.springboot.service.HelloService"></bean>
</beans>package com.qcby.springboot;
import com.qcby.springboot.service.HelloService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootTest {
@Autowired
private HelloService helloService;
@Test
public void testPropertyInjection() {
helloService.sayHello();
}
}
整體核心邏輯:通過 @SpringBootTest 啟動(dòng) Spring 容器,容器自動(dòng)掃描并加載 @Configuration 配置類,先通過 @PropertySource 讀取自定義配置文件,再通過 @Bean 注冊(cè) HelloService 實(shí)例到容器,最后 @Autowired 從容器中取出該實(shí)例,調(diào)用方法驗(yàn)證配置注入是否成功。
@Bean 時(shí) JavaConfig 方式注冊(cè) Bean
在 @Configuration 標(biāo)注的配置類中,通過方法手動(dòng)注冊(cè) Bean 到 Spring 容器,Spring 會(huì)管理 Bean 的生命周期(創(chuàng)建、依賴注入、銷毀)。
package com.qcby.springboot;
import com.qcby.springboot.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:config.properties")
public class MyAppConfig {
@Bean
public HelloService helloService01() {
System.out.println("配置類@Bean注冊(cè)組件:helloService01");
return new HelloService();
}
}
整體核心邏輯:測(cè)試類通過 @SpringBootTest 啟動(dòng) Spring 容器,容器加載 @Configuration 配置類后,通過 @PropertySource 讀取自定義配置文件、@ImportResource 導(dǎo)入 XML 配置并注冊(cè) HelloService 類型 Bean,Spring 自動(dòng)為該 Bean 注入配置文件中的版本屬性,最終測(cè)試類通過 @Autowired 注入 Bean 并調(diào)用方法驗(yàn)證屬性注入效果。
到此這篇關(guān)于Springboot 配置屬性綁定詳解的文章就介紹到這了,更多相關(guān)Springboot 配置屬性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot整合日志功能(slf4j+logback)詳解(最新推薦)
Spring使用commons-logging作為內(nèi)部日志,但底層日志實(shí)現(xiàn)是開放的,可對(duì)接其他日志框架,這篇文章主要介紹了SpringBoot整合日志功能(slf4j+logback)詳解,需要的朋友可以參考下2024-08-08
Java ServletContext對(duì)象原理及功能解析
這篇文章主要介紹了Java ServletContext對(duì)象原理及功能解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06
關(guān)于MyBatis plus條件構(gòu)造器的逐條詳解
什么是條件構(gòu)造器呢?簡(jiǎn)單來說,條件構(gòu)造器就是用來生成我們查數(shù)據(jù)庫的sql。它可以簡(jiǎn)化sql代碼的編寫,靈活、方便且易于維護(hù)2021-09-09
JAVA中的deflate壓縮實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄狫AVA中的deflate壓縮實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09
Redisson分布式閉鎖RCountDownLatch的使用詳細(xì)講解
分布式鎖和我們java基礎(chǔ)中學(xué)習(xí)到的synchronized略有不同,synchronized中我們的鎖是個(gè)對(duì)象,當(dāng)前系統(tǒng)部署在不同的服務(wù)實(shí)例上,單純使用synchronized或者lock已經(jīng)無法滿足對(duì)庫存一致性的判斷。本次主要講解基于rediss實(shí)現(xiàn)的分布式鎖2023-02-02
Java?Web中常見的安全漏洞的防御策略和代碼實(shí)現(xiàn)
隨著互聯(lián)網(wǎng)的快速發(fā)展,Web應(yīng)用安全問題日益突出,作為企業(yè)級(jí)應(yīng)用開發(fā)的主流語言之一,Java在Web開發(fā)領(lǐng)域占據(jù)重要地位,本文將詳細(xì)介紹Java?Web應(yīng)用中常見的安全漏洞,并提供實(shí)用的防御策略和代碼實(shí)現(xiàn),需要的朋友可以參考下2025-06-06

