風雨無阻

          Spring MVC 入門(轉)

          如果你手上有一本《Spring in Action》, 那么你最好從第三部分"Spring 在 Web 層的應用--建立 Web 層"開始看, 否則那將是一場惡夢!

              首先, 我需要在你心里建立起 Spring MVC 的基本概念. 基于 Spring 的 Web 應用程序接收到 http://localhost:8088/hello.do(請求路徑為/hello.do) 的請求后, Spring 將這個請求交給一個名為 helloController 的程序進行處理, helloController 再調用 一個名為 hello.jsp 的 jsp 文件生成 HTML 代碼發給用戶的瀏覽器顯示. 上面的名稱(/hello.do, helloController, hello.jsp) 都是變量, 你可以更改.

              在 Spring MVC 中, jsp 文件中盡量不要有 Java 代碼, 只有 HTML 代碼和"迭代(forEach)"與"判斷(if)"兩個jstl標簽. jsp 文件只作為渲染(或稱為視圖 View)模板使用.

              好了, 我們開始吧. 首先我們需要一個放在 WEB-INF 目錄下的 web.xml 文件:

          web.xml:
           <?xml version="1.0" encoding="UTF-8"?>
          <web-app version="2.4"
           xmlns="http://java.sun.com/xml/ns/j2ee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
           http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
           <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
             /WEB-INF/database.xml
             /WEB-INF/applicationContext.xml
            </param-value>
           </context-param>
           
           <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
           </listener>
           
           <filter>
            <filter-name>EncodingFilter</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>
           </filter>
           
           <filter-mapping>
            <filter-name>EncodingFilter</filter-name>
            <url-pattern>*.do</url-pattern>
           </filter-mapping>
           
           <servlet>
            <servlet-name>test</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
           </servlet>
           
           <servlet-mapping>
            <servlet-name>test</servlet-name>
            <url-pattern>*.do</url-pattern>
           </servlet-mapping>
           
           <welcome-file-list>
            <welcome-file>index.jsp</welcome-file>
            <welcome-file>index.html</welcome-file>
           </welcome-file-list>
           
           <jsp-config>
            <taglib>
             <taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
             <taglib-location>/WEB-INF/c.tld</taglib-location>
            </taglib>
            <taglib>   
             <taglib-uri>http://java.sun.com/jsp/jstl/fmt</taglib-uri>
             <taglib-location>/WEB-INF/fmt.tld</taglib-location>
            </taglib>
           </jsp-config>
          </web-app>
          它配置了以下功能:
          • 配置 DispatcherServlet (servlet 標簽), 它是一個 Java Servlet 程序. 我們將它命名為 test. 然后我們再配置 Servlet 映射(test-mapping 標簽), 也就是你希望哪些請求被DispatcherServlet處理. 這里, 我們設置后綴名為 do(*.do) 的所有URL請求都被名為 test 的 DispatcherServlet 的程序處理. 選擇 .do 只是一個習慣,但是你不要選擇 .html! 雖然《Spring in Action》選擇了 .html, 但是那是一種非常糟糕的作法, 特別是你整合 ApacheTomcat 的時候.

          • 配置 CharacterEncodingFilter (filter 標簽), 否則你會發現中文亂碼. 因為我的 jsp 和 html 文件都是 UTF-8 編碼的, 所以我在 param-value 標簽中設置了 UTF-8. 估計你使用的是 GB2312 或者 GBK, 立即轉到 UTF-8 上來吧.

          • 分解配置文件. context-param 標簽指明我們的配置文件還有 /WEB-INF/database.xml 和 /WEB-INF/applicationContext.xml. ContextLoaderListener(listener 標簽) 由此得知配置文件是哪些, 它會將它們載入.

          因為我們將 DispatcherServlet 命名為test, 所以我們在 WEB-INF 目錄下建立一個名為 test-servlet.xml 的文件:

          test-servlet.xml:
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
          <beans>
           <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <property name="suffix" value=".jsp"/>
           </bean>
           
           <bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
            <property name="mappings">
             <props>
              <prop key="/hello.do">helloController</prop>
             </props>
            </property>
           </bean>
           <bean id="helloController" class="com.ecnulxq.test.HelloController">
           </bean>
          </beans>
          它配置了以下功能:
          
          • 配置 InternalResourceViewResolver, 它是 jsp 渲染模板的處理器. 如果你告訴 InternalResourceViewResolver 處理一個名為 hello 的模板時, 它會渲染 /WEB-INF/jsp/hello.jsp 文件. 把 jsp 文件放到 /WEB-INF/jsp/ 目錄下是被鼓勵的, 這樣可以防止用戶不經過 Controller 直接訪問 jsp 文件從而出錯(有些頑皮的人很喜歡這樣做).

          • 配置 SimpleUrlHandlerMapping, 在上面的配置文件中, /hello.do 的請求將被 helloController 處理. "/hello.do"和"helloController" 是變量, 你可以更改. 但是你注意到了嗎, hello.do 以 .do 作為后綴名. 如果這里(本文的條件下)你不使用.do 作為后綴名, 就沒有程序來處理這個請求了. 因為 DispatcherServlet 將收到的請求轉交給 SimpleUrlHandlerMapping, DispatcherServlet 收不到的請求, SimpleUrlHandlerMapping 當然也收不到了. 你可以在 props 標簽內配置多個 prop 標簽.

          • 我們將在后面編寫com.ecnulxq.test.HelloController類.

          上面, 我們在 web.xml 文件中告訴 ContextLoaderListener, 我們還有另外兩個配置文件 /WEB-INF/database.xml 和 /WEB-INF/applicationContext.xml.

          applicationContext.xml:

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

          <beans>
           <bean id="propertyConfigure" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations">
             <list>
              <value>/WEB-INF/jdbc.properties</value>
             </list>
            </property>
           </bean>

          </beans>

          它配置了以下功能:

          • 讀取 /WEB-INF/jdbc.properties 文件. 你可以在 list 標簽中配置多個 value 標簽.

          database.xml:
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" ">
           
          <beans>
          <!-- Remove this if your database setting is fine.
            <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
              <property name="driverClassName" value="${jdbc.driverClassName}"/>
              <property name="url" value="${jdbc.url}"/>
              <property name="username" value="${jdbc.username}"/>
              <property name="password" value="${jdbc.password}"/>
            </bean>
          -->
            <!-- Transaction manager for a single JDBC DataSource
            <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <property name="dataSource" ref="dataSource"/>
            </bean>
             -->
            <!--
            <bean id="attributeManager" class="com.ideawu.core.AttributeManager">
              <property name="dataSource" ref="dataSource"/>
            </bean>
            -->
          </beans>
          

          它配置了以下功能(不過,已經注釋掉了):

          • 配置數據庫連接. 類似${jbbc.url}是一種訪問變量的方法. 我們可以從 /WEB-INF/jdbc.properties 中找到這個變量的值. 如果你的數據庫已經配置好, 就將第一個注釋去掉.

          jdbc.properties:
          jdbc.driverClassName=com.mysql.jdbc.Driver
          jdbc.url=jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=UTF-8
          jdbc.username=root
          jdbc.password=root
          
          現在, 我們來編寫 Java 代碼吧.
           
          package com.ecnulxq.test;


          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;



          import org.springframework.web.servlet.ModelAndView;
          import org.springframework.web.servlet.mvc.Controller;



          /**
           * @author lxq ecnulxq@163.com
           * @version 創建時間:Oct 12, 2007 類說明
           *
           */
          public class HelloController implements Controller {



           public ModelAndView handleRequest(HttpServletRequest request,
             HttpServletResponse response) throws Exception {
            request.setAttribute("hello_1", "你好!Spring!");
            request.setAttribute("hello_2", "Hello!Spring!");
            return new ModelAndView("hello");
           }



          }


          return new ModelAndView("hello"); 告訴 InternalResourceViewResolver jsp 模板的名字叫作 hello. request.setAttribute() 設置的對象我們可以在 jsp 文件中使用.

          hello.jsp:

          <%@ page contentType="text/html; charset=UTF-8"%>
          <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
          <html xmlns="http://www.w3.org/1999/xhtml">
           <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <title>Hello World!</title>
           </head>
           <body>



            <h2>
             ${hello_1}
            </h2>



            <h2>
             ${hello_2}
            </h2>



           </body>
          </html>

          posted @ 2008-06-05 12:46 秋楓故事 閱讀(902) | 評論 (1)編輯 收藏

          JSTL詳解(一轉)

          7 Functions 標簽庫

                  稱呼 Functions 標簽庫為標簽庫,倒不如稱呼其為函數庫來得更容易理解些。因為 Functions 標簽庫并沒有提供傳統的標簽來為 JSP 頁面的工作服務,而是被用于 EL 表達式語句中。在 JSP2.0 規范下出現的 Functions 標簽庫為 EL 表達式語句提供了許多更為有用的功能。 Functions 標簽庫分為兩大類,共 16 個函數。

          長度函數: fn:length

          字符串處理函數: fn:contains 、 fn:containsIgnoreCase 、 fn:endsWith 、 fn:escapeXml 、 fn:indexOf 、 fn:join 、 fn:replace 、 fn:split 、 fn:startsWith 、 fn:substring 、 fn:substringAfter 、 fn:substringBefore 、 fn:toLowerCase 、 fn:toUpperCase 、 fn:trim

          以下是各個函數的用途和屬性以及簡單示例。

          9.7.1  長度函數 fn:length 函數

               長度函數 fn:length 的出現有重要的意義。在 JSTL1.0 中,有一個功能被忽略了,那就是對集合的長度取值。雖然 java.util.Collection 接口定義了 size 方法,但是該方法不是一個標準的 JavaBean 屬性方法(沒有 get,set 方法),因此,無法通過 EL 表達式“ ${collection.size} ”來輕松取得。

          fn:length 函數正是為了解決這個問題而被設計出來的。它的參數為 input ,將計算通過該屬性傳入的對象長度。該對象應該為集合類型或 String 類型。其返回結果是一個 int 類型的值。下面看一個示例。

          <%ArrayList arrayList1 = new ArrayList();

                                      arrayList1.add("aa");

                                      arrayList1.add("bb");

                                      arrayList1.add("cc");

          %>

          <%request.getSession().setAttribute("arrayList1", arrayList1);%>

          ${fn:length(sessionScope.arrayList1)}

          假設一個 ArrayList 類型的實例“ arrayList1 ”,并為其添加三個字符串對象,使用 fn:length 函數后就可以取得返回結果為“ 3 ”。

          9.7.2  判斷函數 fn:contains 函數

          fn:contains 函數用來判斷源字符串是否包含子字符串。它包括 string 和 substring 兩個參數,它們都是 String 類型,分布表示源字符串和子字符串。其返回結果為一個 boolean 類型的值。下面看一個示例。

          ${fn:contains("ABC", "a")}<br>

          ${fn:contains("ABC", "A")}<br>

          前者返回“ false ”,后者返回“ true ”。

          9.7.3 fn:containsIgnoreCase 函數

          fn:containsIgnoreCase 函數與 fn:contains 函數的功能差不多,唯一的區別是 fn:containsIgnoreCase 函數對于子字符串的包含比較將忽略大小寫。它與 fn:contains 函數相同,包括 string 和 substring 兩個參數,并返回一個 boolean 類型的值。下面看一個示例。

          ${fn:containsIgnoreCase("ABC", "a")}<br>

          ${fn:containsIgnoreCase("ABC", "A")}<br>

          前者和后者都會返回“ true ”。

          9.7.4  詞頭判斷函數 fn:startsWith 函數

          fn:startsWith 函數用來判斷源字符串是否符合一連串的特定詞頭。它除了包含一個 string 參數外,還包含一個 subffx 參數,表示詞頭字符串,同樣是 String 類型。該函數返回一個 boolean 類型的值。下面看一個示例。

          ${fn:startsWith ("ABC", "ab")}<br>

          ${fn:startsWith ("ABC", "AB")}<br>

          前者返回“ false ”,后者返回“ true ”。

          9.7.5  詞尾判斷函數 fn:endsWith 函數

          fn:endsWith 函數用來判斷源字符串是否符合一連串的特定詞尾。它與 fn:startsWith 函數相同,包括 string 和 subffx 兩個參數,并返回一個 boolean 類型的值。下面看一個示例。

          ${fn:endsWith("ABC", "bc")}<br>

          ${fn:endsWith("ABC", "BC")}<br>

          前者返回“ false ”,后者返回“ true ”。

          9.7.6  字符實體轉換函數 fn:escapeXml 函數

          fn:escapeXml 函數用于將所有特殊字符轉化為字符實體碼。它只包含一個 string 參數,返回一個 String 類型的值。

          9.7.8  字符匹配函數 fn:indexOf 函數

          fn:indexOf 函數用于取得子字符串與源字符串匹配的開始位置,若子字符串與源字符串中的內容沒有匹配成功將返回“ -1 ”。它包括 string 和 substring 兩個參數,返回結果為 int 類型。下面看一個示例。

          ${fn:indexOf("ABCD","aBC")}<br>

          ${fn:indexOf("ABCD","BC")}<br>

          前者由于沒有匹配成功,所以返回 -1 ,后者匹配成功將返回位置的下標,為 1 。

          posted @ 2008-06-05 09:49 秋楓故事 閱讀(224) | 評論 (0)編輯 收藏

          hibernate二級緩存的實現

               摘要: 對于Hibernate這類ORM而言,緩存顯的尤為重要,它是持久層性能提升的關鍵.簡單來講Hibernate就是對JDBC進行封裝,以實現內部狀態的管理,OR關系的映射等,但隨之帶來的就是數據訪問效率的降低,和性能的下降,而緩存就是彌補這一缺點的重要方法.     緩存就是數據庫數據在內存中的臨時容器,包括數據庫數據在內存中的臨時拷貝,它位于數據庫與數...  閱讀全文

          posted @ 2008-04-16 18:17 秋楓故事 閱讀(1761) | 評論 (1)編輯 收藏

          深入淺出SQL教程之Group By和Having

          在介紹GROUP BY 和 HAVING 子句前,我們必需先講講sql語言中一種特殊的函數:聚合函數,例如SUM, COUNT, MAX, AVG等。這些函數和其它函數的根本區別就是它們一般作用在多條記錄上。 

          SELECT SUM(population) FROM bbc 

          這里的SUM作用在所有返回記錄的population字段上,結果就是該查詢只返回一個結果,即所有國家的總人口數。 

          通過使用GROUP BY 子句,可以讓SUM 和 COUNT 這些函數對屬于一組的數據起作用。當你指定 GROUP BY region 時, 屬于同一個region(地區)的一組數據將只能返回一行值,也就是說,表中所有除region(地區)的字段,只能通過 SUM, COUNT等聚合函數運算后返回一個值。  HAVING子句可以讓我們篩選成組后的各組數據,WHERE子句在聚合前先篩選記錄.也就是說作用在GROUP BY 子句和HAVING子句前,而 HAVING子句在聚合后對組記錄進行篩選。 

          讓我們還是通過具體的實例來理解GROUP BY 和 HAVING 子句,還采用第三節介紹的bbc表。 

          SQL實例: 

          一、顯示每個地區的總人口數和總面積: 

          SELECT region, SUM(population), SUM(area)

          FROM bbc

          GROUP BY region

           

          先以region把返回記錄分成多個組,這就是GROUP BY的字面含義。分完組后,然后用聚合函數對每組中的不同字段(一或多條記錄)作運算。 

          二、 顯示每個地區的總人口數和總面積.僅顯示那些面積超過1000000的地區。 

          SELECT region, SUM(population), SUM(area)

          FROM bbc

          GROUP BY region

          HAVING SUM(area)>1000000

           

          在這里,我們不能用where來篩選超過1000000的地區,因為表中不存在這樣一條記錄。 

          相反,HAVING子句可以讓我們篩選成組后的各組數據。


          group by分組統計SQL語句(實例)

          用一條查詢語句,查出各姓名的數值余額.

          用戶表:
          姓名
          a
          b
          c
          ....

          扣費表:
          姓名 數值
          a 3.5
          b 5.2
          a 2
          ...

          充值表:
          姓名 數值
          b 10
          a 10
          a 10.5
          ...

          返回:
          姓名 差額(充值和-扣費和)

          測試通過

          select table1.TNAME,table1.TelName, (table3.充值-table2.扣費) as 差額
          from 用戶表 table1,(select TelName,sum(TelQryh)as 扣費 from 扣費表 group by TelName)table2,
          (select TelName,sum(TelQryc)as 充值 from 充值表 group by TelName)table3 where
          table1.TelName=table2.TelName and table1.TelName=table3.TelName

          posted @ 2008-04-12 19:32 秋楓故事 閱讀(144) | 評論 (0)編輯 收藏

          (轉)Struts Spring Hibernate 整合報空指針解決方法

          最近一直在弄WebWork,Struts都快忘了。今天又自己小試了一下SSH,結果每次都是報空指針異常,經過一番研究,發現,如果不把action的type改成

          org.springframework.web.struts.DelegatingActionProxy

          的話,就會報這個

          java.lang.NullPointerException

           com.test.struts.action.UserAction.show(UserAction.java:46)
          sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
          sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
          java.lang.reflect.Method.invoke(Method.java:597)
          org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:274)
          org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:194)
          org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:419)
          org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224)
          org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194)
          org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
          javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
          javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
          解決辦法:
          1.在struts-config.xml的action把type改成org.springframework.web.struts.DelegatingActionProxy,例如:
          <action attribute="userForm" input="/index.jsp" name="userForm"
                    parameter="param" path="/user" scope="request"
                    type="org.springframework.web.struts.DelegatingActionProxy"
                    validate="false">
                    <forward name="success" path="/success.jsp" />
          </action>
          2.在spring的配置文件(applicationContext.xml)里添加一些代碼:
          <bean id="transactionManager"
                   class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                   <property name="sessionFactory">
                    <ref bean="sessionFactory" />
                   </property>
          </bean>
          給DAO加上代理
          <bean id="UserDAOIProxy"
                   class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                   <property name="transactionManager">
                    <ref bean="transactionManager" />
                   </property>
                   <property name="target">
                    <ref bean="UserDao" />
                   </property>
                   <property name="transactionAttributes">
                    <props>
                     <prop key="create*">PROPAGATION_REQUIRED</prop>
                     <prop key="update*">PROPAGATION_REQUIRED</prop>
                     <prop key="delete*">PROPAGATION_REQUIRED</prop>
                     <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                    </props>
                   </property>
          </bean>
          3.更改Service的引用
           <bean name="UserService"
                   class="com.test.service.impl.UserServiceImpl">
                   <property name="userDao">
                    <ref bean="
          UserDAOIProxy" />
                   </property>
          </bean>
          這樣就不會報那個異常了,測試通過^_^
          我的配置文件代碼:
          applicationContext.xml
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
          <beans>
          <bean id="dataSource"
                   class="org.apache.commons.dbcp.BasicDataSource">
                   <property name="driverClassName"
                    value="oracle.jdbc.driver.OracleDriver">
                   </property>
                   <property name="url"
                    value="jdbc:oracle:thin:@192.192.192.19:1521:orcl">
                   </property>
                   <property name="username" value="sunyu"></property>
                   <property name="password" value="19830317"></property>
          </bean>
          <bean id="sessionFactory"
                   class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                   <property name="dataSource">
                    <ref bean="dataSource" />
                   </property>
                   <property name="hibernateProperties">
                    <props>
                     <prop key="hibernate.dialect">
                      org.hibernate.dialect.Oracle9Dialect
                     </prop>
                     <prop key="hibernate.show_sql">true</prop>
                    </props>
                   </property>
                   <property name="mappingResources">
                    <list>
                     <value>com/test/model/TestUser.hbm.xml</value>
                    </list>
                   </property>
          </bean>
          <bean id="transactionManager"
                   class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                   <property name="sessionFactory">
                    <ref bean="sessionFactory" />
                   </property>
          </bean>
          <bean name="UserDao" class="com.test.dao.impl.UserDaoImpl">
                   <property name="sessionFactory">
                    <ref bean="sessionFactory" />
                   </property>
          </bean>
          <bean id="UserDAOIProxy"
                   class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                   <property name="transactionManager">
                    <ref bean="transactionManager" />
                   </property>
                   <property name="target">
                    <ref bean="UserDao" />
                   </property>
                   <property name="transactionAttributes">
                    <props>
                     <prop key="create*">PROPAGATION_REQUIRED</prop>
                     <prop key="update*">PROPAGATION_REQUIRED</prop>
                     <prop key="delete*">PROPAGATION_REQUIRED</prop>
                     <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                    </props>
                   </property>
          </bean>
          <bean name="UserService"
                   class="com.test.service.impl.UserServiceImpl">
                   <property name="userDao">
                    <ref bean="UserDAOIProxy" />
                   </property>
          </bean>
          <bean name="/user" class="com.test.struts.action.UserAction">
                   <property name="userService">
                    <ref bean="UserService" />
                   </property>
          </bean>
          </beans>
          struts-config.xml
          <?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
          ">
          <struts-config>
          <data-sources />
          <form-beans>
                   <form-bean name="userForm" type="com.test.struts.form.UserForm" />
          </form-beans>
          <global-exceptions />
          <global-forwards />
          <action-mappings>
                   <action attribute="userForm" input="/index.jsp" name="userForm"
                    parameter="param" path="/user" scope="request"
                    type="org.springframework.web.struts.DelegatingActionProxy"
                    validate="false">
                    <forward name="success" path="/success.jsp" />
                   </action>
          </action-mappings>
          <message-resources parameter="com.test.struts.ApplicationResources" />
          <plug-in
                   className="org.springframework.web.struts.ContextLoaderPlugIn">
                   <set-property property="contextConfigLocation"
                    value="/WEB-INF/applicationContext.xml" />
          </plug-in>

          </struts-config>



          ------------------------------------------
          第二種方法,如果在struts-config.xml里面加上

          <controller>
          <set-property property="processorClass"
          value="org.springframework.web.struts.DelegatingRequestProcessor" />
          </controller>

          這樣action就不需要type屬性了
          ----------------------------------------------

          posted @ 2008-04-03 19:14 秋楓故事 閱讀(2444) | 評論 (0)編輯 收藏

          (轉)jboss部署ejb

          開發sessionbean EJB最少也需要三個class,remote interface,home interface,and bean implementation(bean行為).

          1. remote interface 用來揭示EJB對外的一些方法.

          package helloWorld; import javax.ejb.EJBObject;
          import java.rmi.RemoteException;
          public interface RemoteHello extends EJBObject
          { public String HelloEcho(String inputString) throws RemoteException; }
          2.home interface 是用來規定怎樣創建一個實現remote interface的bean.
          package helloWorld;
          import java.io.Serializable;
          import java.rmi.RemoteException;
          import javax.ejb.CreateException;
          import javax.ejb.EJBHome;
          public interface HomeHello extends EJBHome

          { RemoteHello create() throws RemoteException, CreateException; }

          3.bean implementation 是提供方法的實現,這些方法在上述兩種interface中都有規定了.

          package helloWorld;

          import java.rmi.RemoteException;

          import javax.ejb.SessionBean;

          import javax.ejb.SessionContext;

          public class HelloBean implements SessionBean{

             public String HelloEcho(String inputString) {

               System.out.println("Someone called 'Hello Echo Successed!'");

               return "*********" + inputString + "*********"; }

               /** Empty method body  */

               public void ejbCreate() {

                  System.out.println("Ejb 4 is creating!...");}

               /** Every ejbCreate() method ALWAYS needs a corresponding   ejbPostCreate () method with exactly the same parameter types.   */

          public void ejbPostCreate() {}

          /** Empty method body   */

          public void ejbRemove() {

              System.out.println("Ejb 4 is removing!...");}

           /** Empty method body */

          public void ejbActivate() {

             System.out.println("Ejb 4 is activating!...");}

          /** Empty method body */

          public void ejbPassivate()

           {}

          /** Empty method body   */

          public void setSessionContext(SessionContext sc)

           {}

          }

          部署jar

          這些classes必須打包進一個JAR文件中,JAR文件中包含了目錄結構和包的層次.在本例中, 這些classes是在包helloworld,這樣他們需要在目錄helloWorld/ 下.

          部署發布描述器ejb-jar.XML和jboss.xml
          在JAR文檔創建之前,還需要一個叫META-INF的目錄,這是存放部署發布描述器的(一般叫ejb-jar.xml).

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD EntERPrise JavaBeans 2.0//EN" "
          http://java.sun.com/dtd/ejb-jar_2_0.dtd">
          <ejb-jar>
           <description>Neosue Helloworld Sample Application</description>
           <display-name>Helloworld EJB</display-name>
           <enterprise-beans>
            <session>
             <ejb-name>Helloworld</ejb-name>
             <!-- home interface -->
             <home>helloWorld.HomeHello</home>
             <!-- remote interface -->
             <remote>helloWorld.RemoteHello</remote>
             <!-- bean implementation -->
             <ejb-class>helloWorld.HelloBean</ejb-class>
             <session-type>Stateless</session-type>
             <transaction-type>Bean</transaction-type>
            </session>
           </enterprise-beans>
          </ejb-jar>

          jboss.xml

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 4.0//EN" "
          http://www.jboss.org/j2ee/dtd/jboss_4_0.dtd">
          <jboss>
           <enterprise-beans>
            <session>
             <ejb-name>Helloworld</ejb-name>
             <jndi-name>Helloworld/Hello</jndi-name>
            </session>
           </enterprise-beans>
          </jboss>
          雖然有了上面你的應用程序和JNDI name的梆定,但是一旦部署發布到JBoss服務器上,你還需要一個jndi.properties文件,以告訴調用你程序的客戶端請求到哪里去初始化JNDI naming service.

          測試程序:

          import javax.naming.Context;

          import javax.naming.InitialContext;

          import javax.rmi.PortableRemoteObject;

          import helloWorld.*;

          public class MyTest {

             public static void main(String[] args) {

                try{ Context ctx=new InitialContext();

                     Object ref=ctx.lookup("Helloworld/Hello");

                     HomeHello home=(HomeHello)PortableRemoteObject.narrow(ref,HomeHello.class);

                     RemoteHello user=home.create(); System.out.println(user.HelloEcho("So easy!"));

                  }catch(Exception e) {

                    e.printStackTrace();

                  }

             }

          }

          Jboss EJB 部署步驟 建立 remote interface-->home interface-->and bean implementation--> ejb-jar.xml-->jboss.xml--打包(package[jar cvf packageName.jar .])-->復制到jboss deploy目錄.

          ---------------------------------------------------------
          原文 URL
          http://blog.blogchina.com/refer.159508.html
          ---------------------------------------------------------
          補充說明如下:

          OS: windows 2000;
          JDK: 1.5.0rc;
          JBoss: 4.0

          HelloWorld.jar
          |--META-INF
          |      |--jboss.xml
          |      |--ejb-jar.xml
          |      |--MANIFEST.MF (自動生成)
          |--helloWorld
                 |--RemoteHello.class
                 |--jndi.properties
                 |--HomeHello.class
                 |--HelloBean.class


          其中 測試文件 MyTest.class 同目錄拷貝一份 jndi.properties 文件過來.

          jndi.properties 的內容如下:

          java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
          java.naming.provider.url=localhost:1099
          java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

          posted @ 2008-03-30 19:38 秋楓故事 閱讀(1054) | 評論 (0)編輯 收藏

          ( 轉)重寫自已的HashCode()方法

           大家都知道,在Java里對對象的操作是基于引用的。而當我們需要對一組對象操作的時候,  就需要有接收這一組引用的容器。平時我們最常用的就是數組。在Java里可以定義一個對象數組來完成許多操作。可是,數組長度是固定的,如果我們需要更 加靈活的解決方案該怎么辦呢?

                 Java提供了container  classes來解決這一問題。container  classes包括兩個部分:Collection和Map。

          它們的結構是這樣的: 

                 本文重點介紹HashMap。首先介紹一下什么是Map。在數組中我們是通過數組下標來對其內容索引的,  而在Map中我們通過對象來對對象進行索引,用來索引的對象叫做key,其對應的對象叫做value。  在下文中會有例子具體說明。

                 再來看看HashMap和TreeMap有什么區別。HashMap通過hashcode對其內容進行快速查找,而TreeMap中所有的元素都保持著 某種固定的順序,如果你需要得到一個有序的結果你就應該使用TreeMap(HashMap中元素的排列順序是不固定的)。

          下面就要進入本文的主題了。先舉個例子說明一下怎樣使用HashMap:













          程序代碼:
          import java.util.*; 
          public class Exp1 { 
               public static void main(String[] args){ 
                    HashMap h1=new HashMap(); 
                    Random r1=new Random();     
                    for(int i=0;i< 1000;i++){ 
                         Integer t=new Integer(r1.nextInt(20)); 
                         if(h1.containsKey(t)) 
                              ((Ctime)h1.get(t)).count++; 
                         else 
                              h1.put(t, new Ctime()); 
                    } 
                    System.out.println(h1); 
               } 

          class Ctime{ 
               int count=1; 
               public String toString(){ 
                    return Integer.toString(count); 
               } 


                     在HashMap中通過get()來獲取value,通過put()來插入value,ContainsKey()則用來檢驗對象是否已經存在。可以看 出,和ArrayList的操作相比,HashMap除了通過key索引其內容之外,別的方面差異并不大。

                   前面介紹了,HashMap是基于HashCode的,在所有對象的超類Object中有一個HashCode()方法,  但是它和equals方法一樣,并不能適用于所有的情況,這樣我們就需要重寫自己的HashCode()方法。
          下面就舉這樣一個例子:













          程序代碼:
          import java.util.*; 
          public class Exp2 { 
               public static void main(String[] args){ 
                    HashMap h2=new HashMap(); 
                    for(int i=0;i< 10;i++) 
                         h2.put(new Element(i), new Figureout()); 
                    System.out.println("h2:"); 
                    System.out.println("Get the result for Element:"); 
                    Element test=new Element(5); 
                    if(h2.containsKey(test)) 
                         System.out.println((Figureout)h2.get(test)); 
                    else 
                         System.out.println("Not found"); 
               } 

          class Element{ 
               int number; 
               public Element(int n){ 
                    number=n; 
               } 

          class Figureout{ 
               Random r=new Random(); 
               boolean possible=r.nextDouble()>0.5; 
               public String toString(){ 
                    if(possible) 
                         return "OK!"
                    else 
                         return "Impossible!"
               } 

           
                 在這個例子中,Element用來索引對象Figureout,也即Element為key,Figureout為value。  在Figureout中隨機生成一個浮點數,如果它比0.5大,打印“OK!”,否則打印“Impossible!”。  之后查看Element(5)對應的Figureout結果如何。  

                 結果卻發現,無論你運行多少次,得到的結果都是“Not  found”。也就是說索引Element(5)并不在HashMap中。這怎么可能呢?

                 原因得慢慢來說:Element的HashCode方法繼承自Object,而Object中的HashCode方法返回的HashCode對應于當前 的地址,也就是說對于不同的對象,即使它們的內容完全相同,用HashCode()返回的值也會不同。這樣實際上違背了我們的意圖。因為我們在使用 HashMap時,  希望利用相同內容的對象索引得到相同的目標對象,這就需要HashCode()在此時能夠返回相同的值。

                 在上面的例子中,我們期望new  Element(i)  (i=5)與  Element  test=new  Element(5)是相同的,  而實際上這是兩個不同的對象,盡管它們的內容相同,但它們在內存中的地址不同。因此很自然的,  上面的程序得不到我們設想的結果。下面對Element類更改如下:













          程序代碼:
          class Element{ 
            int number; 
            public Element(int n){ 
              number=n; 
           } 
            public int hashCode(){ 
             return number; 
            } 
            public boolean equals(Object o){ 
             return (o instanceof Element) && (number==((Element)o).number); 
            } 


                     在這里Element覆蓋了Object中的hashCode()和equals()方法。覆蓋hashCode()使其以number的值作為 hashcode返回,這樣對于相同內容的對象來說它們的hashcode也就相同了。而覆蓋equals()是為了在HashMap判斷兩個key是否 相等時使結果有意義(有關重寫equals()的內容可以參考我的另一篇文章《重新編寫Object類中的方法  》)。修改后的程序運行結果如下:

          h2:  
          Get  the  result  for  Element:  
          Impossible!  

          請記住:如果你想有效的使用HashMap,你就必須重寫在其的HashCode()。

          還有兩條重寫HashCode()的原則:

                 不必對每個不同的對象都產生一個唯一的hashcode,只要你的HashCode方法使get()能夠得到put()放進去的內容就可以了。即“不為 一原則”。  生成hashcode的算法盡量使hashcode的值分散一些,  不要很多hashcode都集中在一個范圍內,這樣有利于提高HashMap的性能。即“分散原則”。  至于第二條原則的具體原因,有興趣者可以參考Bruce  Eckel的《Thinking  in  Java》,
          在那里有對HashMap內部實現原理的介紹,這里就不贅述了。

                 掌握了這兩條原則,你就能夠用好HashMap編寫自己的程序了。不知道大家注意沒有,  java.lang.Object中提供的三個方法:clone(),equals()和hashCode()雖然很典型,  但在很多情況下都不能夠適用,它們只是簡單的由對象的地址得出結果。  這就需要我們在自己的程序中重寫它們,其實java類庫中也重寫了千千萬萬個這樣的方法。  利用面向對象的多態性——覆蓋,Java的設計者很優雅的構建了Java的結構,也更加體現了Java是一門純OOP語言的特性。

               Java提供的Collection和Map的功能是十分強大的,它們能夠使你的程序實現方式更為靈活,  執行效率更高。希望本文能夠對大家更好的使用HashMap有所幫助。

          posted @ 2008-03-28 11:17 秋楓故事 閱讀(251) | 評論 (0)編輯 收藏

          產生對象個數問題

          String a = "hello";
          String b = "world";
          String c = "ok";
          String d = "is";
          String result = a+b+c+d;
          問:共產生多少個對象?

          答:
          現在的編譯器早就對這些代碼作了優化,編譯成如下:
          String a = "hello";
          String b = "world";
          String c = "ok";
          String d = "is";
          String result = new StringBuffer().append(a),append(b),append(c).append(d).toString();
          因此產生了6個對象,其中5個字符串對象,一個StringBuffer臨時對象。

          posted @ 2008-03-28 10:39 秋楓故事 閱讀(311) | 評論 (0)編輯 收藏

          java 文件操作(拷貝一個文件)

          try
          {

            BufferedReader in = new BufferedReader(new FileReader("c:\\1.txt"));
            PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter("c:\\2.txt")),true);
            String tmp = "";
            while((tmp=in.readLine()) != null)
            {
              writer.println(tmp);
            }
            writer.close();
            in.close();
          }
          catch(Exception e)
          {
          e.printStackTrace();
          }

          posted @ 2008-03-25 22:35 秋楓故事 閱讀(359) | 評論 (0)編輯 收藏

          [轉] 解析oracle的ROWNUM

          對于rownum來說它是oracle系統順序分配為從查詢返回的行的編號,返回的第一行分配的是1,第二行是2,依此類推,這個偽字段可以用于限制查詢返回的總行數,而且rownum不能以任何表的名稱作為前綴。
           舉例說明:
          例如表:student(學生)表,表結構為:
          ID       char(6)      --學號
          name    VARCHAR2(10)   --姓名
          create table student (ID char(6), name VARCHAR2(100));
          insert into sale values('200001',‘張一’);
          insert into sale values('200002',‘王二’);
          insert into sale values('200003',‘李三’);
          insert into sale values('200004',‘趙四’);
          commit;

          (1) rownum 對于等于某值的查詢條件
          如果希望找到學生表中第一條學生的信息,可以使用rownum=1作為條件。但是想找到學生表中第二條學生的信息,使用rownum=2結果查不到數據。因為rownum都是從1開始,但是1以上的自然數在rownum做等于判斷是時認為都是false條件,所以無法查到rownum = n(n>1的自然數)。
          SQL> select rownum,id,name from student where rownum=1;(可以用在限制返回記錄條數的地方,保證不出錯,如:隱式游標)
          SQL> select rownum,id,name from student where rownum=1;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
                   1 200001 張一
          SQL> select rownum,id,name from student where rownum =2;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------

          (2)rownum對于大于某值的查詢條件
             如果想找到從第二行記錄以后的記錄,當使用rownum>2是查不出記錄的,原因是由于rownum是一個總是從1開始的偽列,Oracle 認為rownum> n(n>1的自然數)這種條件依舊不成立,所以查不到記錄
          SQL> select rownum,id,name from student where rownum >2;
          ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
          那如何才能找到第二行以后的記錄呀。可以使用以下的子查詢方法來解決。注意子查詢中的rownum必須要有別名,否則還是不會查出記錄來,這是因為rownum不是某個表的列,如果不起別名的話,無法知道rownum是子查詢的列還是主查詢的列。
          SQL>select * from(select rownum no ,id,name from student) where no>2;
                  NO ID     NAME
          ---------- ------ ---------------------------------------------------
                   3 200003 李三
                   4 200004 趙四
          SQL> select * from(select rownum,id,name from student)where rownum>2;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------

          (3)rownum對于小于某值的查詢條件
          如果想找到第三條記錄以前的記錄,當使用rownum<3是能得到兩條記錄的。顯然rownum對于rownum<n((n>1的自然數)的條件認為是成立的,所以可以找到記錄。
          SQL> select rownum,id,name from student where rownum <3;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
                  1 200001 張一
                  2 200002 王二
          綜上幾種情況,可能有時候需要查詢rownum在某區間的數據,那怎么辦呀從上可以看出rownum對小于某值的查詢條件是人為true的,rownum對于大于某值的查詢條件直接認為是false的,但是可以間接的讓它轉為認為是true的。那就必須使用子查詢。例如要查詢rownum在第二行到第三行之間的數據,包括第二行和第三行數據,那么我們只能寫以下語句,先讓它返回小于等于三的記錄行,然后在主查詢中判斷新的rownum的別名列大于等于二的記錄行。但是這樣的操作會在大數據集中影響速度。
          SQL> select * from (select rownum no,id,name from student where rownum<=3 ) where no >=2;
                  NO ID     NAME
          ---------- ------ ---------------------------------------------------
                   2 200002 王二
                   3 200003 李三

          (4)rownum和排序
          Oracle中的rownum的是在取數據的時候產生的序號,所以想對指定排序的數據去指定的rowmun行數據就必須注意了。
          SQL> select rownum ,id,name from student order by name;
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
                   3 200003 李三
                   2 200002 王二
                   1 200001 張一
                   4 200004 趙四
          可以看出,rownum并不是按照name列來生成的序號。系統是按照記錄插入時的順序給記錄排的號,rowid也是順序分配的。為了解決這個問題,必須使用子查詢
          SQL> select rownum ,id,name from (select * from student order by name);
              ROWNUM ID     NAME
          ---------- ------ ---------------------------------------------------
                   1 200003 李三
                   2 200002 王二
                   3 200001 張一
                   4 200004 趙四
          這樣就成了按name排序,并且用rownum標出正確序號(有小到大)
          筆者在工作中有一上百萬條記錄的表,在jsp頁面中需對該表進行分頁顯示, 便考慮用rownum來作,下面是具體方法(每頁
          顯示20條):
            “select * from tabname where rownum<20 order by name" 但卻發現oracle卻不能按自己的意愿來執行,而是先隨便
          取20條記錄,然后再 order by,后經咨詢oracle,說rownum確實就這樣,想用的話,只能用子查詢 來實現先排序,后
          rownum,方法如下:
            "select * from (select * from tabname order by name) where  rownum<20",但這樣一來,效率會較低很多。
            后經筆者試驗,只需在order by 的字段上加主鍵或索引即可讓oracle先按 該字段排序,然后再rownum;方法不變:
             “select * from tabname where rownum<20 order by name"

          取得某列中第N大的行

          select column_name from
          (select table_name.*,dense_rank() over (order by column desc) rank from table_name)
          where rank = &N;
           假如要返回前5條記錄:

            select * from tablename where rownum<6;(或是rownum <= 5 或是rownum != 6)
          假如要返回第5-9條記錄:

          select * from tablename
          where …
          and rownum<10
          minus
          select * from tablename
          where …
          and rownum<5
          order by name
          選出結果后用name排序顯示結果。(先選再排序)

          注意:只能用以上符號(<、<=、!=)。

          select * from tablename where rownum != 10;返回的是前9條記錄。
          不能用:>,>=,=,Between...and。由于rownum是一個總是從1開始的偽列,Oracle 認為這種條件 不成立,查不到記錄.

          另外,這個方法更快:

          select * from (
          select rownum r,a from yourtable
          where rownum <= 20
          order by name )
          where r > 10
          這樣取出第11-20條記錄!(先選再排序再選)

          要先排序再選則須用select嵌套:內層排序外層選。
          rownum是隨著結果集生成的,一旦生成,就不會變化了;同時,生成的結果是依次遞加的,沒有1就永遠不會有2!
          rownum 是在 查詢集合產生的過程中產生的偽列,并且如果where條件中存在 rownum 條件的話,則:

          1: 假如 判定條件是常量,則:
          只能 rownum = 1, <= 大于1 的自然數, = 大于1 的數是沒有結果的, 大于一個數也是沒有結果的
          即 當出現一個 rownum 不滿足條件的時候則 查詢結束   this is stop key!

          2: 當判定值不是常量的時候
          若條件是 = var , 則只有當 var 為1 的時候才滿足條件,這個時候不存在 stop key ,必須進行 full scan ,對每個滿足其他where條件的數據進行判定
          選出一行后才能去選rownum=2的行…… 

          posted @ 2008-03-24 19:35 秋楓故事 閱讀(176) | 評論 (0)編輯 收藏

          僅列出標題
          共5頁: 上一頁 1 2 3 4 5 下一頁 
          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導航

          統計

          • 隨筆 - 63
          • 文章 - 0
          • 評論 - 14
          • 引用 - 0

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          新聞檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 南丰县| 法库县| 台南市| 谢通门县| 牡丹江市| 宜兴市| 华宁县| 富宁县| 乐业县| 昭觉县| 仪陇县| 余姚市| 沙雅县| 福鼎市| 五常市| 平谷区| 云龙县| 苍南县| 清涧县| 南昌县| 宜州市| 社会| 罗源县| 疏附县| 永城市| 青铜峡市| 晋中市| 图们市| 宝丰县| 大英县| 龙山县| 桂东县| 开阳县| 潜江市| 思南县| 成武县| 新乡市| 兰坪| 鄂州市| 广灵县| 醴陵市|