發表於 程式分享

struts2 的struts.enable.DynamicMethodInvocation設定值

前幾日,發現網站被放上一個檔案,

經查Tomcat的access log,

是透過struts2  dynamic method invocation功能寫一上傳檔案的程式,

再透過此檔案上傳了另一個檔案,

方式如下:

http://localhost:8080/S2-032/index.action?method:%23_memberAccess%3D@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%2C%23f%3D@java.lang.Runtime@getRuntime%28%29.exec%28%23parameters.cmd….

經參考此篇文章:

http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities.html

緊急先將struts2.xml如下設定值改為false

<constant name=“struts.enable.DynamicMethodInvocation" value=“true" />

發表於 程式分享

IIS 8與Tocmat 8共同使用80port之設定方式

1.完成Tomcat 8及IIS 8安裝

2.於IIS8 / 設定應用程式集區 : DefaultAppPool

1) 選取 “DefaultAppPool” => 右鍵 => 設定應用程式集區預設值1

2) 啟用32位元應用程式 => False (一定要用False,否則IIS無法串tomcat)

1.png

3.執行Jakarta_isapi_redirector.reg,內容如下說明

1

1) regedit的路徑:[HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Jakarta Isapi Redirector\1.0]
2) extension_uri : isapi_redirect.dll路徑
3) log_file : log檔名
4) log_level : log等級
5) worker_file : Ex.workers.properties
6) worker_mount_file : Ex.uniworkermap.properties

worker.properties:為將IIS與本地tomcat實例(“本地worker”)連接的基本模板。

worker.list=worker1
worker.worker1.port=8009
worker.worker1.host=localhost
worker.worker1.type=ajp13
worker.worker1.lbfactor=1

uniworkermap.properties

