2020年12月30日 星期三

技術筆記:因工作需要架個簡單網站,兼回想曾在網路公司時的青春

前兩天開會時提到,配合文管需要,得有個能上傳WORD,系統自動轉換為PDF(帶浮水印)後,就立刻啟動下載程序的網路服務。聽到網路程式,大家你看看我,我看看你,都是雙手一攤,誰要我們是竹科硬體系統廠呢?但若是在我年輕時任職的網路公司,這種要求只是塊小蛋糕屑屑。所謂術業有專攻,就是這個意思吧。

既然我總是最閒的人,就接了這差事。而原本打算簡單裝個node.js模組(連結 連結)快速搞定,卻因為機器是躲在防火牆和嚴密資安監控,根本無法"安裝"軟體,只能在現有Windows Apache帶著Tomcat的架構上想辦法。只是十多年沒碰伺服器程式,進行時處處碰壁,筆記重拾記憶的雜亂過程時,兼回想過往在網際網路產業工作時的青春。

自己從學生時期就是主修資訊管理,抱著對大規模資料處理的夢想與熱情,甫畢業就加入蕃薯藤網站,也是華人最早的入口網站,幾年後再到以知識檢索見長的宇匯科技。這段期間日日夜夜接觸所及都與網際網路息息相關,且不只是我或少數公司,環顧當時Openfind、奇摩、雅虎、PCHOME等各家公司,無論是工程師或管理階層,都相信只要憑藉著技術,就能建構起偉大服務,然後就能販售產品,取得流量,處處充滿著躍躍欲試的氛圍。

但事與願違,以我自己來說,離開宇匯後進入硬體代工廠後,就再也沒碰觸過任何伺服器,而前述曾經如日中天的企業,若不是轉型為電子商務,也都消弭於市場機制中。今日與大多數人緊綁在一起的服務,無論是臉書、IG、LINE、GOOGLE各種服務,都並非由上述台灣公司演化而來,而是全由國外企業建立。

我當然不是什麼社會觀察家,但只要有眼睛,應該都能發現,與三十年前網際網路推出時狀況相比,現今世界取得資訊的管道是更為集中了。以往標榜的分散式、分權化早已消失於無形。使用者益發向少數資訊平台靠攏。而且不幸的是,這股平台洪流隊伍中,幾乎沒有任何是出自於台灣"軟體"廠商之手。

這絕對不是本土廠商犯了什麼錯誤,而是大勢所趨,但對每個曾經投入網際網路初期發展的人來說,如今軟體廠商的邊緣化,真的是僅有唏噓可以形容。無獨有偶的是,前年開始的人工智慧浪潮,似乎是前述翻版。

扯遠了,回到我那小小的轉換功能。檢視Windows上WORD轉換成PDF的方案,首推C#,但在Apache環境下,似乎只能含淚使用JAVA,連帶還得使用骨灰等級的tomcat、JSP、Servlet就覺得有些無奈。

JSP / Servlet

Apache版本是骨董等級的2.2版,設定在conf/httpd.conf,未來XXX domain服務會自動轉往tomcat服務。

<VirtualHost *:80>ServerName XXX
    ProxyPass / http://XXX:8081/
    ProxyPassReverse / http://XXX:8081/
</VirtualHost>

而Tomcat是更為久遠的6.0版(原atlassian自帶版本過於混亂,也不敢改),安裝在tool\xxxportal\xxx6.0。依序調整port  conf/server.xml  <Connector port="8081"... (原本8080已被占用,改為8081),和bin\startup.bin,在開頭加入下面兩行。若command直接執行startup.bat。

set JAVA_HOME=C:\Program Files\Java\jdk1.7.0_11
set CATALINA_HOME=C:\目前目錄\apache-tomcat-6.0.0

在webapp\ROOT\下簡單放入個JSP,以http://127.0.0.1:8081/DateJSP.jsp,確認執行無誤後,繼續加入servlet。

對習慣使用Django或ROR等WEB應用框架的人來說,JSP實在是又土又難用,若要用MVC還得另外引入Spring Framework,IDE雖然可用ECLIPSE(連結),但最新版ECLIPSE的JAVA都飛到11版了,版號差異太大,評估後決定靜下心研究如何以command模式編譯需要的java成為servlet。

先簡單製作MyServlet.java,貼入

class MyServlet {
    public static void main(String[] args) {
        System.out.println("Hello, World!"); 
    }
}
javac MyServlet.java  -> MyServlet.class -> java MyServlet (應該是省略jar部分)
改換成
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class MyServlet extends HttpServlet
{
    public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException 
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        out.println("<h1>Hello Readers</h1>");
        out.println("</body></html>");
    }
}
javac -classpath C:\tool\XXX\apache-tomcat-6.0.0\lib\servlet-api.jar MyServlet.java  (servlet需要的內容放在classpath中)
把MyServlet.class,放在.\webapps\ROOT\WEB-INF\classes 下,修改WEB-INF\web.xml(連結)
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
重新啟動tomcat  http://127.0.0.1:8081/hello  確認JSP與Servlet連結無誤。

