Java static方法塊只獲取一次物件控制程式碼供全域性使用

lightTrace發表於2018-12-25

前言

說實話,以前沒碰見過必須只獲取一次物件供全域性使用的地方,或者說多重複例項化獲得新的控制程式碼對程式也沒什麼影響,但是這種習慣是非常很不好的,比如我最近在向hdfs寫入檔案的時候我希望FileSystem fs這個控制程式碼只獲得一次,後面所有的fs操作都用這一個物件就行,因為有kerberos的驗證,如果每次操作都需要獲取FileSystem fs這個控制程式碼一來浪費驗證的時間,二來會多佔用一點記憶體!

程式碼

package com.bodyproperty.util;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.security.UserGroupInformation;
import org.springframework.stereotype.Component;
import java.io.IOException;

/**
 * @Auther: kc
 * @Date: 2018/12/19 11:22
 * @Description:
 */
@Component
public class HdfsUtil {
            static FileSystem fs;
            static{
            if (System.getProperty("os.name").toLowerCase().startsWith("win")) {
                // Windows系統
                System.setProperty("java.security.krb5.conf", "C:/Program Files/MIT/Kerberos/krb5.ini");
            } else {
                // linux系統
                System.setProperty("java.security.krb5.conf", "/etc/krb5.conf");
            }
            Configuration conf = new Configuration();
            //這裡設定namenode新
            conf.set("fs.defaultFS", "hdfs://test-da-shanghai:8020");
            //需要增加hadoop開啟了安全的配置
            conf.setBoolean("hadoop.security.authorization", true);
            //配置安全認證方式為kerberos
            conf.set("hadoop.security.authentication", "kerberos");
            //設定namenode的principal
            conf.set("dfs.namenode.kerberos.principal", "nn/test-da-shanghai@BIGDATA.COM");
            //設定datanode的principal值為“hdfs/_HOST@YOU-REALM.COM”
            conf.set("dfs.datanode.kerberos.principal", "dn/test-da-shanghai@BIGDATA.COM");

            conf.set("dfs.support.append", "true");
            conf.set("dfs.client.block.write.replace-datanode-on-failure.policy", "NEVER");
            conf.set("dfs.client.block.write.replace-datanode-on-failure.enable", "true");

            //通過hadoop security下中的 UserGroupInformation類來實現使用keytab檔案登入
            UserGroupInformation.setConfiguration(conf);
            //設定登入的kerberos principal和對應的keytab檔案,其中keytab檔案需要kdc管理員生成給到開發人員
            try {
                UserGroupInformation.loginUserFromKeytab("xxxx@BIGDATA.COM", "file:/usr/lihong/lihong.keytab");
            } catch (Exception e) {
                System.out.println("身份認證異常: " + e.getMessage());
                e.printStackTrace();
            }
                try {
                    fs = FileSystem.get(conf);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    public static  FileSystem getFs() {
                return  fs;
    }

}

其實整個程式碼中間的驗證全部不用看,主要就是我用static程式碼塊將驗證的邏輯包圍起來,然後fs這個物件就只會生成一次了,每次呼叫getFs()方法獲得的都是同一個fs物件 。

相關文章