1. 程式人生 > >spring-boot-starter的理解和開發

spring-boot-starter的理解和開發

Spring Boot Starter 理解

可以認為starter是一種服務(和JS的外掛類似)——使得使用某個功能的開發者不需要關注各種依賴庫的處理,不需要具體的配置資訊,由Spring Boot自動通過classpath路徑下的類發現需要的Bean,並織入bean

starter 開始

  • 首先建立一個maven專案
  • 專案命名方式為[name]-spring-boot-starter (官方命名方式 spring-boot-starter-[name])
  • 在pom.xml中新增starter所需要的依賴
  • 建立starter相關類(至少有一個自動配置類)
  • 在resource資料夾下建立META-INF資料夾 (srping.factories)

jwt-spring-boot-starter 定義

  • 相關配置的用實體類表示(屬性配置類)
  • 開放的服務類
  • JWT工具類
  • 自動配置類
    1. 建立專案
      image
      image
      2.建立所需要的檔案
      image
      image
      3.程式碼簡介
// 屬性配置類
// 需要在配置檔案配置所需要的屬性
// 本例的配置檔案
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.
 */
// 讀取配置檔案,採用的是實體類的方式 當然你也可以 ${} 的方式 @ConfigurationProperties(prefix = "jwt") public class JwtServiceProperties { /** * 金鑰 * 系統的簡稱 */ // 名稱要與配置檔案相同 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; } }
// 服務類 開放出來的介面,當然沒有介面開放也可以不需要這個類
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 {
    // 需要在自動配置類中注入此bean
    @Autowired   
    JwtUtils jwtUtils;

    private String base64Security;

    private String issuer;

    public JwtService(String base64Security, String issuer) {
        this.base64Security = base64Security;
        this.issuer = issuer;
    }

    // 建立 map中放個人資訊,可以被他們獲取到,第二個是傳送給誰,第三引數是過期時間
    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;
    }
}
// jwt工具類 這個主要是jwt業務邏輯的類,不同的starter業務邏輯肯定是不同的
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實現方式
 */
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);
        //生成簽名金鑰 就是一個base64加密後的字串?
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security);
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
        //新增構成JWT的引數
        JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
                .setIssuedAt(now)  //建立時間
                .setSubject(map.toString()) //主題,也差不多是個人的一些資訊
                .setIssuer(issuer) //傳送誰
                .setAudience(audience) //個人簽名
                .signWith(signatureAlgorithm, signingKey);  //估計是第三段金鑰
        //新增Token過期時間
        if (TTLMillis >= 0) {
            // 過期時間
            long expMillis = nowMillis + TTLMillis;
            // 現在是什麼時間
            Date exp = new Date(expMillis);
            // 系統時間之前的token都是不可以被承認的
            builder.setExpiration(exp).setNotBefore(now);
        }
        //生成JWT
        return builder.compact();
    }
}
// 自動裝配類(最重要的類,沒有此類,spring boot不會自動掃描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;

    // 建立相關bean
    @Bean
    JwtService jwtService() {
        return new JwtService(jwtServiceProperties.getBase64Security(), jwtServiceProperties.getIssuer());
    }

    @Bean
    JwtUtils jwtUtils() {
        return new JwtUtils();
    }
}

//建立bean 的一些判斷條件註解
@Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "jwt",value ="enabled",havingValue = "true")
    JwtUtils jwtUtils() {
        return new JwtUtils();
    }

@ConditionalOnClass,當classpath下發現該類的情況下進行自動配置。
@ConditionalOnMissingBean,當Spring Context中不存在該Bean時。
@ConditionalOnProperty(prefix = "jwt",value = "enabled",havingValue = "true"),jwt.enabled=true
  1. pom.xml檔案詳情
<?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>
  1. 打包
    到專案的pom.xml檔案所在的同一層級目錄,開啟命令視窗輸入命令 mvn install ,封裝好的starter在專案的target目錄裡面,而其他專案可以進行依賴。

  2. 開始使用(建立好spring boot專案)

// 新增依賴
<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
//自動注入,並開始使用開放的方法
@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;
    }

結語:

後續的專案直接引入依賴,不需要重新複製。程式碼維護非常方便,將自己的starter上傳到maven倉庫其他人就可以下載使用。當然starter並不是萬能的,適用於一些和系統的業務沒有直接關聯的功能。比如swagger,跨域的配置,攔截器,jwt安全加密等等。。。