spring-boot-starter的理解和開發(fā)

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)目
項(xiàng)目創(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安全加密,緩存等等渣玲!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弟晚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子淑履,更是在濱河造成了極大的恐慌藻雪,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件指煎,死亡現(xiàn)場(chǎng)離奇詭異便斥,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)像街,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門镰绎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來木西,“玉大人,你說我怎么就攤上這事八千×道Γ” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵纵寝,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我爽茴,道長(zhǎng),這世上最難降的妖魔是什么火焰? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任昌简,我火速辦了婚禮绒怨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘南蹂。我一直安慰自己,他們只是感情好晚顷,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布该默。 她就那樣靜靜地躺著策彤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锅锨。 梳的紋絲不亂的頭發(fā)上必搞,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天囊咏,我揣著相機(jī)與錄音,去河邊找鬼霜第。 笑死户辞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的底燎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼桌吃,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼苞轿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起搬卒,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤契邀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后椭迎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體田盈,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年简软,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了痹升。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片畦韭。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖察郁,靈堂內(nèi)的尸體忽然破棺而出转唉,到底是詐尸還是另有隱情,我是刑警寧澤赠法,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站款侵,受9級(jí)特大地震影響喳坠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜壕鹉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一晾浴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脊凰,春花似錦、人聲如沸切省。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芙盘。三九已至脸秽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間记餐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钠怯,地道東北人曙聂。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像断国,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子霞捡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容