買了一本「王者歸來 Java Web 整合開發 (第二版)」,書中包含了 JSP + Servlet + Struts + Hibernate + Spring 等的教學及範例,K了一個星期後,發現最困難的部份竟然在環境架設上,光是環境架設就花了好長的時間,再來是設定檔,小蛙的 Eclipse 有些設定檔的 auto-complete 跑不出東西,加上每個版本的套件下載下來後的 Jar 檔、設定檔都不相同,不同版本的整合方式也不同 … 花了很久的時間在環境架設及設定檔上,這篇文章不記錄完整經過(忘的差不多了),只挑著把過程中要注意的事情及錯誤記錄下來。

  1. 隱藏 .jsp 頁面,對外以 .do 為主

    將 jsp 頁面通通放在 WEB-INF 底下,可自行建立其他分類資料夾,ex. pages, pages/admin, pages/member … 等。並且在 struts-conf.xml 中設定

    <action-mappings> 
        <action path="/index" type="org.apache.struts.actions.ForwardAction" parameter="/WEB-INF/pages/index.jsp"></action>
    </action-mappings>
  2. java.lang ClassNotFoundException 各式各樣怪怪的情況

    這情況太容易出現了,小蛙原本使用 Eclipse IDE 裡面自訂 User Library 的功能,卻一直報錯,最後把所有會用到的 Spring, Struts Jar 通通放在 Web/WEB-INF/lib 下,這些怪裡怪氣的錯誤就自己消失了 …

  3. 亂碼處理

    這應該是最容易遇到的問題,有幾項前提要先遵守:

    R1.  必須先將每一頁 JSP 或每一個 Servelt 設定成 UTF-8 編碼(小蛙直接用 UTF-8 編碼,可以省掉 BIG5 的一些麻煩),如果是 Eclipse 專案請確定專案編碼為 UTF-8,有些文字編輯器可以看到目前檔案編碼。

    R2. 設定 JSP 表頭:
            <%@ page language="java" contentType="text/html; charset=UTF-8″ pageEncoding="UTF-8″%>

    R3. html meta:
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8″>

    以上三個一定要指定同一編碼,確定之後接下來四種方法只要選一種來做就可以了:

    • 勤勞工人法:

      在每個 JSP 頁面及每個 Servelt 中設定

      request.setCharacterEncoding("UTF-8");
      response.setCharacterEncoding("UTF-8");
    • 源頭搞定法:

      使用 tomcat 預設過濾器 (在 Tomcat安裝目錄/conf/ web.xml 中解開註解)

      <filter>
          <filter-name>setCharacterEncodingFilter</filter-name>
          <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
          <init-param>
              <param-name>encoding</param-name>
              <param-value>UTF-8</param-value>
          </init-param>
          <async-supported>true</async-supported>
      </filter>
      <filter-mapping>
          <filter-name>setCharacterEncodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
    • 自我肯定法:

      自定義過濾器
      CharacterEncodingFilter.java

      package com.hans.filter;
      
      import java.io.IOException;
      import javax.servlet.Filter;
      import javax.servlet.FilterChain;
      import javax.servlet.FilterConfig;
      import javax.servlet.ServletException;
      import javax.servlet.ServletRequest;
      import javax.servlet.ServletResponse;
      
      public class CharacterEncodingFilter implements Filter {
      	private String characterEncoding;
      
      	@Override
      	public void init(FilterConfig config) throws ServletException {
      		characterEncoding = config.getInitParameter("encoding");
      	}
      
      	@Override
      	public void doFilter(ServletRequest request, ServletResponse response,
      			FilterChain chain) throws IOException, ServletException {
      		request.setCharacterEncoding(characterEncoding);
      		response.setCharacterEncoding(characterEncoding);
      		chain.doFilter(request, response);
      	}
      
      	@Override
      	public void destroy() {
      		characterEncoding = null;
      	}
      }

      web 下的 web.xml 加入對應

      <filter>
          <filter-name>CharacterEncodingFilter</filter-name>
          <filter-class>com.hans.filter.CharacterEncodingFilter</filter-class>
          <init-param>
              <param-name>encoding</param-name>
              <param-value>utf-8</param-value>
          </init-param>
      </filter>
      <filter-mapping>
          <filter-name>CharacterEncodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
    • 套件嵌用法:

      使用 Spring 過濾器

      <filter>
          <filter-name>CharacterEncodingFilter</filter-name>
          <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
          <init-param>
              <param-name>encoding</param-name>
                  <param-value>utf-8</param-value>
          </init-param>
          <init-param>
              <param-name>forceEncoding</param-name>
            	<param-value>true</param-value>
          </init-param>
      </filter>
      <filter-mapping>
          <filter-name>CharacterEncodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>

      以上幾種方法可以挑選適用於自己的方法來用,勤勞工人法是比較累一點,每一頁都要記得檢查,不然就可能在表單傳遞的時候發生亂碼。

  4. JNDI 錯誤

    javax.servlet.ServletException: javax.servlet.jsp.JspException: Unable to get connection, DataSource invalid: "org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'"
    javax.servlet.ServletException: org.apache.jasper.JasperException: javax.servlet.ServletException: javax.servlet.jsp.JspException: Unable to get connection, DataSource invalid: "org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'"

    明明設定上沒有什麼問題,卻發生以上 exception,設定檔如下(MySQL):

    <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
    	   maxActive="5" maxIdle="2" maxWait="60"
    	   username="your_account" password="your_password" driverClassName="com.mysql.jdbc.Driver"
    	   url="jdbc:mysql://your_domain:3306/your_database?characterEncoding=UTF-8"/>

    不管設定在 server.xml 的 <GlobalNamingResources> 標籤中、設定在 <Host> 標籤下或是設定在 localhost/context.xml 下都會出現上面的錯誤,如果有遇到這樣問題的網友,試試看設定在 Tomcat安裝目錄/conf/context.xml 裡面就不會發生這個錯誤囉!如果用這個方法要把 mysql-connector-java-5.1.22-bin.jar 複製到 Tomcat安裝目錄/conf/ 資料夾下。

    在 Spring 中加入上述 DataSource,可以供其他部份使用(透過 id 指定)

    <!-- 吃 tomcat 內部設定的 jndi 不然就要自己設定 -->
    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jdbc/TestDB"></property>
    </bean>
  5. Struts 標籤設定

    前面提到書上的範例是寫

    <%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %>
    <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>

    Eclipse 頻頻出現錯誤訊息,後來才查到 1.3 版要改成以下才可以使用

    <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
    <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
  6. struts-conf.xml 錯誤

    如果使用 1.3 的表頭檔是沒辦法設定標籤的

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts-config 
    	PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" 
    	"http://struts.apache.org/dtds/struts-config_1_3.dtd">

    要把它改成 1.2 版本的,並且要注意每個 tag 之間的順序,這邊出錯的時候 Eclipse 會列出順序,照著排就可以了。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts-config 
    	PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" 
    	"http://struts.apache.org/dtds/struts-config_1_2.dtd">
  7. Action 中使用 getDataSource 錯誤

    書上的範例以及網路上查到的資料都說在 Struts Action 中,可以透過 getDataSource(request).getConnection(); 的方式來取得連接池的 Connection,實際上試了之後才會發現 1.3 根本就沒有 getDataSource 這個方法,繞了好久才找到必須透過以下方式取得剛剛設定在 context.xml 中的 datasource。

    DataSource ds = (DataSource)new InitialContext().lookup("java:comp/env/jdbc/TestDB");
    Connection conn = ds.getConnection();
  8. Spring, Struts 接合

    接著設定 struts-config.xml 加入 <controller><plug-in> 標籤,這邊家玩如果有 ClassNotFoundException 一樣參考這篇文章第 2 點說明,Eclipse 有報錯要注意 tag 間的順序。

    <controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"></controller>
    <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
        <set-property value="/WEB-INF/beans-conf.xml" property="contextConfigLocation"/>
    </plug-in>

    原本 struts-config.xml 中的 action 設定如下

    <action-mappings> 
        <!-- 這種是預設到特定頁面的,為了隱藏 jsp -->
        <action path="/index" type="org.apache.struts.actions.ForwardAction" parameter="/WEB-INF/pages/index.jsp"></action>
        <!-- 接合 Spring 後的寫法,注意 action path (struts) 要跟 bean name (spring) 一致-->
        <action path="/hello2">
            <forward name="helloUser" path="/WEB-INF/pages/footer.jsp"></forward>
        </action>
    </action-mappings>

    Spring 設定 beans-conf.xml 如下 (範例參考自良葛格學習筆記,userChecker 及 HelloAction 請參考 良葛格學習筆記)

    <bean id="userChecker" class="com.hans.pojo.UserChecker"></bean>
    <!-- bean name 要跟 struts 裡面設定的 action path 一致 -->
    <bean name="/hello2" class="com.hans.struts.action.HelloAction2">
        <property name="userChecker" ref="userChecker" />
    </bean>
  9. Hibernate – getHibernateTemplate().find() 錯誤
    小蛙讓 MemberDao 繼承 HibernateDaoSupport 操作資料庫上比較方便,但透過 HibernateTemplate().find() 查找資料的時候(程式碼如下)

    List<Member> list = this.getHibernateTemplate().find("from Member member");
    if(list.size() > 0)
        return list.get(0);

    出現以下錯誤

    javax.servlet.ServletException: org.springframework.orm.hibernate3.HibernateQueryException: unexpected token: member near line 1, column 29 [from com.hans.entity.Member member]; nested exception is org.hibernate.hql.ast.QuerySyntaxException: unexpected token: member near line 1, column 29 [from com.hans.entity.Member member]

    from Member member 改成 from member,出現下面錯誤

    javax.servlet.ServletException: org.springframework.orm.hibernate3.HibernateQueryException: unexpected token: member near line 1, column 6 [from member]; nested exception is org.hibernate.hql.ast.QuerySyntaxException: unexpected token: member near line 1, column 6 [from member]

    改成 from Member 之後才可正常執行,後來在這篇文章看到原來 … member 是保留字 … 難怪怎麼試都會錯,還以為自己哪裡有問題。

