tomcat install apr and tomcat-native

今天將tomcat6換成tomcat7時,出現以下的資訊。

The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/lib/jvm/java-6-sun-1.6.0.26/jre/lib/amd64/server:/usr/lib/jvm/java-6-sun-1.6.0.26/jre/lib/amd64:/usr/lib/jvm/java-6-sun-1.6.0.26/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib

找尋解決方法,發現可透過aprtomcat native解決。apr主要是為了提高靜態檔案的處理性能,以apache2.0為核心的http service,除了前面所提的,還有改變加密方式等…。

依照官方說明,需先安裝:

debain based
    apt-get install libapr1.0-dev libssl-dev

rpm based
    yum install apr-devel openssl-devel
 
**接著去官方[download apr](http://apr.apache.org/download.cgi)[ and apr-util](http://apr.apache.org/download.cgi):**
wget http://ftp.mirror.tw/pub/apache/apr/apr-1.4.6.tar.gz
wget http://ftp.mirror.tw/pub/apache//apr/apr-util-1.4.1.tar.gz
 
**解壓縮和編譯apr:**
tar zxvf apr-1.4.6.tar.gz   
cd apr-1.4.6.tar.gz  
./configure  
make  
make install
 
**解壓縮和編譯apr-util:**
tar zxvf apr-util-1.4.1.tar.gz  
cd apr-util-1.4.1.tar.gz  
./configure --with-apr=/usr/local/apr  
make  
make install 
 
**安装 tomcat-native:**
cd /usr/local/apache-tomcat-7.0.30/bin  
tar zxvf tomcat-native.tar.gz  
cd tomcat-native-1.1.14-src/jni/native  
./configure --with-apr=/usr/local/apr --with-java-home=/usr/java/jdk1.6.0_26  
make  
make install  
 
**配置apr的環境:**
vi /etc/profile  
# 在檔案最後面,加入以下内容  
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib  
# 使profile生效
source /etc/profile  
 
**啟動tomcat和顯示資訊:**
bin/startup.sh  
head logs/catalina.out

struts2 json field bridge

如果建立了一個model,但是經由action export,得到的是exception,或者不是你想要的結果。這時可以使用@JSONFieldBridge,也可以自行撰寫你想要回傳的值。

import org.apache.struts2.json.annotations.JSONFieldBridge;
import org.apache.struts2.json.bridge.StringBridge;
import org.bson.types.ObjectId;

public class Car{

     private ObjectId id;
     private String name;

     public void setId( ObjectId id ){
          this.id = id;
     }

     @JSONFieldBridge( impl  = StringBridge.class )
     public ObjectId getId(){ return id; }

     public void setName( String name ){
          this.name = name;
     }

     public String getName(){ return name; }
}

其中StringBridge會直接呼叫toString這個method。若你想修改回傳結果,可以實做FieldBridge這個class。以下是一個簡單的example

import org.apache.struts2.json.bridge.FieldBridge;
import org.bson.types.ObjectId;

public class ObjectIdFieldBridge implements FieldBridge{

    @Override
    public String objectToString( Object obj ){

        if( obj instanceof ObjectId )
            return "sparrow_"+obj.toString();

            return null;

    }   

}

JSONFieldBridge只有比較新版的struts才有,再來如果要回傳一個不是String type的值,似乎還沒有提供,只能解決一些比較簡單的需求,要不然只能自己組list

如果export一個model,但又不想把某個欄位值,也一起export出去的話,可以使用@JSON(serialize = false)

@JSON(serialize = false)
public String getName(){ return name; }

泛型(Generic)

在沒使用到泛型之前,有兩個類別擁有相同的功能:
public class IntegerObj {
    private Integer integerObj;
    /**
    * @param {Integer} integerObj
    */
    public void set(Integer integerObj) {
        this.integerObj = integerObj;
    }
    /**
    * @type Integer
    */
    public Integer get() {
        return integerObj;
    }
}
public class StringObj {
    private Integer stringObj;
    /**
    * @param {String} stringObj
    */
    public void set(String stringObj) {
        this.stringObj = stringObj;
    }
    /**
    * @type String
    */
    public String get() {
        return stringObj;
    }
}

以上這兩個class只有member型態上有差異,邏輯上是一模一樣,等於必須對兩種不同型態去各自撰寫一個類別,但同樣的,這些物件的最上層都是繼承Object,可將member成員替換成Object,最後再經由轉型就可以了。但是由於轉型也有轉錯的可能,那麼是不是能在宣告變數時,就先將型態定義好,並且使用同一個class,那麼這時就要使用到泛型了。

以下是個簡單的例子(java):
class CollectionExample<T>{
     private T[] _objects;
     private int _index;
     /**
     *
     */
     CollectionExample(int total){
        _objects =(T[]) new Object[total];
        _index = 0;
     }
     /**
     * @param {T} obj
     */
     public boolean add(T obj){
        boolean result = false;
        if(_index < _objects.length){
            _objects[_index] = obj;
            _index++;
            result = true;
        }
            return result;
     }
     /**
     * @param {int} index
     * @type T
     */
     public T get(int index){
          return _objects[index];
     }
     /**
     * @type int
     */
     public int getLength(){
          return _objects.length;
     }
     /**
     *
     */
     public static void main(String[] args){
      CollectionExample<Integer> collection = new CollectionExample<Integer>(10);
        //
            for(int i=1;i<=collection.getLength();i++)
                collection.add(i);
            for(int i=0;i<collection.getLength();i++)
                System.out.println(collection.get(i));
     }
}

<T>主要是來定義泛型用,T為變數名稱,換句話說他可以是其它文字,最主要用處是拿來替換型態用,例如當你宣告:
//
CollectionExample<Integer> collection = new CollectionExample<Integer>(5);
上面class的變數T,將會取代成Integer。CollectionExample類別提供了add、get和getLength三個method,主要功能是將object儲存起來以及取出。
 
###### 以下是C++的範例: CollectionExample.h
template <class CType>
class CollectionExample{
//
public:
    CollectionExample(int);
    ~CollectionExample();
    void add(CType);
    int getLength();
    CType get(int);
private:
    CType *_objs;
    int _index;
    int _length;
};
/**
* @param {int} total
*/
template <class CType>
CollectionExample<CType>::CollectionExample(int total){
    _objs = new CType[total];
    _length = total;
    _index = 0;
}
/**
*
*/
template <class CType>
CollectionExample<CType>::~CollectionExample() {
    delete [] _objs;
}
/**
* @param {CType} obj 
*/
template <class CType>
void CollectionExample<CType>::add(CType obj){
    if(_index<_length){
        _objs[_index] = obj;
        _index++;
    }
}
/***
* @param {int} index
* @type CType
*/
template <class CType>
CType CollectionExample<CType>::get(int index){
    if(index<_length)
        return _objs[index];
}
/**
* @type int
*/
template <class CType>
int CollectionExample<CType>::getLength(){
    return _length;
}

main.cpp

#include <iostream> 
#include "CollectionExample.h"
using namespace std; 

int main(){
    CollectionExample<int> collection(10);

       for(int i=0;i<collection.getLength();i++)
           collection.add(i);
       for(int i=0;i<collection.getLength();i++)
           cout<<collection.get(i)<<endl;
    return 0;
} 

結果與java相同。

Closure Template

closure template是由google release的工具之一,最主要是為了讓html與程式邏輯分開,方

便程式的維護性,讓程式只要像call method的方式,將直塞入即可得到一個完整的html

以下是一個簡單的範例:
soy:

{namespace examples.simple}

/**

  • @param color
  • @param name
    */
    {template .car}

This car is {$color} color.

Its name is {$name}.

{/template}

soy檔案的定義方式,主要是定義在註解裡,再由template裡的{$color},將值塞入。

soy定義了兩個參數,分別為namecolor,作為為塞入樣板的參數。

(即使無參數傳入時,也必須保留註解。)

 
接著將soy檔轉成js,執行以下指令:
java -jar SoyToJsSrcCompiler.jar –outputPathFormat firstExample.js firstExample.soy

 
javascript的使用方式:

document.write(examples.simple.car({name:"cool car",color:"yellow"}));

要使用template之前必須先載入soyutils.js,接著載入剛剛由soy產生好的firstExample.js,

最後只要對應好template的命名,由js呼叫就可以產生html了。

 
java的使用方式:

import com.google.template.soy.SoyFileSet;
import com.google.template.soy.data.SoyMapData;
import com.google.template.soy.tofu.SoyTofu;
import java.io.File;

public class FirstExample {

public static void main (String[] args) {

SoyFileSet sfs = (new SoyFileSet.Builder()).add(new File(&quot;firstExample.soy&quot;)).build();

SoyTofu tofu = sfs.compileToJavaObj();

System.out.println(tofu.render(&quot;examples.simple.car&quot;, new SoyMapData(&quot;name&quot;,&quot;cool car&quot;,&quot;color&quot;,&quot;yellow&quot;), null));

}

}

以上做法主要是讀取soy檔(與js做法不同),接著將檔案轉成javaobject,最後塞入參數即可產生html

closure template還有很多command可以使用,例如ifforswitch等…,詳情請參考此link