2016年11月16日 星期三

Spring Bean List max size (Spring AutoPopulatingList)


在使用Spring的時候會把資料封裝在Model(Bean)中使用,有時候資料傳輸用的Model(Bean)的屬性有List類型的資料時,資料數量預設是256筆。(BeanWrapperImpl#autoGrowCollectionLimit)

但有時候需要回傳的資料超過此限制時,就需要在Controller中定義調整,可透過以下方式將上限增加。

@InitBinderpublic void initListBinder(WebDataBinder binder) {
    binder.setAutoGrowCollectionLimit(5000);}

最近開發時碰到此一問題,做個紀錄。

2016年10月23日 星期日

使用tomcat建立WebSocket

什麼是WebSocket?

HTML5後出現的新功能,主要功能可使Client端瀏覽器與Server端建立一個持續的雙向連線,有興趣查詢詳細說明請自行參閱WikiwebsocketIThome

HTTP連線時,是一個Client端的請求發出後再由Server端回覆,Server端完成回覆後需待下次Client端再次發出請求後才會再次回覆。(如下圖)


WebSocket時,先由Client端發出請求建立一個WebSocket連線(handshaking),連線完成後ServerClient彼此建立了一個雙向的連線,使得Server可不需再透過Client發出的請求即可直接送出訊息。(如下圖)

  

WebSocket需求

為了達到上述的目的,因此需要兩個部份的Code來完成,Server端及Client

Server這裡選擇用Tomcat8Java來開發。

Client支援WebSocket的瀏覽器及Javascript來開發。


WebSocket   Code

  • Server   Side(Tomcat)

支援WebSocketTomcat需要7.x以上才可支援,需要的jar檔案是javax.websocket-api,若是Weblogic12.x或是Jetty9.x則不需要額外的Jar檔案。
  • Server Side   Code(Java)

/**
 * Created by yc_lin on 2016/10/14.
 */
import javax.websocket.*;
import 
javax.websocket.server.ServerEndpoint;
import 
java.io.IOException;
import 
java.util.HashMap;
import 
java.util.Map;/**
 * @ServerEndpoint gives the relative name for the end point
 * This will be accessed via ws://hostName:port/ApplicationName/
echo
 */
@ServerEndpoint("/echo")public class EchoServer {

    
static Map<StringRemoteEndpoint.BasicallRemote new HashMap<StringRemoteEndpoint.Basic>();

    
/**
     * @OnOpen 
透過此Method在開啟連線時可取得UserSession,將Session保存後可再次利用來傳送訊息
     */
    
@OnOpen
    
public void onOpen(Session session){
        System.out.println(session.getId() + 
" has opened a connection");
        try 
{
            RemoteEndpoint.Basic basicRemote = session.getBasicRemote()
;
            
allRemote.put(session.getId()basicRemote);
            
basicRemote.sendText("Connection Established");
        
catch (IOException ex) {
            ex.printStackTrace()
;
        
}
    }

    
/**
     * 
Server端接收到訊息時觸發
     */
    
@OnMessage
    
public void onMessage(String messageSession session){
        System.out.println(
"Message from " session.getId() + ": " + message);
        try 
{
            session.getBasicRemote().sendText(message)
;
            for 
(String id : allRemote.keySet()) {
                RemoteEndpoint.Basic basic = 
allRemote.get(id);
                
basic.sendText("123..." + message);
            
}
            System.out.println(
"allRemote..." allRemote.size());
        
catch (IOException ex) {
            ex.printStackTrace()
;
        
}
    }

    
/**
     * 
WebSocket連線關閉時觸發
     */
    
@OnClose
    
public void onClose(Session session) {
        
allRemote.remove(session.getId());
        
System.out.println("Session " session.getId() + " has ended");
    
}
}

  • Client Side   Code(Javascript)

<html>
<head>
    <title></title>
    <script>
        
var wsLoc = "ws://hostName:port/ApplicationName/echo";
        
//WebSocket可以選擇ws或是wss通訊協定,ws就相當於一般的httpwss則相當於https
        
var ws = new WebSocket(wsLoc);

        
//當連線開啟時觸發
        
ws.onopen function () {
            
console.log("Websocket is opened!!");
        
};
        
//收到訊息時觸發
        
ws.onmessage function (msgEvent) {
            
console.log("Received Message!!"msgEvent);
            var 
msgDisplay = document.getElementById("msgDisplay");
            
msgDisplay.innerText msgEvent.data;
        
};

        
//直接測試傳送訊息
        
ws.send('Hello WebSocket.');
    
</script>
</head>
<body>
Waiting for order!!<div id="msgDisplaystyle="colorblue;padding15px;">

</div>
</body>
</html>

完整的Code就如上述的部分,需要特別注意的是ws://hostName:port/ApplicationName/echo這串WebSocket網址,echo是透過@ServerEndpointannotation所指定的,這部分也可透過extend EndPoint的方式進行,這邊就另行討論。

其他參考資料:
http://blog.csdn.net/jia20003/article/details/48751847

2016年8月30日 星期二

使用jQuery時,HTML中的ID避免使用"."做串接

使用jQuery為了選擇特定的DOM常會使用ID這個屬性,命名時候需要注意使用"."

$("[id='some.cssCls.xx']")是可行的,但若用$("#ID")的模式需要改成$("#some\\. cssCls\\.xx")

這是為了避免selector"."的話是會選到Class的混淆

 $(#some.cssCls
指的會是 <span id="some" class="cssCls"> 
 而不是 <span id="some.cssCls" class="cssCls">

SO也有

所以ID盡量不要放"."


2016年8月24日 星期三

Nodejs npm install error

最近AngularJS2又更新了,連Type Script5 MIN QUICKSTART也更新,之前做過的Sample不知道丟哪去了。為了想重新看了一下裡面的差異,決定再做一次好了,沒想到nodejs此時的需求居然又變了,只好重新再下載一次。

以下是官網的需求說明
Install Node.js® and npm if they are not already on your machine.
Verify that you are running at least node v4.x.x and npm 3.x.x by running node -v and npm -vin a terminal/console window. Older versions produce errors.


因為在公司使用,所以必須修改proxy設定。

npm config set https-proxy http://proxyServer:80
npm config set proxy http://proxyServer:80

結果出現了一堆的Errororz

剛開始注意到的error codeUNABLE_TO_VERIFY_LEAF_SIGNATURE

error code UNABLE_TO_VERIFY_LEAF_SIGNATURE

查了半天只知道大概可能是網路問題,但Proxy Server已經定義好了,為什麼還是有這問題?
後來才又仔細看了一下npm-debug.log裡面,找到了unable to verify the first certificate

Error: unable to verify the first certificate

才找到可能的原因可能是因為http://registry.npmjs.org/沒有被proxy信任,參考

所以再執行以下指令才終於成功T_T

npm config set registry http://registry.npmjs.org/ --global

做個紀錄一下…..

2016年4月21日 星期四

ExtJS "sencha package upgrade"排除方式

最近必須花點時間研究Extjs了,於是從Sencha Cmd開始.....碰到了一個小問題,順手紀錄一下。

使用Sencha Cmd with Ext JS XXX時,先透過sencha which確認目前Sencha Cmd的版本。

>  Sencha which


若碰到所下載的Sencha Cmd與指定的sdk版本不相符,此時進行generate會出現錯誤。


Please run "sencha package upgrade" to update to 6.0.1.76.


>  sencha -sdk D:\extjs\ext-6.0.0\ext-6.0.0 generate app HelloWorld D:\Sencha\HelloWorld
 

需要透過命令列執行sencha package upgrade方可正常進行。

>  cd D:\extjs\ext-6.0.0-gpl\ext-6.0.0
>  sencha package upgrade

2016年3月17日 星期四

Javascript Sort

有時需要在前端進行排序時,可透過String.localeCompare()來進行比對。

var v1 "abc";
var v2 "def";
console.log(v1.localeCompare(v2));// -1
console.log(v2.localeCompare(v1));// 1
console.log(v1.localeCompare(v1));// 0

所以當有一個ObjectArray需要進行排序時,可寫成如下

var objectAry = [
    {userName:'John Doe',age:20}
    ,{userName:'Peter Hancock',age:42}
    ,{userName:'May J.',age:16}
   ];
var compareAttr 'userName';
    objectAry.sort(function (o1,o2) {
    return o1[compareAttr].localeCompare(o2[compareAttr]);
    }).forEach(function(row,index){
    console.log("row:" + index, row);
    });
 
row:0 Object {userName: "John Doe", age: 20}
row:1 Object {userName: "May J.", age: 16}
row:2 Object {userName: "Peter Hancock", age: 42}

由於localeCompare只有String才有,所以若直接用Number的資料以localeCompare的方式排序會出現錯誤。

compareAttr 'age';
    objectAry.sort(function (o1,o2) {
    return o1[compareAttr].localeCompare(o2[compareAttr]);
    }).forEach(function(row,index){
    console.log("row:" + index, row);
    });

Uncaught TypeErroro1[compareAttr].localeCompare is not a function

所以可透過prototype的方式將Number資料型態增加localeComparefunction來處理。

Number.prototype.localeCompare = function (compare) {
    if (isNaN(compare)) {//用於資料為String and Number混合比對的時候
        
return (this + "").localeCompare(compare);
    } else if (this > compare) {
        return 1;
    } else if (this < compare) {
        return -1;
    } else {
        return 0;
    }
    };
 
再次執行
 
compareAttr 'age';
    objectAry.sort(function (o1,o2) {
    return o1[compareAttr].localeCompare(o2[compareAttr]);
    }).forEach(function(row,index){
    console.log("row:" + index, row);
    });

row:0 Object {userName: "May J.", age: 16}
row:1 Object {userName: "John Doe", age: 20}
row:2 Object {userName: "Peter Hancock", age: 42}

Javascript Number

蒐集整理一下最近用Javascript計算數字的心得,以免日後每次用都要重新再搞一次….orz

·   Javascript浮點數計算

由於浮點數的誤差(詳細請參閱),因此簡單的數學計算常會在Javascript出現出乎意料之外的結果。

var n1 0.1;
var n2 0.2;
console.log(n1 n2);//0.30000000000000004
console.log(n1 n2);//0.020000000000000004
console.log(n1 n2);//0.5
console.log(n1 n2);//-0.1

0.30000000000000004
0.020000000000000004
0.5
-0.1


因此建議不要透過javascript來進行運算,或透過javascriptlibmathjs來使用。
但若只是單純的運算,不涉及一些重要資訊如金錢或有嚴重影響的資訊,也不想再額外包入相關的javascript lib,則可透過簡單的使用方式如下。

console.log(Math.round((n1 n2) * 100) / 100);
console.log(Math.round((n1 n2) * 100) / 100);
console.log(Math.round((n1 n2) * 100) / 100);
console.log(Math.round((n1 n2) * 100) / 100);

0.3
0.02
0.5
-0.1

或是增加一個Numberprototype function如下

Number.prototype.toCorrectFloat function () {
    return Math.round(this 100) / 100;
};

console.log((n1 n2).toCorrectFloat());
console.log((n1 n2).toCorrectFloat());
console.log((n1 n2).toCorrectFloat());
console.log((n1 n2).toCorrectFloat());

0.3
0.02
0.5
-0.1


· Javascript科學符號  toExponential(x)

將數字以科學符號表示,並取小數點後x字數,不足的字數以0補上。(無條件捨去)

console.log((0.00011235).toExponential());//1.1235e-4console.log((0.00011235).toExponential(3));//1.123e-4console.log((0.00011235).toExponential(7));//1.1235000e-4

· Javascript Number Format  toPrecision(x)

大於0則會取x字數(包含0不含小數點且無條件捨去)

console.log((1.0025).toPrecision(2));//1.0
console.log((1.0025).toPrecision(4));//1.003

大於0且字數大於x則會變為科學記號並只取由前數來共x數字(四捨五入)

console.log((9861.0001).toPrecision(2));//9.9e+3
console.log((9841.0001).toPrecision(2));//9.8e+3
console.log((9811.0001).toPrecision(6));//9811.00

小於0則取小數點第一個非0的數字後x字數(四捨五入)

console.log((0.00011634).toPrecision(1));//0.0001
console.log((0.00011634).toPrecision(2));//0.00012
console.log((0.00011634).toPrecision(3));//0.000116

·Javascript Number Format  toFixed(x)

取小數點後x字數(四捨五入),不足的字數量會以0補上

console.log((0.00011634).toFixed(1));//0.0001
console.log((13333.00511634).toFixed(2));//13333.01
console.log((0.103).toFixed(6));//0.103000