Spring Bootシリーズ-自分でstarterを書きます.

14901 ワード

原文の住所:https://www.xncoding.com/2017/07/22/spring/sb-starter.html
前言:
Spring Bootは多くのスターで構成されています.バージョンの推移に伴い、Starter家族のメンバーも日増しに増えています.従来のMavenプロジェクトでは、しばしばいくつかの層、コンポーネントをモジュールに分割して管理し、相互に多重化に依存するため、Spring Bootプロジェクトでは、カスタムSpring Boot Starterを作成して目的を達成することができる.
スターはある機能を使用する開発者が各種の依存ライブラリの処理に関心を持つ必要がないようにするサービスであり、具体的な配置情報は必要なく、Spring Bootによって自動的にクラスパス下のクラスを通して必要なビーンを発見し、相応のビーンを織り込むサービスであると考えられています.栗を挙げて、spring-boot-starter-jdbcというstarterの存在によって、私たちはBookPubAppleで@Autowiredを使ってDataSourceのbeanを導入すればいいです.Spring Bootは自動的にDataSourceの実例を作成します.
本稿では簡単な例を通して、自分のスタンダーをどうやって作成するかを示します.
この例は自分で閉じた支払い機能のeasy-pay-spring-boot-starterです.
もちろん公式名称のspring-boot-stater-{name}そして自分で定義したスター名{name}-spring-boot-stater
一、Maven依存追加
第一歩はもちろんmavenプロジェクトを作成し、SpringBootの自動依存性を追加します.



    com.zuoyan.spring.boot
    4.0.0
    easy-pay-spring-boot-starter
    1.0-SNAPSHOT
    jar

    
        org.springframework.boot
        spring-boot-starter-parent
        1.5.9.RELEASE
         
    

    
        UTF-8
        UTF-8
        1.8
    

    

    
        
            org.springframework.boot
            spring-boot-starter
        

        
            org.springframework.boot
            spring-boot-autoconfigure
        

        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        

        
            javax.servlet
            servlet-api
            2.5
            provided
        

    

    


上のservlet-appiはプロジェクトの中で必要なHttpRequestがあるので、この依存性を使う必要があります.残りは自動配置の必要な依存性です.
なお、spring-boot-configuration-processorは、コンパイル時にspring-configuration-metadata.jsonを生成する役割を果たしており、このファイルは主にIDEに使用され、使用を促すために使用される.intellij ideaでは、このjar関連の構成属性がapplication.ymlで構成されると、ctlr+マウスの左ボタンを使って、IDEがこの属性を設定するクラスにジャンプします.
ここでは、アーティファクトの命名について、Spring公式Starterは、spring-boot-starter-{name}のようにspring-boot-starter-webと名づけられています.
Spring公式Starter以外の名前は{name}-spring-boot-starterのフォーマットに従うべきだと提案しています.
二、属性配置類の作成
つまり、私たちはSpring Bootに配置されているaplication.propertiesまたはappication.ymlファイルに配置されている属性を、プロジェクトに注入して使用してくれます.
package com.zuoyan.springboot.easypay.bean;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * 
 *         
 *    application.properties        
 * 1.partner:  ID
 * 2.key :        
 * 
 * @author   
 *
 */

@ConfigurationProperties(value = "spring.easy.pay")
public class Alipay_config {

	//  ID
	private String partner = "your ID";
	//  Key
	private String key = "your key"; 
	//        
	private String sign_type = "MD5";
	//      ,    GBK  utf-8
	private String input_charset = "utf-8";
	//    ,            ssl  ,      https;       http
	private String transport = "http";
	//  API  
	private String apiurl = "http://pay.hackwl.cn/";
	//         url
	private String notify_url = "http://www.xxxxx.com/notifyurl";
	//              
	private String return_url = "http://www.xxxxxx.com/returnurl";


	public String getPartner() {
		return partner;
	}