繼續參考(連結)完成網頁上傳檔案服務。

javac -classpath C:\XXX\apache-tomcat-6.0.0\lib\servlet-api.jar;commons-fileupload-1.2.jar;commons-io-2.2.jar FileUploadServlet.java

編成的class放入C:\XXX...\webapps\ROOT\WEB-INF\classes\net\codejava\upload (後面這串是配合package而寫)  同時要把jar放在 C:\XXX...\webapps\ROOT\WEB-INF\lib 中,修改web.xml為

<servlet>
    <servlet-name>FileUploadServlet</servlet-name>
    <servlet-class>net.codejava.upload.FileUploadServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>FileUploadServlet</servlet-name>
    <url-pattern>/uploadFile</url-pattern>
</servlet-mapping>
把相關JSP放好,連結 http://127.0.0.1:8081/upload.jsp 上傳檔案會在.\webapps\ROOT\upload,並顯示message.jsp。

至此已經大致完成,最後探討WORD轉換為PDF方案,先測試jofficeconvert(連結),以console編譯和執行方式為

1.javac -classpath jofficeconvert.jar WordToPDF.java (程式在此,會使用lib)
2.jar -cf WordToPDF.jar WordToPDF.class (將class編入jar檔案中)
3.java -cp jofficeconvert.jar;WordToPDF.jar WordToPDF 直接執行class中function

確認無誤後,嘗試將這組程式併入前段的上傳範例 javac -classpath C:\XXX\apache-tomcat-6.0.0\lib\servlet-api.jar;commons-fileupload-1.2.jar;commons-io-2.2.jar;jofficeconvert.jar FileUploadServlet.java  將新產生的class比照上傳範例更新,測試成功。最後是修改message.jsp,上傳完畢後,servlet啟動轉換程序,並且讓瀏覽器透過JSP繼續下載已經轉換完的PDF檔案。


SPRING Framework

工作持續演進,需要個簡易佈告欄功能。參考(連結),並且開始使用spring framework,ECLIPSE和MAVEN。tomcat是單獨安裝8.5。(eclipse內部安裝似乎有副作用)

ECLIPSE位置在/home/kayjean/eclipse/jee-2020-12/eclipse,啟動,選擇window -> preference -> server -> runtime environment ...  設定兩者可以結合。未來,系統會自動包裹進入/home/kayjean/eclipse-workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/tomcat1/WEB-INF/xxx 且由ECLIPSE直接 啟動該tomcat。

MAVEN

曾嘗試單獨安裝Spring和其他套件,遭遇太多困難,決定啟用MAVEN。在ECLIPSE中file->new->maven project->skip page 1 , page 2 wait 10 seconds , choose org.apache.maven.archetypes maven-archetype-webapp -> groupid(company name ex:com.altek.medical) artifact id(project name ex:portal)   至此,先測試right click project->run as->run on server -> choose server -> choose correct war set
http://localhost:8080/portal/  -> Hello World 測試成功.  (重複測試時發生error :
The superclass "javax.servlet.http.HttpServlet" was not found... 解決方式是property->project facets->runtimes-> enable server

pom file中加入下面內容
    <spring.version>4.2.0.RELEASE</spring.version>
    <jstl.version>1.2</jstl.version>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>

重新開始(clean),就會發現JSP編譯失敗。在java build path -> libraries -> add library -> server runtime -> choose tomcat 8.5,在order中選擇並且放到最上面,且enable。回到原始控制台,JSP正常,並且出現src/main/java可以加入我們的程式碼。

XML要另外加入xpath
<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jaxen/jaxen -->
<dependency>
    <groupId>jaxen</groupId>
    <artifactId>jaxen</artifactId>
    <version>1.1.6</version>
</dependency>

Controller

Spring Framework最核心概念為MVC,程式上乃依靠bean在運作。所有瀏覽器傳送過來的URL,凡包含xxx.do,會由bean轉交給org.springframework.web.servlet.DispatcherServlet處理。DispatcherServlet規則是解析 /WEB-INF/appconfig-root.xml 的設定,如<context:component-scan base-package="com.altek.medical.board.dao.*"/> ,由目錄名稱,自動對應到需要的CLASS且開始執行。處理結果,可用下面幾種方式回傳使用者。

  • return xxx,xxx就會變成xxx.jsp
  • return "redirect:/jsps/user_login.jsp"
  • 呼叫另外controller
  • spring注射方式

JSP類會在JSP目錄中尋找配對檔案,將servlet資料與JSP頁面整合後輸出。

使用者帳密

Tomcat似乎能請瀏覽器將當時電腦的網域登錄名稱傳回伺服器(連結)。測試結果失敗,但若是要整合AD是有可能的(連結 連結 連結),取得名稱方式(連結 連結)。

沒有留言:

張貼留言