顯示具有 java 標籤的文章。 顯示所有文章
顯示具有 java 標籤的文章。 顯示所有文章

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年1月10日 星期日

檢查文字檔案編碼

最近做了針對純文字檔案(.txt)的Parse工作,由於取得的txt檔案有可能是utf-16編碼

因此若用一般IO方式讀檔案

new BufferedReader(fileReader);

會出現多餘的空白導致判斷有問題,因此需要先判斷檔案的格式是什麼再改成

new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-16"));

以下是找到的java lib Sample Code,做個紀錄...

https://code.google.com/p/juniversalchardet/

import org.mozilla.universalchardet.UniversalDetector;
public class TestDetector {
  public static void main(String[] args) throws java.io.IOException {
    byte[] buf = new byte[4096];
    String fileName = args[0];
    java.io.FileInputStream fis = new java.io.FileInputStream(fileName);

    // (1)
    UniversalDetector detector = new UniversalDetector(null);

    // (2)
    int nread;
    while ((nread = fis.read(buf)) > 0 && !detector.isDone()) {
      detector.handleData(buf, 0, nread);
    }
    // (3)
    detector.dataEnd();

    // (4)
    String encoding = detector.getDetectedCharset();
    if (encoding != null) {
      System.out.println("Detected encoding = " + encoding);
    } else {
      System.out.println("No encoding detected.");
    }

    // (5)
    detector.reset();
  }
}


2015年8月12日 星期三

ORA-22922: nonexistent LOB value

ORA-22922: nonexistent LOB value

最近處理了一個原本以為是Java端控制JDBC資料有問題而導致的ORA錯誤,找了半天終於找到可能的原因,紀錄一下免得下次再找半天....

環境敘述

Database : Oracle 10G
Program Language : Java
Application Server : weblogic
Framework : spring 4


錯誤訊息

org.springframework.jdbc.UncategorizedSQLException: StatementCallback;
uncategorized SQLException for SQL [ 
  SELECT *
  FROM (SELECT a.*, ROWNUM r__
          FROM (SELECT *
                  FROM DUMMY_V
                 WHERE (1 = 1)) a
         WHERE ROWNUM < ( (1 * 100) + 1))
  WHERE r__ >= ( ( (1 - 1) * 100) + 1)
];
SQL state [99999]; error code [22922]; ORA-22922: nonexistent LOB value;
nested exception is java.sql.SQLException: ORA-22922: nonexistent LOB value


錯誤分析

其中DUMMY_V是一個View,透過WMSYS.WM_CONCAT將多筆資料合成一筆,為了避免處理CLOB資料型態,所以公司習慣補上to_char將資料轉成varchar,因此寫成了

... select key, to_char(WMSYS.WM_CONCAT(column1 )) from table ...

因此在某些狀況下(可能是資料筆數少),會出現錯誤訊息。原因可能是因為google上找到的某段訊息....

to_char and WM_CONCAT allocated memory size is inconsistent

所以將to_char拿掉後老實處理就解決了.....

資料參考
http://www.javaproblemstips.com/160064/

更新(2015/9/25):
拿掉之後仍在資料較多的情況發生了同樣的訊息,因此後來將本來透過wm_concat將資料串接改成透過trigger串街後存入其他的資料表在查詢的方式處理,因此上述的方法可能沒有完全解決問題,透過11G的LISTAGG會是較好的處理方式(若只有10G以前的版本就.....)

2014年10月31日 星期五

安裝及設定Apache Maven

以下文章主要基於Apache Maven的官方文件並加上一些個人經驗。若需要檢視原文可參考以下網址進行。http://maven.apache.org/download.cgi#Installation

0.其他準備

由於Maven是基於Java開發的工具,因此需要先安裝JDK,以下是參考版本,由於目前安裝的版本是Maven 3.2.3,因此至少需要安裝JDK1.6以上的版本,其餘版本請再參考相關版本關聯的系統需求。

1.下載Maven

可至Apache官方網站確認所需要使用的版本來下載,這邊以Maven 3.2.3為例來安裝。
apache-maven-3.1.1-bin.zip(http://ftp.twaren.net/Unix/Web/apache/maven/maven-3/3.0.5/binaries/apache-maven-3.0.5-bin.zip)

2.解壓縮

請解壓縮至自己喜歡的位置,並記得解壓縮的路徑,後面設定環境變數的時候會需要用到。這邊我下載到D:\Tools\Apache Maven。

3.設定環境變數

按下Window鍵+Pause/Break鍵可出現系統檢視畫面,按下【進階系統設定】。

這裡先確認JDK的JAVA_HOME參數是否有設定,如果沒有需要補上。
JAVA_HOME = C:\Program Files\Java\jdk1.7.0_51 (這裡放上JDK的安裝目錄)

這裡增加變數如下
M2_HOME = D:\Tools\Apache Maven\apache-maven-3.2.3-bin\apache-maven-3.2.3 (即Maven解壓縮後的目錄)
M2 = %M2_HOME%\bin

在原有的Path變數後增加以下兩個,並且以;隔開 (例如xxxx;%M2%;%JAVA_HOME%\bin;)
Path add %M2%
Path add %JAVA_HOME%\bin
xxxx;%M2%;%JAVA_HOME%\bin;


選擇性可增加以下參數,用於Maven使用JVM的一些參數。
MAVEN_OPTS="-Xms256m -Xmx512m"

4.驗證
使用命令提示字元鍵入以下指令,如果正常即會出現下畫面。

mvn --version