Spring Boot Starter 理解
可以認(rèn)為starter是一種服務(wù)(和JS的插件類似)——使得使用某個(gè)功能的開發(fā)者不需要關(guān)注各種依賴庫(kù)的處理误债,不需要具體的配置信息,由Spring Boot自動(dòng)通過classpath路徑下的類發(fā)現(xiàn)需要的Bean糟袁,并織入bean
starter 開始
- 首先創(chuàng)建一個(gè)maven項(xiàng)目
- 項(xiàng)目命名方式為[name]-spring-boot-starter (官方命名方式 spring-boot-starter-[name])
- 在pom.xml中添加starter所需要的依賴
- 創(chuàng)建starter相關(guān)類(至少有一個(gè)自動(dòng)配置類)
- 在resource文件夾下創(chuàng)建META-INF文件夾 (srping.factories)
jwt-spring-boot-starter 定義
- 相關(guān)配置的用實(shí)體類表示(屬性配置類)
- 開放的服務(wù)類
- JWT工具類
- 自動(dòng)配置類
1:創(chuàng)建項(xiàng)目
2:創(chuàng)建所需要的文件
3: 代碼簡(jiǎn)介
JwtServiceProperties 屬性配置類
// 需要在配置文件配置所需要的屬性
// 本例的配置文件
jwt.base64Security = 0914234854!wa
jwt.issuer = alienlabManage
package com.alienlab.starter;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Created by Msater Zg on 2017/7/13.
*/
// 讀取配置文件,采用的是實(shí)體類的方式
當(dāng)然你也可以 ${} 的方式
@ConfigurationProperties(prefix = "jwt")
public class JwtServiceProperties {
/**
* 密鑰
* 系統(tǒng)的簡(jiǎn)稱
*/
// 名稱要與配置文件相同
private String base64Security;
private String issuer;
public String getBase64Security() {
return base64Security;
}
public void setBase64Security(String base64Security) {
this.base64Security = base64Security;
}
public String getIssuer() {
return issuer;
}
public void setIssuer(String issuer) {
this.issuer = issuer;
}
}
JwtService 啟動(dòng)器服務(wù)類
// 服務(wù)類 開放出來的接口辩撑,當(dāng)然沒有接口開放也可以不需要這個(gè)類
package com.alienlab.starter;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Map;
/**
* Created by Msater Zg on 2017/7/13.
*/
public class JwtService {
// 需要在自動(dòng)配置類中注入此bean
@Autowired
JwtUtils jwtUtils;
private String base64Security;
private String issuer;
public JwtService(String base64Security, String issuer) {
this.base64Security = base64Security;
this.issuer = issuer;
}
// 創(chuàng)建 map中放個(gè)人信息仿耽,可以被他們獲取到,第二個(gè)是發(fā)送給誰君躺,第三參數(shù)是過期時(shí)間
public String createPersonToken(Map map, String audience, long TTLMillis) {
String personToken = jwtUtils.createJWT(map, audience, this.issuer, TTLMillis, this.base64Security);
return personToken;
}
// token
public Claims parsePersonJWT(String personToken) {
Claims claims = jwtUtils.parseJWT(personToken, this.base64Security);
return claims;
}
}
JwtUtils 工具類(啟動(dòng)器的邏輯類)
// jwt工具類 這個(gè)主要是jwt業(yè)務(wù)邏輯的類开缎,不同的starter業(yè)務(wù)邏輯肯定是不同的
package com.alienlab.starter;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;
import java.util.Map;
/**
* Created by Msater Zg on 2017/3/13. jwt實(shí)現(xiàn)方式
*/
public class JwtUtils {
// 加密方法
public Claims parseJWT(String jsonWebToken, String base64Security) {
try {
Claims claims = Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))
.parseClaimsJws(jsonWebToken).getBody();
return claims;
} catch (Exception ex) {
return null;
}
}
// 解密方法
public String createJWT(Map map,
String audience, String issuer, long TTLMillis, String base64Security) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
//生成簽名密鑰 就是一個(gè)base64加密后的字符串奕删?
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security);
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
//添加構(gòu)成JWT的參數(shù)
JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
.setIssuedAt(now) //創(chuàng)建時(shí)間
.setSubject(map.toString()) //主題完残,也差不多是個(gè)人的一些信息
.setIssuer(issuer) //發(fā)送誰
.setAudience(audience) //個(gè)人簽名
.signWith(signatureAlgorithm, signingKey); //估計(jì)是第三段密鑰
//添加Token過期時(shí)間
if (TTLMillis >= 0) {
// 過期時(shí)間
long expMillis = nowMillis + TTLMillis;
// 現(xiàn)在是什么時(shí)間
Date exp = new Date(expMillis);
// 系統(tǒng)時(shí)間之前的token都是不可以被承認(rèn)的
builder.setExpiration(exp).setNotBefore(now);
}
//生成JWT
return builder.compact();
}
}
JwtAutoConfiguration 自動(dòng)裝配類(必須的文件類)
// 自動(dòng)裝配類(最重要的類,沒有此類熟掂,spring boot不會(huì)自動(dòng)掃描jar)
package com.alienlab.starter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created by Msater Zg on 2017/7/13.
*/
@Configuration
@ConditionalOnClass(JwtService.class)
@EnableConfigurationProperties(JwtServiceProperties.class)
public class JwtAutoConfiguration {
@Autowired
private JwtServiceProperties jwtServiceProperties;
// 創(chuàng)建相關(guān)bean
@Bean
JwtService jwtService() {
return new JwtService(jwtServiceProperties.getBase64Security(), jwtServiceProperties.getIssuer());
}
@Bean
JwtUtils jwtUtils() {
return new JwtUtils();
}
}
//創(chuàng)建bean 的一些判斷條件注解
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "jwt",value ="enabled",havingValue = "true")
JwtUtils jwtUtils() {
return new JwtUtils();
}
@ConditionalOnClass打掘,當(dāng)classpath下發(fā)現(xiàn)該類的情況下進(jìn)行自動(dòng)配置鹏秋。
@ConditionalOnMissingBean,當(dāng)Spring Context中不存在該Bean時(shí)横朋。
@ConditionalOnProperty(prefix = "jwt",value = "enabled",havingValue = "true")百拓,jwt.enabled=true時(shí)
spring.factories文件(必需的晰甚,這樣spring boot啟動(dòng)時(shí)决帖,才會(huì)發(fā)現(xiàn)并且加載這個(gè)jar)
// 指向剛才自動(dòng)裝配類路徑
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.alienlab.starter.JwtAutoConfiguration
4:pom.xml文件詳情(所依賴的jar地回,如果不同啟動(dòng)器所依賴的jar有相同,則盡量寫在一起刻像。防止兩個(gè)同時(shí)引用產(chǎn)生jar包沖突的問題O杆)
<?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>
<groupId>alienlab</groupId>
<artifactId>jwt-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<jwtio.version>0.6.0</jwtio.version>
<auth0.version>3.1.0</auth0.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!--jwt-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${auth0.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwtio.version}</version>
</dependency>
</dependencies>
</project>
4:項(xiàng)目打包
- 到項(xiàng)目的pom.xml文件所在的同一層級(jí)目錄溜徙,打開命令窗口輸入命令 mvn install ,打包好的starter在項(xiàng)目的target目錄里面雁歌。
5: 開始使用(創(chuàng)建好spring boot項(xiàng)目)
// 添加依賴(選擇自己的啟動(dòng)器路徑)
<dependency>
<groupId>alienlab</groupId>
<artifactId>jwt-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
//在application.properties配置所需要的屬性
#jwt setting
jwt.base64Security=091418wa!
jwt.issuer=yuqingmanage
//自動(dòng)注入知残,并開始使用服務(wù)的方法
@Autowired
JwtService jwtService;
@RequestMapping(value = "/getAllSysUser", method = RequestMethod.GET)
@ApiOperation(value = "getAllSysUser", notes = "獲取到所有的用戶")
@ApiImplicitParams({
})
public String getAllSysUser() {
String reuslt = iUserService.getAllSysUser().toString();
Map map = new HashMap();
map.put("user", "趙剛");
System.out.println(jwtService.createPersonToken(map, "1402753117", 200));
return reuslt;
}
結(jié)語:
- 后續(xù)的項(xiàng)目直接引入依賴比庄,不需要重新復(fù)制佳窑。代碼維護(hù)非常方便,將自己的starter上傳到maven倉(cāng)庫(kù)其他人就可以下載使用神凑。當(dāng)然starter并不是萬能的,適用于一些和系統(tǒng)的業(yè)務(wù)沒有直接關(guān)聯(lián)的邏輯鹃唯。比如swagger瓣喊,跨域的配置,攔截器洪橘,jwt安全加密,緩存等等渣玲!