詳解SpringBoot如何創(chuàng)建自定義Starter
Spring Boot的自動(dòng)配置機(jī)制為開(kāi)發(fā)人員提供了一種輕松集成和配置各種功能的便捷方式。然而,隨著項(xiàng)目的復(fù)雜性增加,更好地組織和分享通用功能變得至關(guān)重要。自定義Starter成為了理想的解決方案,旨在簡(jiǎn)化項(xiàng)目的依賴管理和自動(dòng)配置,使開(kāi)發(fā)者能夠迅速而靈活地集成特定的功能模塊。本文將深入探討在Spring Boot中如何創(chuàng)建自定義Starter,為構(gòu)建模塊化且易維護(hù)的應(yīng)用提供有力的支持。
接下來(lái)我們來(lái)實(shí)現(xiàn)一個(gè)自定義的starter。
實(shí)現(xiàn)自定義Starter
首先,我們需要明確自定義starter的目標(biāo)功能,如提供特定領(lǐng)域的服務(wù)或集成第三方庫(kù)。比如我們創(chuàng)建一個(gè)coderacademy-spring-boot-starter的starter,用于提供某些服務(wù)。例如我們的服務(wù)就實(shí)現(xiàn)一個(gè)打印功能:
public class CoderAcademyService {
public String sayHello(){
return "Hello 碼農(nóng)Academy!";
}
}
本文旨在介紹如何自定義starter,故而starter的功能不是本文的主要內(nèi)容,后續(xù)我們會(huì)提供一個(gè)基于注解實(shí)現(xiàn)ES操作/搜索的服務(wù)的starter。感興趣的,點(diǎn)個(gè)關(guān)注哦~
創(chuàng)建項(xiàng)目結(jié)構(gòu)
我們創(chuàng)建一個(gè)名為springboot-coderacademy-starter的項(xiàng)目,在pom.xml中設(shè)置groupId,artifactId還有version。其中groupId與artifactId應(yīng)反映starter的名稱(chēng)。
<groupId>com.springboot.coderacaemy</groupId> <artifactId>coderacermy-spring-boot-starter</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>jar</packaging>
然后我們?cè)谝胍恍┪覀冃枰怯玫降囊蕾嚕热缥覀円褂?code>@Configuration,@EnableConfigurationProperties等注解:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<groupId>com.springboot.coderacaemy</groupId>
<artifactId>coderacermy-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-starter</name>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
其中spring-boot-configuration-processor這個(gè)依賴主要用于IDEA支持和編譯時(shí)生成元數(shù)據(jù)。
本文使用的springboot版本為2.7.0
創(chuàng)建自動(dòng)配置類(lèi)
自動(dòng)配置類(lèi)負(fù)責(zé)定義Spring Boot應(yīng)用程序中的通用配置和功能。這個(gè)類(lèi)通常使用@Configuration注解進(jìn)行標(biāo)記,在這個(gè)類(lèi)中注入服務(wù)、組件或其他你需要自動(dòng)配置的對(duì)象。
import com.springboot.starter.coderacademy.service.CoderAcademyService;
import org.springframework.context.annotation.Configuration;
/**
* @version 1.0
* @description: <p></p >
* @author: 碼農(nóng)Academy
* @create: 2024/1/31 14:38
*/
@Configuration
public class CoderAcademyAutoConfig {
@Bean
public CoderAcademyService coderAcademyService(){
return new CoderAcademyService();
}
}
指定自動(dòng)裝配類(lèi)
在resources文件夾下創(chuàng)建一個(gè)META-INF/spring.factories文件,在這個(gè)文件中指定自動(dòng)裝配類(lèi)CoderAcademyAutoConfig:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.springboot.starter.coderacademy.config.CoderAcademyAutoConfig
在META-INF/spring.factories文件中,org.springframework.boot.autoconfigure.EnableAutoConfiguration是一個(gè)特殊的鍵,它的值是一個(gè)包含要應(yīng)用的自動(dòng)配置類(lèi)的全限定名列表。當(dāng)應(yīng)用啟動(dòng)時(shí),SpringBoot的引導(dǎo)過(guò)程會(huì)掃描所有已引入jar包中的spring.factories文件,并根據(jù)EnableAutoConfiguration鍵下的類(lèi)來(lái)加載和執(zhí)行相應(yīng)的自動(dòng)配置邏輯。
當(dāng)然如果不使用這個(gè)配置,在調(diào)用方使用@ComponentScan也可以掃描到CoderAcademyAutoConfig。但是這跟Starter的設(shè)計(jì)理念相悖。在Starter的設(shè)計(jì)中,一般不推薦調(diào)用方手動(dòng)進(jìn)行額外的掃描。這是因?yàn)檎{(diào)用方引入了Starter,就應(yīng)該依賴于 Starter提供的自動(dòng)配置。手動(dòng)掃描可能會(huì)導(dǎo)致不必要的麻煩,例如循環(huán)依賴、配置類(lèi)的重復(fù)加載等問(wèn)題。
假如我們現(xiàn)在沒(méi)有其他的配置了,比如說(shuō)一下額外的屬性配置,那我們就可以打包與發(fā)布了。
打包與發(fā)布
此時(shí)我們就可以將自定義Starter打包,并發(fā)布到Maven倉(cāng)庫(kù)或其他倉(cāng)庫(kù)管理工具。
本地開(kāi)發(fā)時(shí),可以直接install。不必發(fā)不到私服。
測(cè)試
我們新建一個(gè)調(diào)用方的項(xiàng)目,在其中引入coderacademy-spring-boot-starter。
<dependency>
<groupId>com.springboot.coderacaemy</groupId>
<artifactId>coderacermy-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
我們編寫(xiě)測(cè)試類(lèi):
@SpringBootTest
class SpringbootCodeApplicationTests {
private CoderAcademyService coderAcademyService;
@Test
public void testCoderAcademy(){
String str = coderAcademyService.sayHello();
System.out.println(str);
}
@Autowired
public void setCoderAcademyService(CoderAcademyService coderAcademyService) {
this.coderAcademyService = coderAcademyService;
}
}
執(zhí)行結(jié)果如下:

這樣一個(gè)很簡(jiǎn)單的Starter就完成了。
當(dāng)然在實(shí)際開(kāi)發(fā)中,我們還需要一些自定義配置項(xiàng)需要注入到Starter中,才可以提供完整的服務(wù)。
配置屬性
我們新建一個(gè)CoderAcademyProperties類(lèi)用于接收,調(diào)用方在自己項(xiàng)目中的application.yaml或者其他的配置中心配置的信息。
@ConfigurationProperties(prefix = "coderacademy")
public class CoderAcademyProperties {
private String name = "碼農(nóng)Academy";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@ConfigurationProperties 是 SpringBoot中用于綁定外部配置到Bean的屬性上,prefix屬性指定了配置前綴。這樣我們就可以在調(diào)用方的application.yml中配置以coderacademy為前綴的信息。這里我們也給了默認(rèn)值。
然后我們將這個(gè)配置注入到CoderAcademyService中去。
public class CoderAcademyService {
private final CoderAcademyProperties coderAcademyProperties;
public String sayHello(){
return "Hello "+ coderAcademyConfig.getName();
}
public CoderAcademyService(CoderAcademyProperties coderAcademyProperties) {
this.coderAcademyProperties = coderAcademyProperties;
}
}
我們改動(dòng)一下CoderAcademyService的AutoConfig。
@EnableConfigurationProperties({CoderAcademyProperties.class})
@Configuration
public class CoderAcademyAutoConfig {
@Bean
public CoderAcademyService coderAcademyService(CoderAcademyProperties coderAcademyProperties){
return new CoderAcademyService(coderAcademyProperties);
}
}
我重新Deploy之后,然后在調(diào)用方配置一下CoderAcademyProperties中對(duì)應(yīng)的屬性:
coderacademy.name = CoderAcademy
再次跑一下單測(cè):

在實(shí)際開(kāi)發(fā)場(chǎng)景中,我們有時(shí)會(huì)遇到這樣的需求:調(diào)用方希望根據(jù)自身項(xiàng)目的需求靈活定義配置項(xiàng),無(wú)需嚴(yán)格遵循CoderAcademyProperties中預(yù)設(shè)的模式(例如coderacademy.name)。例如,他們可能傾向于通過(guò)自定義屬性customer.starter.name來(lái)代替,并將這個(gè)屬性值映射到其項(xiàng)目的配置文件中。隨后,在調(diào)用方自己的@Configuration類(lèi)里,基于這些個(gè)性化配置來(lái)創(chuàng)建一個(gè)CoderAcademyService實(shí)例。
然而,問(wèn)題在于,Starter模塊內(nèi)部預(yù)先提供了一個(gè)默認(rèn)的CoderAcademyService Bean定義。當(dāng)調(diào)用方在其應(yīng)用上下文中也聲明了同類(lèi)型的Bean時(shí),這將觸發(fā)Spring容器中的Bean沖突和初始化異常。為了解決這個(gè)問(wèn)題,我們?cè)谠O(shè)計(jì)Starter時(shí)需要考慮到這一點(diǎn),我們?cè)谧詣?dòng)配置類(lèi)中利用@ConditionalOnMissingBean注解來(lái)確保僅在容器中尚無(wú)CoderAcademyService Bean時(shí)才進(jìn)行創(chuàng)建操作。這樣就避免了重復(fù)注冊(cè)同一類(lèi)型Bean導(dǎo)致的問(wèn)題。
@EnableConfigurationProperties({CoderAcademyProperties.class})
@Configuration
@ConditionalOnMissingBean(CoderAcademyService.class)
public class CoderAcademyAutoConfig {
@Bean
public CoderAcademyService coderAcademyService(CoderAcademyProperties coderAcademyProperties){
return new CoderAcademyService(coderAcademyProperties);
}
}
然后我們?cè)谡{(diào)用方設(shè)計(jì)一個(gè)配置類(lèi),用于創(chuàng)建一個(gè)CoderAcademyService。
@Configuration
public class CustomerConfig {
@Value("${customer.coderacademy.name}")
private String customerName;
@Bean
public CoderAcademyService coderAcademyService(){
CoderAcademyProperties properties = new CoderAcademyProperties();
properties.setName(customerName);
return new CoderAcademyService(properties);
}
}
在調(diào)用方的application.properties加上customer.coderacademy.name配置。
customer.coderacademy.name = customer,coderacademy
我們?cè)俅卧谡{(diào)用方執(zhí)行:

屬性配置提示
我們?cè)谑褂闷渌墓俜?code>Starter時(shí)在application.properties或者application.yml配置相關(guān)屬性時(shí),IDEA會(huì)自動(dòng)給出屬性的Key的提示,以及給出默認(rèn)值。那么在自定義Starter中該如何實(shí)現(xiàn)這功能呢?其實(shí)這就需要用到了我們引入的spring-boot-configuration-processor依賴。
spring-boot-configuration-processor 是 Spring Boot 提供的一個(gè)注解處理器,用于處理 @ConfigurationProperties 注解,生成配置屬性的元數(shù)據(jù),以提供更好的 IDE 支持和配置文件提示。注解處理器會(huì)掃描項(xiàng)目中標(biāo)注了@ConfigurationProperties 注解的類(lèi),然后生成包含有關(guān)這些配置屬性的詳細(xì)信息的 spring-configuration-metadata.json文件。該文件位于META-INF下。這個(gè)元數(shù)據(jù)文件包含了配置屬性的描述、類(lèi)型、默認(rèn)值等信息,以提供更好的代碼提示和文檔生成功能。元數(shù)據(jù)文件被 IDE(如 IDEA、Eclipse)使用,用于提供更強(qiáng)大的代碼提示和補(bǔ)全功能。開(kāi)發(fā)者在編輯配置文件時(shí)可以看到配置屬性的描述、類(lèi)型等信息,更容易正確地配置應(yīng)用程序。
當(dāng)然添加依賴之后,我們還需要添加Maven的插件(如果使用的是Maven)。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.7.0</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
然后我們執(zhí)行mvn clean -U install -DskipTests命令后,就可以在target下的META-INF就可以看見(jiàn)這個(gè)元數(shù)據(jù)文件。