/*.jsp=worker1
/myweb/* =worker1

4.右鍵 => 新增應用程式

1.png

別名 : jakarta
應用程式集區 : DefaultAppPool
實體路徑 : D:\Program Files (x86)\Apache Software Foundation\Jakarta Isapi Redirector\bin\

1.png

5.設定ISAPI篩選器

1.png

右鍵 => 新增ISAPI篩選器 =>
篩選器名稱 : jakarta
執行檔 : D:\Program Files (x86)\Apache Software Foundation\Jakarta Isapi Redirector\bin\isapi_redirect.dll

1.png

1.png

6.新增處理常式對應

1.png

右鍵 => 新增指令對應碼

1.png

輸入
要求路徑 : *.dll
執行檔 : D:\Program Files (x86)\Apache Software Foundation\Jakarta Isapi Redirector\bin\isapi_redirect.dll
名稱 : jakarta

1.png

ISAPI及CGI限制 => 更新為”允許”

1.png

右鍵 => 編輯功能權限 => 請將使用權限 讀取、指令碼、執行 均勾選

1.png

1.png

發表於 程式分享

linux 遇到inode不夠的原因

在使用MySQL查詢時出現錯誤訊息:

Can’t create/write to file ‘/var/lib/mysql/#sql_ .MYI’ (Errcode: 28)

(後來重啟Mysql竟啟動失敗,因/var/lib/mysql/mysql.sock無法產生)

於Linux執行指令確認是disk space不足,

1

但執行指令df -h卻是尚有20%空間,

後來google發現有可能是inode不足,

執行df -i 果然inode不夠,

disk內有65萬個檔案;

後來找到路徑/var/spool/clientmqueue內共有50萬個檔案,

這個路徑的檔案是因為當cron執行時 會將相關結果以mail傳送給執行身份的帳號,

可是當sendmail 沒有啟動 那麼所有信件就會暫存在這個目錄,

因此就大膽的先刪除檔案,

檔案太多建議執行以下指令ls | xargs rm -rf刪檔,

刪除後DB就正常了。

建議若不需要傳送cron執行結果的排程最後方要加上:

1

即標準輸出、錯誤輸出均導至/dev/null刪除。

發表於 程式分享

MySQL 無法查詢及執行資料,且出現錯誤訊息SQL Error: 1030, SQLState: HY000

爬文後發現是disk滿了,

在linux 上執行command:df -h確認disk 100%,

切換至mysql log路徑,將log檔案導空 (不是刪除檔案,是導空哦),

我用的路徑及指令如下:

cd /var/log/mysql

mysql_log

發表於 程式分享

使用word功能變數,convert word to pdf,並解決中文顯示問題

使用xdocreport套件:https://github.com/opensagres/xdocreport

1.word / Ctrl + F9 => 編輯功能變數 => 設定"Merge Field",欄位名稱請加$

1.PNG1.PNG

2.程式碼

import java.awt.Color;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.poi.xwpf.converter.pdf.PdfOptions;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfWriter;
import fr.opensagres.xdocreport.converter.ConverterTypeTo;
import fr.opensagres.xdocreport.converter.ConverterTypeVia;
import fr.opensagres.xdocreport.converter.Options;
import fr.opensagres.xdocreport.core.XDocReportException;
import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.itext.extension.font.ITextFontRegistry;
import fr.opensagres.xdocreport.samples.docxandvelocity.model.Project;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;

public class Convert2PDF {
    public static void main(String[] args) throws DocumentException {
        try {             
              InputStream in = new FileInputStream(new File("A.docx"));
              IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Velocity);
              IContext context = report.createContext();
              Project project = new Project("測試XDocReport");
              context.put("project", project);
              //功能變數替換
              context.put("fieldName1", "-1.FieldFirst中文");
              context.put("titleName2", "-2.中文MergeTitleTwo");
              context.put("parameter1", "-3.row1,value3");
              context.put("parameter2", "-4.row2,value1");
              context.put("parameter3", "-5.red,row3,value2");
             
              OutputStream out = new FileOutputStream(new File("A_Out.pdf"));
              PdfOptions pdfOptions = PdfOptions.create();
              pdfOptions.fontProvider( new ITextFontRegistry()
              {
                  public Font getFont( String familyName, String encoding, float size, int style, Color color )
                  {
                      try
                      {
                          BaseFont bfChinese =
                              BaseFont.createFont( "font/kaiu.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED );
                          Font fontChinese = new Font( bfChinese, size, style, color );
                          if ( familyName != null )
                              fontChinese.setFamily( familyName );
                          return fontChinese;
                      }
                      catch ( Throwable e )
                      {
                          e.printStackTrace();
                          // An error occurs, use the default font provider.
                          return ITextFontRegistry.getRegistry().getFont( familyName, encoding, size, style, color );
                      }
                  }
    
              } );
              
              Options options = Options.getTo(ConverterTypeTo.PDF).via(ConverterTypeVia.XWPF).subOptions(pdfOptions);
              report.convert(context, options, out);
             
              //加密            
              Document pdfDocument = new Document();
              PdfCopy pdfCopy = new PdfCopy(pdfDocument, new FileOutputStream("A_Out2.pdf"));
              String pwd = "testpwd";
              pdfCopy.setEncryption(pwd.getBytes(), pwd.getBytes(), 0,
                        PdfWriter.ENCRYPTION_AES_128);
              
              PdfReader pdfReader = new PdfReader("A_Out.pdf");
              int numberPage = pdfReader.getNumberOfPages();
              pdfDocument.open();
              for (int iPage = 1; iPage <= numberPage; iPage++) {
                  pdfCopy.addPage(pdfCopy.getImportedPage(pdfReader, iPage));
              }
              pdfDocument.close();
         } catch (IOException e) {
             e.printStackTrace();
         } catch (XDocReportException e) {
             e.printStackTrace();
         }
    }
}

3.執行後結果:開啟"A_Out2.pdf"

1) 顯示輸入密碼

1.PNG

2) 顯示內容

1

補充:pdf檔案加密,需於執行此程式時,請下載 bcprov-jdk16-146.jar (http://www.java2s.com/Code/Jar/b/Downloadbcprovjdk16146jar.htm),
執行時classpath加上bcprov-jdk16-146.jar

補充說明:我使用的xdocReport是使用iText2,原本是要用iText7開發套表成pdf檔,但需購買pdf writer,且iText7/iText5應該需要購買商業版權,關於iText license說明如下-https://zh.wikipedia.org/wiki/IText說明請參考:

iTextSharp 4.1.6/iText 4.2.0之前的版本是在MPLLGPL許可證下分發的,
允許用戶在閉源軟體專案中使用。
2009年底,iText第5版發布,其許可證被更換為Affero通用公共許可證第3版。 
那些不願意提供其原始碼的專案,可以購買iText第5版的商業許可,
或沒有任何變化的繼續使用iText的以前版本(其許可證更寬鬆)。
然而,開發商Bruno Lowagie警告說,
第5版之前的版本可能包含非LGPL授權的代碼,
因而以前版本的閉源專案的用戶可能需要為侵犯版權負責。
雖然AGPL庫可以連結到GPL的程式,但AGPL許可證與GPL許可證不相容。
發表於 程式分享

使用iText將多個pdf檔合併成一個pdf檔

範例如下,請參考:

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfSmartCopy;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;

public class mergePDF {
    public static void main(String args[]) throws IOException, DocumentException {
        //merge
        String[] files = {"filled_out_job_application.pdf", "replace_stream.pdf"};
        mergeFiles(files, "a.pdf", true);
        mergeFiles(files, "b.pdf", false);
    }

    public void mergeFiles(String[] files, String result, boolean smart) throws IOException, DocumentException {
        Document document = new Document();
        PdfCopy copy;
        if (smart)
            copy = new PdfSmartCopy(document, new FileOutputStream(result));
        else
            copy = new PdfCopy(document, new FileOutputStream(result));
        document.open();

        com.itextpdf.text.pdf.PdfReader[] reader = new com.itextpdf.text.pdf.PdfReader[3];
        for (int i = 0; i < files.length; i++) {
            reader[i] = new com.itextpdf.text.pdf.PdfReader(files[i]);
            copy.addDocument(reader[i]);
            copy.freeReader(reader[i]);
            reader[i].close();
        }
        document.close();
    }
}
發表於 程式分享

使用iText套表產生新的pdf檔~一併解決中文字顯示issue

1.先使用Adobe Acrobat Pro DC 產生 Field Properties(Edit PDF => Prepare Form)

1.PNG

2.下載iText7

http://developers.itextpdf.com/itext-7-java

3.程式如下

import com.itextpdf.forms.PdfAcroForm;
import com.itextpdf.forms.fields.PdfFormField;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.color.Color;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.*;

ublic class testPDF { 
    public static final String SRC = "pdf/src/subscribe.pdf";
    public static final String DEST = "pdf/dest/subscribe_result.pdf";
 
    public static void main(String args[]) throws IOException {
        new testPDF().manipulatePdf(SRC, DEST);
    }
 
    public void manipulatePdf(String src, String dest) throws IOException {
        //Initialize PDF document
        PdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(dest)); 
 
        PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);
        Map<String, PdfFormField> fields = form.getFormFields();
        //中文字issue 
        PdfFont font = PdfFontFactory.createFont("font/kaiu.ttf", PdfEncodings.IDENTITY_H, true);
        fields.get("personal.name").setFont(font); 
        fields.get("personal.loginname").setFont(font);
        fields.get("personal.password").setFont(font);
        fields.get("personal.reason").setFont(font);
        
        fields.get("personal.name").setValue("測試名字").setBackgroundColor(Color.ORANGE);
        fields.get("personal.loginname").setValue("NickName").setBackgroundColor(Color.WHITE);
        fields.get("personal.password").setValue("a12345678").setBackgroundColor(Color.WHITE);
        fields.get("personal.reason").setValue("原因是...").setBackgroundColor(Color.WHITE);
        
        form.flattenFields();
        pdfDoc.close();
    }
}

4.執行後產生之PDF如下圖

2.PNG

5.若使用iText5,中文字的處理如下範例

        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader,
                new FileOutputStream(dest));
        
        AcroFields fields = stamper.getAcroFields();
        //中文字處理
        BaseFont font = BaseFont.createFont("font/kaiu.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED );
        fields.setFieldProperty("name","textfont",font,null);        
        fields.setField("name", "ROC 台灣");

        stamper.setFormFlattening(true);
        stamper.close();
        reader.close();
發表於 程式分享

jquery bootstrapValidator如何驗證2個欄位只輸入其一即可

期望的畫面如下

1
畫面的html如下

1

 

1.jquery bootstrapValidator如何驗證2個欄位只輸入其一即可

    //被授權人
    $('#rowAddAuthForm').bootstrapValidator({
        excluded: [':disabled'],
        fields: {
            telNo: {
                group: '.col-md-3',
                validators: {
                    callback: {
                        callback: function(value, validator, $field) {
                            var field_name = $($field).attr('name');
                            if (value.length == 0 && $('#mobileNo_auth').val() == '') {
                                return {
                                    valid: false,
                                    message: '連絡電話、手機請至少輸入其一'
                                }
                            }
                            
                            if ($('#mobileNo_auth').val() == '') {
                                $('#rowAddAuthForm').bootstrapValidator('resetField', 'mobileNo' )
                                     .bootstrapValidator('updateStatus', 'mobileNo', 'VALID');
                                $('#rowAddAuthForm').bootstrapValidator('disableSubmitButtons', false);
                            }
                            
                            $('#rowAddCommForm').data('bootstrapValidator').resetForm(true);
                            if (value.length != 0) {
                                var pattern = /^[0-9]+$/;        
                                if (value.length  8) {
                                    return {
                                        valid: false,
                                        message: '電話 長度需為6~8'
                                    }
                                } else if (pattern.test(value) == false) {
                                    return {
                                        valid: false,
                                        message: '電話 請輸入數字'
                                    }
                                } else {
                                    return true;
                                }                                
                            } else {
                                $('#rowAddAuthForm').bootstrapValidator('resetField', field_name )
                                     .bootstrapValidator('updateStatus', field_name, 'NOT_VALIDATED');
                                $('#rowAddAuthForm').bootstrapValidator('disableSubmitButtons', false);
                                return true;
                            }
                        }
                    }
                }
            },
            mobileNo: {
                group: '.col-md-3',
                validators: {
                    callback: {
                        callback: function(value, validator, $field) {
                            var field_name = $($field).attr('name');
                            if (value.length == 0 && $('#telNo_auth').val() == '') {
                                return {
                                    valid: false,
                                    message: '連絡電話、手機請至少輸入其一'
                                }
                            }
                            
                            if ($('#telNo_auth').val() == '') {
                                $('#rowAddAuthForm').bootstrapValidator('resetField', 'telNo' )
                                        .bootstrapValidator('updateStatus', 'telNo', 'VALID');  
                                $('#rowAddAuthForm').bootstrapValidator('disableSubmitButtons', false);
                            }
                            
                            if (value.length != 0) {
                                var pattern = /^[0-9]+$/;        
                                if (value.length != 10) {
                                    return {
                                        valid: false,
                                        message: '手機號碼 長度需為10'
                                    }
                                } else if (pattern.test(value) == false) {
                                    return {
                                        valid: false,
                                        message: '手機號碼 請輸入數字'
                                    }
                                } else {
                                    return true;
                                }                                
                            } else {
                                $('#rowAddAuthForm').bootstrapValidator('resetField', field_name )
                                        .bootstrapValidator('updateStatus', field_name, 'NOT_VALIDATED');  
                                $('#rowAddAuthForm').bootstrapValidator('disableSubmitButtons', false);
                                return true;
                            }
                            
                        }
                    }
                }
            }
        }
    }).on('success.form.bv', function(e) {
        e.preventDefault();
        myfootable.auth_save(e);
        $("#addAuthModal").modal("hide");
    });    

2.bootstrapValidator如何判斷A欄位有值,B欄位也應有值 (反之,若A欄位無值,則B欄位無需有值)

    //被授權人
    $('#rowAddAuthForm').bootstrapValidator({
        excluded: [':disabled'],
        fields: {
            ...
            telRC: {
                validators: {
                    stringLength: {
                        min: 2,
                        max: 4,
                        message: '電話區碼 長度需為2~4'
                    },
                    regexp: {
                        regexp: /^[0-9]+$/,
                        message: '電話區碼 請輸入數字'
                    },
                    callback: {
                        callback: function(value, validator, $field) {
                            var field_name = $($field).attr('name');
                            if (value.length == 0 && $('#telNo_auth').val().length > 0) {
                                return {
                                    valid: false,
                                    message: '請輸入電話區碼'
                                }
                            } else {
                                return true;
                            }
                        }
                    }
                }                
            },
            ...
        }
    }).on('success.form.bv', function(e) {
        e.preventDefault();
        myfootable.auth_save(e);
        $("#addAuthModal").modal("hide");
    });    

註:bootstrapValidator的相關文件可參考 http://bv.doc.javake.cn/api/

發表於 程式分享

hibernate效能

文章:Tomcat啟動很久才完成經過2週終於找到原因並成功解決了~

原因是hibernate的hbm.xml設定檔在Tomcat啟動時需先load至Tomcat memory,但是透過hbm.xml檔load至memory需要I/O及memory,故會花費許久,因table共70多個,而且有些table的欄位很多,故造成Tomcat需啟動許久。
我試了以下3種hbm.xml的設定均無法降低啟動時間:

<property name="mappingDirectoryLocations">
    <list>
        <value>classpath:com/xxx/bean/</value>
    </list>
</property>

<property name="mappingLocations">
    <list>
        <value>classpath:com/xxx/bean/*.hbm.xml</value>
        ...
    </list>
</property>

<property name="mappingResources">
    <list>
        <value>com/xxx/bean/PRCmdCfg.hbm.xml</value>
        ...
    </list>
</property> 

後來,試著將設定檔內sql調整成直接寫在程式內而不用hbm.xml設定的方式,啟動效能並未改善:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC    
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
  "http://hibernate.org/dtd/hibernate-mapping"> 
<hibernate-mapping> 
  <class name="com.xxx.bean.PRUnit" table="PRUnit"> 
   ...
  </class>
    <sql-query name="findPRUnitWithDetail">
        <return alias="t1" class="com.xxx.bean.PRUnit"/>
        <return alias="t2" class="com.xxx.bean.PRFuncCfg"/>
        <return alias="t3" class="com.xxx.bean.PRCmdCfg"/>
        <return alias="t4" class="com.xxx.bean.PRCode"/>
        <return alias="t5" class="com.xxx.bean.PRCode"/>
        <return alias="t7" class="com.xxx.bean.PRMenuCfg"/>
        <![CDATA[
        SELECT {t1.*}, {t2.*}, {t3.*}, {t4.*}, {t5.*}, {t7.*} 
          FROM PRUnit t1
          JOIN PRFuncCfg t2
            ON t1.platForm = t2.platForm
           AND t1.funcId   = t2.funcId
          JOIN PRCmdCfg t3
            ON t1.platForm = t3.platForm
           AND t1.funcId   = t3.funcId  
           AND t1.cmdId    = t3.cmdId      
          JOIN PRCode t4
            ON t4.CodeType = 'UNIT'
           AND t1.unitId   = t4.CodeId
          JOIN PRCode t5
            ON t5.CodeType = 'PLFM'
           AND t1.platForm = t5.CodeId  
          JOIN PRMenuCfg t7
            ON t2.platForm = t7.platForm
           AND t2.menuId   = t7.menuId                 
         WHERE t1.unitId 
               in (SELECT t8.unitId 
                     FROM PREmpUnit t8 
                    WHERE t8.empId=:EmpId AND t8.cmdEnable = 1)
           AND t1.cmdEnable = 1 
        ]]>
    </sql-query>
</hibernate-mapping>

最後,只好用最麻煩的方式,取消hbm.xml的設定,改為直接在class設定

...

@Entity
@Table(name = "PRUnit")
public class PRUnit implements Serializable {
    @EmbeddedId
    @AttributeOverrides({
        @AttributeOverride(
            name = "platForm",
            column = @Column(name = "platForm")),
        @AttributeOverride(
            name = "unitId",
            column = @Column(name = "unitId")),
        @AttributeOverride(
            name = "funcId",
            column = @Column(name = "funcId")),
        @AttributeOverride(
            name = "cmdId",
            column = @Column(name = "cmdId"))
    })
    private PRUnitPK PRUnitPK;
    @Column(name = "cmdEnable")
    private int cmdEnable;
    @Column(name = "cfgVal")
    private String cfgVal;
    @Column(name = "optVal")
    private String optVal;
    @Column(name = "modifyTime")
    private Date modifyTime;
    @Column(name = "modifyEmp")
    private String modifyEmp;

    public PRUnit() {
        
    }
    
    public PRUnit(PRUnitPK PK) {
        this.PRUnitPK = PK;
    }

    public PRUnitPK getPRUnitPK() {
        return PRUnitPK;
    }

    public void setPRUnitPK(PRUnitPK pRUnitPK) {
        PRUnitPK = pRUnitPK;
    }

    public int getCmdEnable() {
        return cmdEnable;
    }

    public void setCmdEnable(int cmdEnable) {
        this.cmdEnable = cmdEnable;
    }

    public String getCfgVal() {
        return cfgVal;
    }

    public void setCfgVal(String cfgVal) {
        this.cfgVal = cfgVal;
    }

    public String getOptVal() {
        return optVal;
    }

    public void setOptVal(String optVal) {
        this.optVal = optVal;
    }

    public Date getModifyTime() {
        return modifyTime;
    }

    public void setModifyTime(Date modifyTime) {
        this.modifyTime = modifyTime;
    }

    public String getModifyEmp() {
        return modifyEmp;
    }

    public void setModifyEmp(String modifyEmp) {
        this.modifyEmp = modifyEmp;
    }

    @Override
    public String toString() {
        return "PRUnit [PRUnitPK=" + PRUnitPK + ", cmdEnable=" + cmdEnable + ", cfgVal=" + cfgVal + ", optVal=" + optVal
                + ", modifyTime=" + modifyTime + ", modifyEmp=" + modifyEmp + "]";
    }   
}

而applicationContext.xml調整為下面任一方式,Tomcat均能在1、2分鐘內啟動完畢

<property name="packagesToScan">
    <list>
        <value>com.xxx.bean</value>
    </list>
</property>
<property name="mappingDirectoryLocations">
    <list>
        <value>classpath:com/xxx/bean/</value>
    </list>
</property>

究其原因,猜測是hibernate在load hbm.xml需要花費較多的I/O及memory,故造成啟動花費超久,
剛開始使用此架構因table尚少沒感覺,等系統愈來愈大就開始造成困擾了~還好調整後能修正此問題,
要不然整個架構大改,就不是花幾天能完成的~

發表於 程式分享

Tomcat啟動很久才完成

1.在"catalina.sh"增加此行效果不大

JAVA_OPTS="$JAVA_OPTS -Xms1024m -Xmx1024m"

2.研究spring設定檔 “applicationContext.xml" 讀取hibernate hbm.xml,

因為似乎是加上新的db schema在設定了hbm.xml後才變慢的~~

原本設定是遞迴讀此目錄下的所有檔案,但此目錄下有其它的class (非hbm.xml)

<property name="mappingDirectoryLocations">
    <list>
        <value>classpath:com/test/bean/</value>
    </list>
</property>

改成如下

<property name="mappingLocations">
    <list>
        <value>classpath:com/test/bean/*.hbm.xml</value>
        <value>classpath:com/test/bean/derivadm/*.hbm.xml</value>
        <value>classpath:com/test/bean/futadm/*.hbm.xml</value>
        <value>classpath:com/test/bean/job/*.hbm.xml</value>
        <value>classpath:com/test/bean/warrantadm/*.hbm.xml</value>
    </list>
 </property>

收到不錯的效果,啟動時間由原本的10多分鐘,縮短至4分鐘,
但仍需有努力的空間…
hibernate設定hbm.xml還有一個方式就是逐檔設定,當初就是嫌麻煩才用路徑,
也這之後要改回這個方式再試試吧~

<property name="mappingResources">
    <list>
        <value>au/com/test/bean/Address.hbm.xml</value>
        <value>au/com/test/bean/Country.hbm.xml</value>
        <!-- repeat for their mapping files -->
    </list>
</property>

3.後來再調整applicationContext.xml
於bean加上lazy-init=true

<bean id="IFServiceDao" class="com.xxx.xxx.transactional.IFServiceImpl" 
        scope="singleton" lazy-init="true">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

但效果不大
故於beans加上default-lazy-init=true

<beans xmlns="http://www.springframework.org/schema/beans"
        ....
        default-lazy-init="true">

看似有點效果,但tomcat啟動還是要5分鐘。

最後再將hibernate.hbm2ddl.auto整個移除Tomcat竟然1分鐘內就啟動好了,
雖然執行application的程式仍需要3~4分鐘,
但至少其它application可以早點執行了~

會想要調整這個參數是因每次都在log看到此行以後Tomcat才算啟動完成。
INFO [http-bio-80-exec-4] SchemaUpdate [execute] [101] HHH000228: Running hbm2ddl schema update

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        ...
        <property name="hibernateProperties">
            <props>
                ...
                <!-- 
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                 -->
                ...         
            </props>
        </property>
    </bean>