	public void setPartner(String partner) {
		this.partner = partner;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public String getSign_type() {
		return sign_type;
	}

	public void setSign_type(String sign_type) {
		this.sign_type = sign_type;
	}

	public String getInput_charset() {
		return input_charset;
	}

	public void setInput_charset(String input_charset) {
		this.input_charset = input_charset;
	}

	public String getTransport() {
		return transport;
	}

	public void setTransport(String transport) {
		this.transport = transport;
	}

	public String getApiurl() {
		return apiurl;
	}

	public void setApiurl(String apiurl) {
		this.apiurl = apiurl;
	}

	public String getNotify_url() {
		return notify_url;
	}

	public void setNotify_url(String notify_url) {
		this.notify_url = notify_url;
	}

	public String getReturn_url() {
		return return_url;
	}

	public void setReturn_url(String return_url) {
		this.return_url = return_url;
	}

}

皆さんは私の名前を突っ込まないでください.主に当初この機能類を書いた時、PHPによって変えました.また当時はJavaに入門したばかりで、命名規範の良い習慣がありませんでした.その後、引用が多すぎて、交換するのもおっくうでした.このように使いましょう.この中には主にいくつかの支払いに必要なパラメータがあります.例えば、取引先のkey、取引先のsecuritykey、成功ジャンプのurlを支払い、成功通知のurlを支払います.
業務類を作成する(個人的には分かりやすいですが、この属性配置類が必要なところはどこですか?)
package com.zuoyan.springboot.easypay.bean;

import com.zuoyan.springboot.easypay.function.EpayCoreFunction;
import com.zuoyan.springboot.easypay.function.EpayMD5Function;

import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.TreeMap;


/**
 *   :EpaySubmit 
 *   :          
 *   :         HTML  ,    HTTP  
 * 
 * @author   
 *
 */
public class EpaySubmit {

	private Alipay_config alipay_config;
	private String alipay_gateway_new;

	//  EpaySubmit   
	public void setAlipay_config(Alipay_config alipay_config) {
		this.alipay_config = alipay_config;
	}

	public EpaySubmit(Alipay_config alipay_config) {
		this.alipay_config = alipay_config;
		this.alipay_gateway_new = alipay_config.getApiurl()+"submit.php?";
	}
	
	public TreeMap buildRequestPara(HashMap parameter) throws Exception
	{
		//                  
		HashMap para_filter = EpayCoreFunction.paraFilter(parameter);
		//         
		TreeMap para_sort = EpayCoreFunction.argSort(para_filter);
		//      
		String mysign = this.buildRequestMysign(para_sort);
		//                    
		para_sort.put("sign", mysign);
		para_sort.put("sign_type",alipay_config.getSign_type().toUpperCase());
		return para_sort;
		
	}
	
	public String buildRequestMysign(TreeMap para_sort) throws Exception
	{
		//       ,  “  =   ”    “&”        
		String prestr = EpayCoreFunction.createLinkstring(para_sort);
		String mysign = EpayMD5Function.md5Sign(prestr.trim(),alipay_config.getKey());
		return mysign;
		
	}
	