參考資料:

  1. Struts+Spring+Hibernate项目框架构建中的问题及解决方法集锦(1) @ Morecans的专栏
    http://blog.csdn.net/morecans/article/details/1686416
  2. Spring Gossip: 在 Struts 中整合 Spring @ 良葛格學習筆記
    http://caterpillar.onlyfun.net/Gossip/SpringGossip/StrutsSpring.html 
  3. Hibernate 查詢數據時報錯,請問這是什麽原因呢?急死了! @ [email protected]
    http://www.javaworld.com.tw/jute/post/view?bid=41&id=171839
相關文章

Struts 1.3 + Spring 3.2 + Hibernate 3.6 安裝筆記

「王者歸來 Java Web 整合開發 (第
2012-11-02 21:58:30
hans

18

SSL For Free – 免費又有綠色鎖頭的 SSL Certificates

之前聽說 Google 會優先搜尋有 https 的網頁 (參考:
2016-07-07 23:00:54
hans

8

Android Vuforia with jPCT-AE (5) – 多重模型載入,以 obj 為例

要進到這系列最後一篇文章了,這篇文章拖了很久,一直沒有時間整理,結果到最後 ... 程式碼留下來了,記憶卻有些模糊了,這邊小蛙配著程式碼盡可能的把還記得的東西寫下來。
2016-07-06 11:24:19
hans

8

Android Vuforia with jPCT-AE (4) – 載入 3DS 測試

延續 jPCT-AE Loader 載入模型的部份,這篇要記錄載入 3ds 檔案格式的方法,基本上跟前面幾個 obj, md2 的方法差不多,只有一些小小的變化而已。
2016-07-06 10:24:33
hans

8

Android Vuforia with jPCT-AE (3) – 載入 md2 測試

前兩篇介紹如何直接透過 jPCT-AE 直接繪圖以及載入 .obj 檔案,這邊繼續介紹 jPCT-AE 載入 md2 的方法,載入動作大致上類似,唯一不同的只有 texture 設定部份。
2016-07-06 09:24:43
hans

8

Android Vuforia with jPCT-AE (2) – 載入 obj 測試

上一篇 Android Vuforia with jPCT-AE (1) –
2016-07-06 08:24:55
hans

8

Android Vuforia with jPCT-AE (1) – 基本範例

說來慚愧,從 Google Adsense 被 ban 之後,就好久沒有發文了,站上 Vuforia 的文章也已經是好久以前的事情了 (遠目),最近有專案要用到 Vuforia,爬以前的文回來看,蛙哩咧 ... 現在已經更新到 Vu
2016-07-06 07:57:58
hans

8

ClickForce (MobiForce) 當機問題

這真是個浪費時間又漫長的過程,CF 推出新版後台以及新版 SDK 的時候,小蛙就下載來測試,一開始小蛙直接套在「我的股票精算師」上,但只要一套上去就當機 ...
2015-09-02 10:32:51
hans

8

我的股票精算師備份功能

常遇到使用者詢問「我的股票精算師」要怎麼備份,這篇記錄一下,需要寫怎麼備份表示軟體設計上有很大的問題,造成使用者使用上的困難,但小蛙最近沒有時間去做修改 ... 只好委屈精算師的使用者了 ><
2015-02-06 18:32:07
hans

8




 回覆

你可以使用以下語法 HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="">

(required)

(required)

   
© 2012 蛙齋 Suffusion theme by Sayontan Sinha