我們?cè)谥匦麓虬?,在調(diào)用方的application.properties中配置屬性信息時(shí),可以看到效果:

配置文件默認(rèn)值
在上述示例中,我們?cè)?code>CoderAcademyProperties代碼中顯示的給name賦值了一個(gè)默認(rèn)值。這種方式實(shí)現(xiàn)也可以,但是不夠優(yōu)雅,我們換一種優(yōu)雅的方式去實(shí)現(xiàn)配置的默認(rèn)值設(shè)置。我們?cè)撚迷O(shè)置一個(gè)存儲(chǔ)默認(rèn)值的配置文件coderacademy-default.properties,從這個(gè)文件綁定配置的默認(rèn)值。
我們?cè)?code>resources/META-INF下創(chuàng)建一個(gè)coderacademy-default.properties。
coderacademy.name = Default CoderAcademy
然后在CoderAcademyAutoConfig中使用@PropertySource將這這個(gè)默認(rèn)文件中的配置加載綁定到Bean中即CoderAcademyProperties中。
@AutoConfigureAfter({CoderAcademyPropertiesAutoConfig.class})
@EnableConfigurationProperties({CoderAcademyProperties.class})
@Configuration
@ConditionalOnMissingBean(CoderAcademyService.class)
@PropertySource(name = "CoderAcademy Default Properties", value = "classpath:/META-INF/coderacademy-default.properties")
public class CoderAcademyAutoConfig {
@Bean
public CoderAcademyService coderAcademyService(CoderAcademyProperties coderAcademyProperties){
return new CoderAcademyService(coderAcademyProperties);
}
}
在SpringBoot應(yīng)用中,通過(guò)application.properties或application.yml設(shè)置的屬性具有較高的優(yōu)先級(jí)。如果使用@PropertySource加載的屬性與前者有沖突,則會(huì)被后者覆蓋。
我們?cè)谡{(diào)用方直接使用Starter中創(chuàng)建的CoderAcademyService,看一下效果:

即此時(shí)使用的是coderacademy-default.properties中配置的默認(rèn)值。
我們?cè)谡{(diào)用方配置coderacademy.name的值
coderacademy.name = This is CoderAcademy
再次運(yùn)行一下數(shù)據(jù)

至此一個(gè)自定義的Starter就完成了。
示例
項(xiàng)目架構(gòu):

依賴:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<groupId>com.springboot.coderacaemy</groupId>
<artifactId>coderacermy-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-starter</name>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.7.0</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
- 服務(wù)配置信息
@ConfigurationProperties(prefix = "coderacademy")
public class CoderAcademyProperties {
private String url;
private Integer port;
private String userName;
private String password;
// 省略get set方法
}
CoderAcademyProperties主要作用是為了綁定application.properites中配置信息。其默認(rèn)的配置文件coderacademy-default.properties:
coderacademy.url=https://www.coderacademy.online/ coderacademy.port=8080 coderacademy.user-name=CoderAcademy coderacademy.password=123456
- 服務(wù)配置類(lèi)
新建一個(gè)CoderAcademyConfig用于創(chuàng)建CoderAcademyService服務(wù)。CoderAcademyProperties只作為服務(wù)的配置信息,主要參與綁定外部配置文件中的配置信息。
public class CoderAcademyConfig {
private String url;
private Integer port;
private String userName;
private String password;
// 省略 get set
}
在創(chuàng)建一個(gè)將CoderAcademyProperties的參數(shù)綁定到配置類(lèi)CoderAcademyConfig的一個(gè)自動(dòng)裝配類(lèi)CoderAcademyPropertiesAutoConfig。
@Configuration
@EnableConfigurationProperties({CoderAcademyProperties.class})
@PropertySource(name = "CoderAcademy Default Properties", value = "classpath:/META-INF/coderacademy-default.properties")
public class CoderAcademyPropertiesAutoConfig {
@Bean
public CoderAcademyConfig coderAcademyConfig(CoderAcademyProperties coderAcademyProperties){
CoderAcademyConfig coderAcademyConfig = new CoderAcademyConfig();
coderAcademyConfig.setPort(coderAcademyProperties.getPort());
coderAcademyConfig.setUrl(coderAcademyProperties.getUrl());
coderAcademyConfig.setPassword(coderAcademyProperties.getPassword());
coderAcademyConfig.setUserName(coderAcademyProperties.getUserName());
return coderAcademyConfig;
}
}
- 服務(wù)類(lèi)
服務(wù)類(lèi)中就是用CoderAcademyConfig創(chuàng)建。
public class CoderAcademyService {
private final CoderAcademyConfig coderAcademyConfig;
public String connectDB(){
return "Connect to " + coderAcademyConfig.getUrl() + ":" + coderAcademyConfig.getPort() + " successfully!";
}
public CoderAcademyService(CoderAcademyConfig coderAcademyConfig) {
this.coderAcademyConfig = coderAcademyConfig;
}
}
創(chuàng)建一個(gè)服務(wù)自動(dòng)裝配類(lèi)。
@Configuration
@AutoConfigureAfter({CoderAcademyPropertiesAutoConfig.class})
@ConditionalOnBean({CoderAcademyConfig.class})
public class CoderAcademyAutoConfig {
@Bean
@ConditionalOnMissingBean
public CoderAcademyService coderAcademyService(CoderAcademyConfig coderAcademyConfig){
return new CoderAcademyService(coderAcademyConfig);
}
}
然后在META-INF/spring.factories下中使用EnableAutoConfiguration指定自動(dòng)配置類(lèi)。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.springboot.starter.coderacademy.config.CoderAcademyAutoConfig,com.springboot.starter.coderacademy.config.CoderAcademyPropertiesAutoConfig
這時(shí)就可以把這個(gè)Starter打包推到私服,就可以使用了。
總結(jié)
自定義Spring Boot Starter的原理是在應(yīng)用啟動(dòng)時(shí),SpringBoot掃描含有spring.factories的jar包,加載其中的org.springframework.boot.autoconfigure.EnableAutoConfiguration條目。引入自定義starter后,相應(yīng)的自動(dòng)配置類(lèi)會(huì)被檢測(cè)并加載到Spring容器執(zhí)行。通過(guò)條件注解等機(jī)制,可根據(jù)用戶提供的配置信息或其他Bean的存在動(dòng)態(tài)配置和初始化Bean,實(shí)現(xiàn)功能的自動(dòng)化裝配。自定義starter體現(xiàn)了SpringBoot模塊化和可擴(kuò)展性,簡(jiǎn)化了依賴管理和配置,使開(kāi)發(fā)者能迅速構(gòu)建具有特定功能的應(yīng)用。
以上就是詳解SpringBoot如何創(chuàng)建自定義Starter的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot自定義Starter的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于HTML5+js+Java實(shí)現(xiàn)單文件文件上傳到服務(wù)器功能
應(yīng)公司要求,在HTML5頁(yè)面上實(shí)現(xiàn)上傳文件到服務(wù)器功能,對(duì)于我這樣的菜鳥(niǎo),真是把我難住了,最后還是請(qǐng)教大神搞定的,下面小編把例子分享到腳本之家平臺(tái),供大家參考2017-08-08
SpringBoot 2.0 整合sharding-jdbc中間件實(shí)現(xiàn)數(shù)據(jù)分庫(kù)分表
這篇文章主要介紹了SpringBoot 2.0 整合sharding-jdbc中間件,實(shí)現(xiàn)數(shù)據(jù)分庫(kù)分表,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-06-06
Java數(shù)據(jù)結(jié)構(gòu)之鏈表的概念及結(jié)構(gòu)
這篇文章主要介紹了數(shù)據(jù)鏈表的概念及結(jié)構(gòu),鏈表是一種物理存儲(chǔ)結(jié)構(gòu)上非連續(xù)、非順序的存儲(chǔ)結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過(guò)鏈表中的指針鏈接次序?qū)崿F(xiàn)的。想進(jìn)一步了解的同學(xué),可以參考閱讀本文2023-04-04
java如何防止表單重復(fù)提交的注解@RepeatSubmit
@RepeatSubmit是一個(gè)自定義注解,用于防止表單重復(fù)提交,它通過(guò)AOP和攔截器模式實(shí)現(xiàn),結(jié)合了線程安全和分布式環(huán)境的考慮,注解參數(shù)包括interval(間隔時(shí)間)和message(提示信息),使用時(shí)需要注意并發(fā)處理、用戶體驗(yàn)、性能和安全性等方面,失效原因是多方面的2024-11-11
kafka 重新分配partition和調(diào)整replica的數(shù)量實(shí)現(xiàn)
當(dāng)需要提升Kafka集群的性能和負(fù)載均衡時(shí),可通過(guò)kafka-reassign-partitions.sh命令手動(dòng)重新分配Partition,增加節(jié)點(diǎn)后,可以將Topic的Partition的Leader節(jié)點(diǎn)均勻分布,以提高寫(xiě)入和消費(fèi)速度,感興趣的可以了解一下2022-03-03
springmvc+shiro+maven 實(shí)現(xiàn)登錄認(rèn)證與權(quán)限授權(quán)管理
Shiro 是一個(gè) Apache 下的一開(kāi)源項(xiàng)目項(xiàng)目,旨在簡(jiǎn)化身份驗(yàn)證和授權(quán),下面通過(guò)實(shí)例代碼給大家分享springmvc+shiro+maven 實(shí)現(xiàn)登錄認(rèn)證與權(quán)限授權(quán)管理,感興趣的朋友一起看看吧2017-09-09
使用google.kaptcha來(lái)生成圖片驗(yàn)證碼的實(shí)現(xiàn)方法
這篇文章主要介紹了使用google.kaptcha來(lái)生成圖片驗(yàn)證碼的實(shí)現(xiàn)方法,非常不錯(cuò)具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09