	/**
	 *     ,   Html     
	 * @param parameter        
	 * @return
	 * @throws NoSuchAlgorithmException 
	 */
	public String buildRequestForm(HashMap parameter) throws Exception
	{
		TreeMap para = this.buildRequestPara(parameter);
		String method = "";
		String sHtml = "
"; // Parameter, for(String key : para.keySet()) { sHtml+= ""; } String button_name=" , !"; //submit name sHtml+="
"; // js sHtml+="document.forms['alipaysubmit'].submit();"; // js return sHtml; } }
支払成功通知返却類:
package com.zuoyan.springboot.easypay.function;

import com.zuoyan.springboot.easypay.bean.Alipay_config;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Pattern;

/**
 *
 *   :EpayNotify   :             :           
 * 
 * @author   
 *
 */
public class AlipayNotify {

	private Alipay_config alipay_config;
	private String http_verify_url;

	public void setAlipay_config(Alipay_config alipay_config) {
		this.alipay_config = alipay_config;
	}


	public AlipayNotify(Alipay_config alipay_config) {
		this.alipay_config = alipay_config;
		this.http_verify_url = alipay_config.getApiurl() + "api.php?";
	}


	public AlipayNotify(){}

	/**
	 *   notify_url                 
	 *
	 * @param request
	 * @param response
	 * @return     
	 * @throws Exception
	 */
	public boolean verifyNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
		return veryfy(request, response);

	}


	/**
	 *   return_url                   
	 *
	 * @param request
	 * @param response
	 * @return     
	 * @throws Exception
	 */
	public boolean verifyReturn(HttpServletRequest request, HttpServletResponse response) throws Exception {

		return veryfy(request, response);
	}

	/**
	 *  Request              map
	 *
	 * @param request
	 * @return
	 * @throws Exception
	 */
	public static HashMap getGetMap(HttpServletRequest request) throws Exception {

		Map requestMap = request.getParameterMap();
		HashMap returnMap = new HashMap();

		for (String key : requestMap.keySet()) {
			returnMap.put(key, new String(request.getParameter(key).getBytes("ISO8859-1"), "UTF-8"));
			//       
		}

		return returnMap;

	}

	/**
	 *   :            
	 *
	 * @param para_temp           
	 * @param sign             
	 * @return       
	 * @throws Exception
	 */
	public boolean getSignVeryfy(HashMap para_temp, String sign) throws Exception {
		//                     
		HashMap paraFilter = EpayCoreFunction.paraFilter(para_temp);
		//           
		TreeMap para_sort = EpayCoreFunction.argSort(paraFilter);
		//        ,   “  =   ”    "&"        
		String prestr = EpayCoreFunction.createLinkstring(para_sort);

		System.out.println("         :" + prestr);

		boolean isSgin = false;

		isSgin = EpayMD5Function.md5Verify(prestr, sign, this.alipay_config.getKey());

		return isSgin;

	}


	/**
	 *     : 
* 〈 〉 * @Param: No such property: code for class: Script1 * @Return: boolean * @Author: Administrator * @Date: 2019/10/24 15:34 * */ public boolean veryfy(HttpServletRequest request, HttpServletResponse response) { try { // GET if (request.getParameterMap().isEmpty()) { return false; } else { // Request , map HashMap para_temp = getGetMap(request); // Map, Request String sign = para_temp.get("sign"); // boolean isSign = getSignVeryfy(para_temp, sign); // ATN ( ) String responseTxt = "true"; // // responseTxt true, 、 ID、notify_id // isSign true, 、 ( : )、 // Java String regex = ".*(?i)true$"; if (Pattern.matches(regex, responseTxt) && isSign) { return true; } else { return false; } } } catch (Exception e) { e.printStackTrace(); } // return false; } }
また、上のSystem.out.printl()も、軽くツッコミを入れてほしいです.これも当時はロゴを使う習慣がなかったので、今は慣れていません.でも、幸いにも、値をプリントしてデバッグするのが便利だと思いました.
三、重の中の重さが来ました.自動配置類
package com.zuoyan.springboot.easypay;

import com.zuoyan.springboot.easypay.bean.Alipay_config;
import com.zuoyan.springboot.easypay.bean.EpaySubmit;
import com.zuoyan.springboot.easypay.function.AlipayNotify;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @ProjectName: EasyPayBootStarter
 * @Package: PACKAGE_NAME
 * @ClassName: EasyPayAutoConfiguration
 * @Author: ZuoYanCoder
 * @Description:   Starter     
 * @Date: 2019/10/24 15:00
 * @Version: 1.0
 */

@Configuration
@ConditionalOnClass({AlipayNotify.class,EpaySubmit.class})
@EnableConfigurationProperties(Alipay_config.class)
public class EasyPayAutoConfiguration {

    private final Alipay_config alipay_config;

    @Autowired
    public EasyPayAutoConfiguration(Alipay_config alipay_config)
    {
        this.alipay_config = alipay_config;
    }

    @Bean
    //        Bean        Bean
    @ConditionalOnMissingBean(AlipayNotify.class)
    public AlipayNotify alipayNotify(){
        AlipayNotify alipayNotify = new AlipayNotify(alipay_config);
        return alipayNotify;
    }

    @Bean
    @ConditionalOnMissingBean(EpaySubmit.class)
    public EpaySubmit epaySubmit(){
        EpaySubmit epaySubmit = new EpaySubmit(alipay_config);
        return epaySubmit;
    }

}

これは、appication.propertiesプロファイルに配置されている属性を取得し、他の2つの構成クラスのEpaySubmit、Alipay Notifyを配置することです.
説明で使用するいくつかのスターターに関するコメント:
1. @ConditionalOnClass, classpath               。
2. @ConditionalOnMissingBean, Spring Context     Bean 。
3. @ConditionalOnProperty(prefix = "example.service",value = "enabled",havingValue = "true"),      example.service.enabled=true 。
四、spring.factoresを追加する
最後のステップは、resources/META-INF/においてspring.factoriesファイルが作成され、以下を参照するためにコンテンツが作成される.
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.zuoyan.springboot.easypay.EasyPayAutoConfiguration
自動設定クラスが複数ある場合は、コンマで区切って改行すればいいです.
OK、完了しました.mvn:installを実行して包装してインストールします.Spring Boot Starterは開発されました.
五、まとめ
スターの仕事原理をまとめます.
  • Spring Bootが起動時にスキャン項目に依存するJARパッケージを探しています.spring.factoriesファイルを含むJARパッケージ
  • を探しています.
  • は、spring.factoriesの構成に従ってAutoConfigreクラス
  • をロードする.
  • は、@Conditionalが注釈した条件に従って、自動的に配置し、ビームをSpring Contect
  • に注入する.