解析MVC模式 (轉(zhuǎn)載)

               摘要: MVC 模式概述       MVC 是三個單詞的縮寫 , 分別為:      模型 (Model), 視圖 (View) 和控制 Controller) 。    ...  閱讀全文

          posted @ 2006-06-12 11:55 nbt 閱讀(428) | 評論 (0)編輯 收藏

          對Servlet的初始化的理解

          版權(quán)所有,轉(zhuǎn)載請聲明出處 zhyiwww@163.com

          在讀我自己的認(rèn)識之前 , 我們先來看一下 servet 的結(jié)構(gòu)圖 :

          servlet.png
          以下是我自己的一點淺見:

          ①  Servlet 在初始化的時候 , 是通過 init(ServletConfig? config) init() 來執(zhí)行的。

          ServletConfig 是一個接口,它怎樣傳遞給他一格對象來進(jìn)行初始化呢?其實,是這個對象是由 servlet 容器來實例化的,由容器產(chǎn)生一格 ServletConfig 的實現(xiàn)類的對象,然后傳遞給 Servlet

          結(jié)論: ServletConfig 由容器實例化

          ②  我們有些時候可能在 Servlet 初始化時給它一些固定的配置參數(shù),那么這些參數(shù)是怎樣傳遞到 Servlet 呢?

          其實,我們在 web.xml 中給 servlet 配置啟動參數(shù),在容器對 servlet 進(jìn)行初始化的時候,會收集你所配置的參數(shù),記錄在 ServletConfig 的實現(xiàn)類中,所以你才可以通過 ServletConfig 對象的

          ??? public String getInitParameter(String name);

          ??? public Enumeration getInitParameterNames();

          方法來取得你已經(jīng)配置好的參數(shù),也就是說,你對 servlet 的配置都已經(jīng)記錄在 ServletConfig 對象中了。

          結(jié)論:你對 Servlet 的配置,在 Servlet 的初始化時都由容器來收集并且記錄到 ServletConfig 的實現(xiàn)類中。

          ?

          ③  我們來看一個 Servlet 的配置

          ? <servlet>

          ??? <servlet-name>index</servlet-name>

          ??? <servlet-class>org.zy.pro.sw.servlet.IndexServlet</servlet-class>

          ??? <init-param>

          ????? <param-name>dbconfig</param-name>

          ????? <param-value>/WEB-INF/dbconfig.xml</param-value>

          ??? </init-param>

          ? </servlet>

          在此,我們實現(xiàn)對數(shù)據(jù)庫的配置文件的加載。

          當(dāng) Servlet 初始化完成后,我們可以通過

          String? dbconf=this.getServletConfig().getInitParameter("dbconfig")

          來取得我們的配置的參數(shù)的值。

          但是,我們僅能得到一個配置的字符串。之后我們可以通過配置文件取得我們的數(shù)據(jù)庫的配置參數(shù),然后對數(shù)據(jù)庫進(jìn)行初始化。

          其實我們也可以通過傳遞一個類的名字串,然后再實例化。

          ??? <init-param>

          ????? <param-name>dbconfig</param-name>

          ????? <param-value>org.zy.util.db.DBUtil</param-value>

          ?? ?</init-param>

          我們先取得配置參數(shù):

          String? dbconf=this.getServletConfig().getInitParameter("dbconfig")

          然后通過

          Class.forName(dbconf).getInstance();

          來實例化對象,就可以實現(xiàn)對數(shù)據(jù)庫的調(diào)用了。

          結(jié)論:在 web.xml 中對 Servlet 的初始化,只能傳遞字符串類型的數(shù)據(jù)

          ④  ServletContext

          ServletContext 是負(fù)責(zé)和 Servlet 的上文和下文交互,上面和 Servlet 容器交互,下面和 Servlet 中的請求和相應(yīng)進(jìn)行交互。

          ServletConfig 中, ???

          public ServletContext getServletContext(); 方法實現(xiàn)取得當(dāng)前 ServletContext 的對象。

          你可能要問, ServletContext 是一個接口,那么你如何取得他的對象呢?

          其實這個問題和 ServletConfig 相同,都是在 Servlet 進(jìn)行初始化的時候產(chǎn)生的對象,是由容器來初始化的。

          posted @ 2006-06-12 11:53 nbt 閱讀(312) | 評論 (0)編輯 收藏

          ant+cactus+tomcat5.5容器內(nèi)單元測試簡明手冊

          摘要:

          折騰了一個星期,終于搞定ant+cactus+tomcat5.5容器內(nèi)單元測試,為感謝cleverpig斑竹的熱心回貼,特首發(fā)于matrix apache版。
          折騰了一個星期,終于搞定ant+cactus+tomcat5.5容器內(nèi)單元測試,為感謝cleverpig斑竹(http://blog.matrix.org.cn/page/cleverpig)的熱心回貼,特首發(fā)于matrix apache版。關(guān)于ant的使用,請搜索ant的使用手冊,網(wǎng)上大把中文的。

          一、下載并解壓縮cactus
          下載地址為http://apache.freelamp.com/jakarta/cactus/binaries/jakarta-cactus-12-1.7.1.zip。將cactus的lib目錄下的cactus-ant-1.7.1.jar復(fù)制到ant的lib目錄。


          二、配置cactus
          cactus的配置很簡單,新建一個cactus.properties文件,并把它放在ant腳本中的cactus任務(wù)的classpath下,文件中包括如下內(nèi)容
          cactus.sysproperties=cactus.contextURL
          #cactus-sample-servlet-cactified就是你的測試應(yīng)用所在路徑,8080是端口號
          cactus.contextURL = http://localhost:8080/cactus-sample-servlet-cactified
          cactus.servletRedirectorName = ServletRedirector
          cactus.jspRedirectorName = JspRedirector
          cactus.filterRedirectorName = FilterRedirector

          具體的做法結(jié)合ant腳本再進(jìn)一步解釋。

          三、運行ant腳本
          ??ant腳本主要執(zhí)行以下任務(wù)

          1、設(shè)定classpath
          ????
          <path id="project.classpath">
          ????????<fileset dir="${lib.dir}">
          ?????????? <include name="*.jar"/>
          ????????</fileset>
          ????????<!-- cactus.properties文件就需要放在lib.dir所對應(yīng)的路徑中 -->
          ????????<pathelement location="${lib.dir}"/>
          ????????<pathelement location="${tomcat.home}/common/lib/jsp-api.jar"/>
          ????????<pathelement location="${tomcat.home}/common/lib/servlet-api.jar"/>
          ????</path>


          2、定義相關(guān)任務(wù)
          ??
          <taskdef resource="cactus.tasks" classpathref="project.classpath"/>
          ?? <taskdef name="runservertests" classname="org.apache.cactus.integration.ant.RunServerTestsTask">
          ????????????<classpath>
          ????????????????<path refid="project.classpath"/>
          ????????????</classpath>
          ????????</taskdef>


          3、編譯應(yīng)用的類文件和測試的類文件

          4、打包整個應(yīng)用為war文件
          需要注意的是,不僅要打包應(yīng)用類,測試類也要打包
          ??
          ??
          <target name="war" depends="compile.java"
          ????????????description="Generate the runtime war">

          ????????<war warfile="${target.dir}/${project.name}.war"
          ???????????? webxml="${src.webapp.dir}/WEB-INF/web.xml">
          ????????????<fileset dir="${src.webapp.dir}">
          ????????????????<exclude name="cactus-report.xsl"/>
          ????????????????<exclude name="WEB-INF/cactus-web.xml"/>
          ????????????????<exclude name="WEB-INF/web.xml"/>
          ????????????</fileset>
          ????????????<classes dir="${target.classes.java.dir}"/>
          ????????????<!-- 別忘了打包測試類 -->
          ????????????<classes dir="${target.classes.test.dir}"/>
          ????????????<!-- 別忘了打包各種相關(guān)的jar文件 -->
          ????????????< lib dir="project.classpath"/>
          ????????</war>
          ????</target>


          5、在應(yīng)用的web.xml文件中添加測試所需的各種映射
          cactus提供了兩個task來完成這個工作,CactifyWar和WebXmlMerge。
          CactifyWar的功能是自動在已經(jīng)打包的應(yīng)用的web.xml文件中添加所需的映射。WebXmlMerge是提供合并兩個web.xml文件的功能。
          <target name="test.prepare"
          ????????????depends="war, compile.cactus, test.prepare.logging">

          ????????<!-- Cactify the web-app archive -->
          ????????<cactifywar srcfile="${target.dir}/${project.name}.war"
          ????????????????????destfile="${tomcat.home}/webapps/${project.name}-cactified.war"
          ????????????????>
          ????????????<classes dir="${target.classes.java.dir}"/>
          ????????????<classes dir="${target.classes.test.dir}"/>
          ????????????<lib dir="project.classpath"/>
          ?????? </cactifywar>
          </target>


          6、運行測試
          cactus提供了cactus和RunServerTests兩個task來運行測試。
          "cactus" task是通過復(fù)制容器服務(wù)器的最小文件并運行來運行測試,因此需要制定容器服務(wù)器的類型,啟動速度稍快點,另外配置比較方便,但是無法測試象tomcat連接池等資源。另外對tomcat5.5的支持也不好。
          "RunServerTests"是通過直接啟動容器服務(wù)起來運行測試,因此速度稍慢,且配置較麻煩,但能測試各種資源。
          ??
          <target name="test" depends="test.prepare"
          ???????????? description="Run tests on Tomcat ">

          ????????<!-- Start the servlet engine, wait for it to be started, run the
          ???????????? unit tests, stop the servlet engine, wait for it to be stopped.
          ???????????? The servlet engine is stopped if the tests fail for any reason -->
          ????????<!-- 8080是服務(wù)器的端口號,${project.name}-cactified是項目的路徑,和上一步的cactifywar 的destfile相對應(yīng) -->
          ????????<runservertests
          ????????????????testURL="http://localhost:8080/${project.name}-cactified/ServletRedirector?Cactus_Service=RUN_TEST"
          ????????????????startTarget="_StartTomcat"
          ????????????????stopTarget="_StopTomcat"
          ????????????????testTarget="_Test"/>

          ????</target>

          ????
          ????
          <!-- _Test就是一個普通的junit任務(wù) -->
          ????<target name="_Test">
          ????????<junit printsummary="yes" fork="yes">
          ????????????<classpath>
          ????????????????<path refid="project.classpath"/>
          ????????????????<pathelement location="${target.classes.java.dir}"/>
          ????????????????<pathelement location="${target.classes.test.dir}"/>
          ????????????</classpath>
          ????????????<formatter type="brief" usefile="false"/>
          ????????????<formatter type="xml"/>

          ????????????<batchtest>
          ????????????????<fileset dir="${src.test.dir}">
          ????????????????????<!-- Due to some Cactus synchronization bug, the 'unit' tests need
          ??????????????to run before the 'sample' tests -->
          ????????????????????<include name="**/Test*.java"/>
          ????????????????????<exclude name="**/Test*All.java"/>
          ????????????????</fileset>
          ????????????</batchtest>
          ????????</junit>
          ????</target>

          posted @ 2006-06-12 11:48 nbt 閱讀(229) | 評論 (0)編輯 收藏

          JUnit 最佳實踐(轉(zhuǎn)載)

               摘要: Techniques for building resilient, relocatable, multithreaded JUnit tests一項靈活的、可重定位的多線程JUnit測試技術(shù)?作者 Andy Schneider譯者 雷云飛 javawebstart Barret gstian [AKA]校對 gstian [AKA]Summary摘要?Extreme Programming's ...  閱讀全文

          posted @ 2006-06-12 09:39 nbt 閱讀(321) | 評論 (0)編輯 收藏

          Cactus實例講解(轉(zhuǎn)載)

          Cactus簡介

          . 簡介

          Cactus實現(xiàn)了對JUnit測試框架的無縫擴(kuò)展,可以方便地測試服務(wù)端應(yīng)用程序。Cactus可以在下面幾種情況下使用:

          • 測試Servlet以及任何使用了像HttpServletRequest,HttpServletResponse,……這樣的對象的代碼。使用ServletTestCase。
          • 測試Filter以及任何使用了像FilterConfig,……這樣的對象的代碼。使用FilterTestCase。
          • 測試JSP 。使用ServletTestCase或JspTestCase。
          • 測試Taglibs以及任何使用了像PageContext,……這樣的對象的代碼。使用JspTestCase。
          • 測試EJB。ServletTestCase或JspTestCase或FilterTestCase。

          Cactus的使用也是非常簡單的,你寫的測試類只需繼承ServletTestCase或者JspTestCase、FilterTestCase(它們都繼承了JUnit的TestCase)。寫好測試代碼后需要啟動web容器,然后執(zhí)行測試代碼。在下面的章節(jié)中我們將通過例子向你詳細(xì)講解。

          Cactus項目Apache Jakarta Commons的一個子項目,網(wǎng)址是:http://jakarta.apache.org/commons/cactus/

          . TestCase框架

          在Cactus下,我們寫的TestCase與JUnit有所不同,先看一段代碼,如下:

                 public class TestSample extendsServletTestCase/JspTestCase/FilterTestCase {
                 public TestSample (String testName) {
                 super(testName);
                 }
                 public void setUp() {
                 }
                 public void tearDown() {
                 }
                 public void beginXXX(WebRequest theRequest) {
                 }
                 public void testXXX() {
                 }
                 public void endXXX(WebResponse theResponse) {
                 }

          上面是一個Cactus測試類的完整代碼框架,其中的extends部分需要按你所測試的不同目標(biāo)來繼承不同的類(簡介中有所描述)。

          另外我們注意到兩個新的方法beginXXX和endXXX的,這兩個方法分別會在testXXX執(zhí)行前和執(zhí)行后執(zhí)行,它們和setUp、tearDown不同的是beginXXX和endXXX會在相應(yīng)的testXXX前執(zhí)行,而setUp和tearDown則在每個testXXX方法前都會執(zhí)行。另外beginXXX和endXXX是客戶端代碼,所以在這兩個方法里是無法使用request這樣的服務(wù)端對象的。

          對于endXXX方法需要另加說明的是,在Cactus v1.1前(包括v1.1),它的形式是這樣的public void endXXX(HttpURLConnection theConnection),而在Cactus v1.2開始它的形式有兩種可能:

          • public void endXXX(org.apache.cactus.WebResponse theResponse);
          • public void endXXX(com.meterware.httpunit.WebResponse theResponse);

          可以看到區(qū)別在于引用的包不同,為什么會這樣的呢?因為在v1.2開始Cactus集成了HttpUnit這個組件。如果你熟悉HttpUnit這個組件,我想應(yīng)該明白為什么要集成HttpUnit。下面我們來看一段代碼開比較一下兩者的區(qū)別:

          public void endXXX(org.apache.cactus.WebResponse theResponse) {

          String content = theResponse.getText();

          assertEquals(content, "<html><body><h1>Hello world!</h1></body></html>");

          }

          public void endXXX(com.meterware.httpunit.WebResponse theResponse) {

          WebTable table = theResponse.getTables()[0];

          assertEquals("rows", 4, table.getRowCount());

          assertEquals("columns", 3, table.getColumnCount());

          assertEquals("links", 1, table.getTableCell(0, 2).getLinks().length);

          }

          當(dāng)然,在實際應(yīng)用中你需要根據(jù)不同的需要來選擇不同的endXXX。兩個WebResponse的差別可以參見兩者各自的API Doc,這里就不再多說了。

          如何在Cactus里寫測試

          . 寫測試代碼

          首先,我們給出被測類的代碼,是一個Servlet:

          public class SampleServlet extends HttpServlet {

          public void doGet(HttpServletRequest theRequest,

          HttpServletResponse theResponse) throws IOException {

          PrintWriter pw = theResponse.getWriter();

          theResponse.setContentType("text/html");

          pw.print("<html><head/><body>");

          pw.print("A GET request");

          pw.print("</body></html>");

          }

          public String checkMethod(HttpServletRequest theRequest) {

          return theRequest.getMethod();

          }

          }

          Cactus中的測試類框架已經(jīng)在上面給出。下面來看一下例子,例子是從中Cactus自帶的實例中抽取的一部分,如下:

          public class TestSampleServlet extends ServletTestCase {

          public void testReadServletOutputStream() throws IOException {

          SampleServlet servlet = new SampleServlet();

          servlet.doGet(request, response);

          }

          public void endReadServletOutputStream(WebResponse theResponse)

          throws IOException {

          String expected = "<html><head/><body>A GET request</body></html>";

          String result = theResponse.getText();

          assertEquals(expected, result);

          }

          public void beginPostMethod(WebRequest theRequest) {

          theRequest.addParameter("param", "value", WebRequest.POST_METHOD);

          }

          public void testPostMethod() {

          SampleServlet servlet = new SampleServlet();

          assertEquals("POST", servlet.checkMethod(request));

          assertEquals("value", request.getParameter("param"));

          }

          }

          第一個方法testReadServletOutputStream,調(diào)用doGet,相當(dāng)于在客戶端提交請求,然后在Servlet處理后會產(chǎn)生一個回饋,所以,在endReadServletOutputStream方法里,我們通過調(diào)用response的相應(yīng)方法判斷回饋是否符合預(yù)期結(jié)果。

          第二個方法testPostMethod,在這之前有一個beginPostMethod,在這個方法里我們以POST方式往request里增加一個表單數(shù)據(jù)param,值為”value”。下面在testPostMethod我們就要驗證表單數(shù)據(jù)是否以POST方式提交到了服務(wù)端的Servlet里,所以,我們看到了兩個assertEquals,分別進(jìn)行了判斷。在這里我們要注意到beginPostMethod方法中的theRequest和testPostMethod中的request的區(qū)別,在前面我們已經(jīng)提到過,beginPostMethod是在客戶端執(zhí)行的,所以它方法內(nèi)的所有操作事實上是模擬頁面操作的,比如上面的設(shè)置表單數(shù)據(jù),而testPostMethod是服務(wù)端執(zhí)行的,其中的request也是服務(wù)端的。

          配置cactus.properties和web.xml

          cactus.properties

          • cactus.contextURL

          這個屬性是必須的,它指定了web應(yīng)用的訪問地址

          例:cactus.contextURL = http://localhost:8080/test

          • cactus.servletRedirectorName

          可選,當(dāng)測試類繼承ServletTestCase時用于指定Cactus Servlet Redirector的映射名稱。默認(rèn):ServletRedirector

          例:cactus.servletRedirectorName = ServletRedirector

          • cactus.jspRedirectorName

          可選,當(dāng)測試類繼承ServletTestCase時用于指定Cactus Jsp Redirector的映射名稱。默認(rèn):ServletRedirector

          例:cactus.jspRedirectorName = JspRedirector

          可選,當(dāng)測試類繼承ServletTestCase時用于指定Cactus Filter Redirector的映射名稱。默認(rèn):ServletRedirector

          例:cactus.filterRedirectorName = FilterRedirector

          Cactus.properties你可以放置在WEB-INF/classes/下。

          web.xml

          在web.xml里要為相應(yīng)的測試類指定相應(yīng)的Cactus Redirector。

          ServletTestCase對應(yīng)org.apache.cactus.server.ServletTestRedirector

          JspTestCase對應(yīng)/jspRedirector.jsp

          FilterTestCase對應(yīng)org.apache.cactus.server.FilterTestRedirector

          <web-app>

          <filter>

          <filter-name>FilterRedirector</filter-name>

          <filter-class>org.apache.cactus.server.FilterTestRedirector</filter-class>

          </filter>

          <filter-mapping>

          <filter-name>FilterRedirector</filter-name>

          <url-pattern>/FilterRedirector</url-pattern>

          </filter-mapping>

          <servlet>

          <servlet-name>ServletRedirector</servlet-name>

          <servlet-class>org.apache.cactus.server.ServletTestRedirector</servlet-class>

          </servlet>

          <servlet>

          <servlet-name>JspRedirector</servlet-name>

          <jsp-file>/jspRedirector.jsp</jsp-file>

          </servlet>

          <servlet-mapping>

          <servlet-name>ServletRedirector</servlet-name>

          <url-pattern>/ServletRedirector</url-pattern>

          </servlet-mapping>

          <servlet-mapping>

          <servlet-name>JspRedirector</servlet-name>

          <url-pattern>/JspRedirector</url-pattern>

          </servlet-mapping>

          </web-app>

          如果你的測試類繼承了JspTestCase則需要將jspRedirector.jsp文件放置到你在web.xml中指定的路徑里。

          安裝說明

          • 在使用Cactus時,strutstest.jar還需要有下列包的支持。包可放置在WEB-INF/lib下

          如下:

          junit.jar

          servlet.jar

          cactus.jar

          httpclient.jar

          commons-logging.jar

          httpunit.jar,Tidy.jar,xerces.jar(可選,如果你集成了httpunit的話就需要,也就是在endXXX中使用了httpunit)

            • Server端(也就是web容器)需要如下包

          cactus.jar

          junit.jar

          aspectjrt.jar

          commons-logging.jar

          • 寫好測試代碼后將class放置在WEB-INF/classes下
          • 被測代碼也放置在WEB-INF/classes下
          • 寫好cactus.properties和web.xml兩個配置文件
          • 啟動web容器
          • 運行測試代碼

          posted @ 2006-06-12 09:34 nbt 閱讀(273) | 評論 (0)編輯 收藏

          JDBC連接大全

          Java數(shù)據(jù)庫連接(JDBC)由一組用 Java 編程語言編寫的類和接口組成。JDBC 為工具/數(shù)據(jù)庫開發(fā)人員提供了一個標(biāo)準(zhǔn)的 API,使他們能夠用純Java API 來編寫數(shù)據(jù)庫應(yīng)用程序。然而各個開發(fā)商的接口并不完全相同,所以開發(fā)環(huán)境的變化會帶來一定的配置變化。本文主要集合了不同數(shù)據(jù)庫的連接方式。

            一、連接各種數(shù)據(jù)庫方式速查表

            下面羅列了各種數(shù)據(jù)庫使用JDBC連接的方式,可以作為一個手冊使用。

            1、Oracle8/8i/9i數(shù)據(jù)庫(thin模式)

          Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
          String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl為數(shù)據(jù)庫的SID
          String user="test";
          String password="test";
          Connection conn= DriverManager.getConnection(url,user,password);

            2、DB2數(shù)據(jù)庫

          Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();
          String url="jdbc:db2://localhost:5000/sample"; //sample為你的數(shù)據(jù)庫名
          String user="admin";
          String password="";
          Connection conn= DriverManager.getConnection(url,user,password);

            3、Sql Server7.0/2000數(shù)據(jù)庫

          Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
          String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb";
          //mydb為數(shù)據(jù)庫
          String user="sa";
          String password="";
          Connection conn= DriverManager.getConnection(url,user,password);

            4、Sybase數(shù)據(jù)庫

          Class.forName("com.sybase.jdbc.SybDriver").newInstance();
          String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDB為你的數(shù)據(jù)庫名
          Properties sysProps = System.getProperties();
          SysProps.put("user","userid");
          SysProps.put("password","user_password");
          Connection conn= DriverManager.getConnection(url, SysProps);

            5、Informix數(shù)據(jù)庫

          Class.forName("com.informix.jdbc.IfxDriver").newInstance();
          String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
          user=testuser;password=testpassword"; //myDB為數(shù)據(jù)庫名
          Connection conn= DriverManager.getConnection(url);

            6、MySQL數(shù)據(jù)庫

          Class.forName("org.gjt.mm.mysql.Driver").newInstance();
          String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1"
          //myDB為數(shù)據(jù)庫名
          Connection conn= DriverManager.getConnection(url);

            7、PostgreSQL數(shù)據(jù)庫

          Class.forName("org.postgresql.Driver").newInstance();
          String url ="jdbc:postgresql://localhost/myDB" //myDB為數(shù)據(jù)庫名
          String user="myuser";
          String password="mypassword";
          Connection conn= DriverManager.getConnection(url,user,password);

            8、access數(shù)據(jù)庫直連用ODBC的

          Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
          String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
          Connection conn = DriverManager.getConnection(url,"","");
          Statement stmtNew=conn.createStatement() ;

            二、JDBC連接MySql方式

            下面是使用JDBC連接MySql的一個小的教程

            1、查找驅(qū)動程序

            MySQL目前提供的java驅(qū)動程序為Connection/J,可以從MySQL官方網(wǎng)站下載,并找到mysql-connector-java-3.0.15-ga-bin.jar文件,此驅(qū)動程序為純java驅(qū)動程序,不需做其他配置。

            2、動態(tài)指定classpath

            如果需要執(zhí)行時動態(tài)指定classpath,就在執(zhí)行時采用-cp方式。否則將上面的.jar文件加入到classpath環(huán)境變量中。

            3、加載驅(qū)動程序

          try{
           Class.forName(com.mysql.jdbc.Driver);
           System.out.println(Success loading Mysql Driver!);
          }catch(Exception e)
          {
           System.out.println(Error loading Mysql Driver!);
           e.printStackTrace();
          }

            4、設(shè)置連接的url

          jdbc:mysql://localhost/databasename[?pa=va][&pa=va]

            三、以下列出了在使用JDBC來連接Oracle數(shù)據(jù)庫時可以使用的一些技巧

            1、在客戶端軟件開發(fā)中使用Thin驅(qū)動程序

            在開發(fā)Java軟件方面,Oracle的數(shù)據(jù)庫提供了四種類型的驅(qū)動程序,二種用于應(yīng)用軟件、applets、servlets等客戶端軟件,另外二種用于數(shù)據(jù)庫中的Java存儲過程等服務(wù)器端軟件。在客戶機(jī)端軟件的開發(fā)中,我們可以選擇OCI驅(qū)動程序或Thin驅(qū)動程序。OCI驅(qū)動程序利用Java本地化接口(JNI),通過Oracle客戶端軟件與數(shù)據(jù)庫進(jìn)行通訊。Thin驅(qū)動程序是純Java驅(qū)動程序,它直接與數(shù)據(jù)庫進(jìn)行通訊。為了獲得最高的性能,Oracle建議在客戶端軟件的開發(fā)中使用OCI驅(qū)動程序,這似乎是正確的。但我建議使用Thin驅(qū)動程序,因為通過多次測試發(fā)現(xiàn),在通常情況下,Thin驅(qū)動程序的性能都超過了OCI驅(qū)動程序。

            2、關(guān)閉自動提交功能,提高系統(tǒng)性能

            在第一次建立與數(shù)據(jù)庫的連接時,在缺省情況下,連接是在自動提交模式下的。為了獲得更好的性能,可以通過調(diào)用帶布爾值false參數(shù)的Connection類的setAutoCommit()方法關(guān)閉自動提交功能,如下所示:

            conn.setAutoCommit(false);

            值得注意的是,一旦關(guān)閉了自動提交功能,我們就需要通過調(diào)用Connection類的commit()和rollback()方法來人工的方式對事務(wù)進(jìn)行管理。

            3、在動態(tài)SQL或有時間限制的命令中使用Statement對象

            在執(zhí)行SQL命令時,我們有二種選擇:可以使用PreparedStatement對象,也可以使用Statement對象。無論多少次地使用同一個SQL命令,PreparedStatement都只對它解析和編譯一次。當(dāng)使用Statement對象時,每次執(zhí)行一個SQL命令時,都會對它進(jìn)行解析和編譯。這可能會使你認(rèn)為,使用PreparedStatement對象比使用Statement對象的速度更快。然而,我進(jìn)行的測試表明,在客戶端軟件中,情況并非如此。因此,在有時間限制的SQL操作中,除非成批地處理SQL命令,我們應(yīng)當(dāng)考慮使用Statement對象。

            此外,使用Statement對象也使得編寫動態(tài)SQL命令更加簡單,因為我們可以將字符串連接在一起,建立一個有效的SQL命令。因此,我認(rèn)為,Statement對象可以使動態(tài)SQL命令的創(chuàng)建和執(zhí)行變得更加簡單。

            4、利用helper函數(shù)對動態(tài)SQL命令進(jìn)行格式化

            在創(chuàng)建使用Statement對象執(zhí)行的動態(tài)SQL命令時,我們需要處理一些格式化方面的問題。例如,如果我們想創(chuàng)建一個將名字O'Reilly插入表中的SQL命令,則必須使用二個相連的“''”號替換O'Reilly中的“'”號。完成這些工作的最好的方法是創(chuàng)建一個完成替換操作的helper方法,然后在連接字符串心服用公式表達(dá)一個SQL命令時,使用創(chuàng)建的helper方法。與此類似的是,我們可以讓helper方法接受一個Date型的值,然后讓它輸出基于Oracle的to_date()函數(shù)的字符串表達(dá)式。

            5、利用PreparedStatement對象提高數(shù)據(jù)庫的總體效率

            在使用PreparedStatement對象執(zhí)行SQL命令時,命令被數(shù)據(jù)庫進(jìn)行解析和編譯,然后被放到命令緩沖區(qū)。然后,每當(dāng)執(zhí)行同一個PreparedStatement對象時,它就會被再解析一次,但不會被再次編譯。在緩沖區(qū)中可以發(fā)現(xiàn)預(yù)編譯的命令,并且可以重新使用。在有大量用戶的企業(yè)級應(yīng)用軟件中,經(jīng)常會重復(fù)執(zhí)行相同的SQL命令,使用PreparedStatement對象帶來的編譯次數(shù)的減少能夠提高數(shù)據(jù)庫的總體性能。如果不是在客戶端創(chuàng)建、預(yù)備、執(zhí)行PreparedStatement任務(wù)需要的時間長于Statement任務(wù),我會建議在除動態(tài)SQL命令之外的所有情況下使用PreparedStatement對象。

            6、在成批處理重復(fù)的插入或更新操作中使用PreparedStatement對象

            如果成批地處理插入和更新操作,就能夠顯著地減少它們所需要的時間。Oracle提供的Statement和 CallableStatement并不真正地支持批處理,只有PreparedStatement對象才真正地支持批處理。我們可以使用addBatch()和executeBatch()方法選擇標(biāo)準(zhǔn)的JDBC批處理,或者通過利用PreparedStatement對象的setExecuteBatch()方法和標(biāo)準(zhǔn)的executeUpdate()方法選擇速度更快的Oracle專有的方法。要使用Oracle專有的批處理機(jī)制,可以以如下所示的方式調(diào)用setExecuteBatch():

          PreparedStatement pstmt3D null;
          try {
           ((OraclePreparedStatement)pstmt).setExecuteBatch(30);
           ...
           pstmt.executeUpdate();
          }

            調(diào)用setExecuteBatch()時指定的值是一個上限,當(dāng)達(dá)到該值時,就會自動地引發(fā)SQL命令執(zhí)行,標(biāo)準(zhǔn)的executeUpdate()方法就會被作為批處理送到數(shù)據(jù)庫中。我們可以通過調(diào)用PreparedStatement類的sendBatch()方法隨時傳輸批處理任務(wù)。

            7、使用Oracle locator方法插入、更新大對象(LOB)

            Oracle的PreparedStatement類不完全支持BLOB和CLOB等大對象的處理,尤其是Thin驅(qū)動程序不支持利用PreparedStatement對象的setObject()和setBinaryStream()方法設(shè)置BLOB的值,也不支持利用setCharacterStream()方法設(shè)置CLOB的值。只有l(wèi)ocator本身中的方法才能夠從數(shù)據(jù)庫中獲取LOB類型的值。可以使用PreparedStatement對象插入或更新LOB,但需要使用locator才能獲取LOB的值。由于存在這二個問題,因此,我建議使用locator的方法來插入、更新或獲取LOB的值。

            8、使用SQL92語法調(diào)用存儲過程

            在調(diào)用存儲過程時,我們可以使用SQL92或Oracle PL/SQL,由于使用Oracle PL/SQL并沒有什么實際的好處,而且會給以后維護(hù)你的應(yīng)用程序的開發(fā)人員帶來麻煩,因此,我建議在調(diào)用存儲過程時使用SQL92。

            9、使用Object SQL將對象模式轉(zhuǎn)移到數(shù)據(jù)庫中

            既然可以將Oracle的數(shù)據(jù)庫作為一種面向?qū)ο蟮臄?shù)據(jù)庫來使用,就可以考慮將應(yīng)用程序中的面向?qū)ο竽J睫D(zhuǎn)到數(shù)據(jù)庫中。目前的方法是創(chuàng)建Java bean作為偽裝的數(shù)據(jù)庫對象,將它們的屬性映射到關(guān)系表中,然后在這些bean中添加方法。盡管這樣作在Java中沒有什么問題,但由于操作都是在數(shù)據(jù)庫之外進(jìn)行的,因此其他訪問數(shù)據(jù)庫的應(yīng)用軟件無法利用對象模式。如果利用Oracle的面向?qū)ο蟮募夹g(shù),可以通過創(chuàng)建一個新的數(shù)據(jù)庫對象類型在數(shù)據(jù)庫中模仿其數(shù)據(jù)和操作,然后使用JPublisher等工具生成自己的Java bean類。如果使用這種方式,不但Java應(yīng)用程序可以使用應(yīng)用軟件的對象模式,其他需要共享你的應(yīng)用中的數(shù)據(jù)和操作的應(yīng)用軟件也可以使用應(yīng)用軟件中的對象模式。

            10、利用SQL完成數(shù)據(jù)庫內(nèi)的操作

            我要向大家介紹的最重要的經(jīng)驗是充分利用SQL的面向集合的方法來解決數(shù)據(jù)庫處理需求,而不是使用Java等過程化的編程語言。

            如果編程人員要在一個表中查找許多行,結(jié)果中的每個行都會查找其他表中的數(shù)據(jù),最后,編程人員創(chuàng)建了獨立的UPDATE命令來成批地更新第一個表中的數(shù)據(jù)。與此類似的任務(wù)可以通過在set子句中使用多列子查詢而在一個UPDATE命令中完成。當(dāng)能夠在單一的SQL命令中完成任務(wù),何必要讓數(shù)據(jù)在網(wǎng)上流來流去的?我建議用戶認(rèn)真學(xué)習(xí)如何最大限度地發(fā)揮SQL的功能。

          posted @ 2006-06-12 09:11 nbt 閱讀(330) | 評論 (0)編輯 收藏

          利用xdoclet開發(fā)hibernate3的ant配置文件


          <?xml version="1.0" encoding="utf-8"?>
          <project name="利用工具開發(fā)Hibernate" default="help" basedir=".">

          ?<!-- ******? 環(huán)境設(shè)置,可以根據(jù)自己的實際配置自行更改 ***** -->
          ?<!-- ******? http://blog.csdn.net/fasttalk??? ***** -->
          ?<!-- ******? http://www.aygfsteel.com/asktalk? ***** -->
          ?<!-- 源文件目錄, 可以通過 項目->屬性->Java構(gòu)建路徑 更改 -->
          ?<property name="src.dir" value="./src" />
          ?<!-- 輸出的class文件目錄,可以通過 項目->屬性->Java構(gòu)建路徑 更改 -->
          ?<property name="class.dir" value="./bin" />
          ?<!-- 庫文件目錄? -->
          ?<property name="lib.dir" value="E:/workspace/java/hibernate3" />

          ?<!-- 定義類路徑 -->
          ?<path id="project.class.path">
          ??<fileset dir="${lib.dir}">
          ???<include name="*.jar"/>
          ??</fileset>
          ??<pathelement location="${class.dir}" />
          ?</path>

          ?<!-- ************************************************************** -->
          ?<!-- 使用說明 -->
          ?<!-- ************************************************************** -->
          ?<target name="help">
          ??<echo message="利用工具開發(fā)Hibernate" />
          ??<echo message="-----------------------------------" />
          ??<echo message="" />
          ??<echo message="提供以下任務(wù):" />
          ??<echo message="" />
          ??<echo message="generate-hbm???? --> 運行HibernateDoclet,生成 Hibernate 類的映射文件" />
          ??<echo message="schemaexport???? --> 運行SchemaExport,利用 hbm.xml 文件生成數(shù)據(jù)表" />
          ??<echo message="" />
          ?</target>


          ?<!-- ************************************************************** -->
          ?<!-- Hbm2Java 任務(wù) 在hibernate3中無法實現(xiàn) -->
          ?<!-- ************************************************************** -->
          ?<target name="generate-code" >
          ??<echo message="運行 Hbm2Java 任務(wù), 利用 hbm.xml 文件生成Java類文件"/>

          ??<taskdef name="hbm2java"
          ?????? classname="org.hibernate.tool.instrument.InstrumentTask"
          ????????? classpathref="project.class.path">
          ??</taskdef>

          ??<hbm2java output="${src.dir}">
          ???<fileset dir="${src.dir}">
          ????<include name="**/*.hbm.xml"/>
          ???</fileset>
          ??</hbm2java>
          ?</target>


          ?<!-- ************************************************************** -->
          ?<!-- HibernateDoclet 任務(wù) -->
          ?<!-- ************************************************************** -->
          ?<target name="generate-hbm" >
          ??<echo message="運行HibernateDoclet,生成 Hibernate 類的映射文件"/>

          ??<taskdef name="hibernatedoclet"
          ???classname="xdoclet.modules.hibernate.HibernateDocletTask"
          ???classpathref="project.class.path">
          ??</taskdef>
          ??????? <!--
          ??????? destdir???????? 輸出目錄;
          ??????? force,????????? 每次都強(qiáng)行執(zhí)行,覆蓋原有文件;
          ??????? -->
          ??<hibernatedoclet destdir="${src.dir}"
          ???excludedtags="@version,@author,@todo" force="true" encoding="GBK"
          ???verbose="true">

          ???<fileset dir="${src.dir}">
          ????<include name="**/*.java"/>
          ???</fileset>

          ???<hibernate version="3.0" xmlencoding="utf-8" />
          ??</hibernatedoclet>
          ?</target>


          ?<!-- ************************************************************** -->
          ?<!-- SchemaExport 任務(wù) -->
          ?<!-- ************************************************************** -->
          ?<target name="schemaexport">
          ??<echo message="運行SchemaExport,利用 hbm.xml 文件生成數(shù)據(jù)表"/>

          ??<taskdef name="schemaexport"
          ???classname="org.hibernate.tool.hbm2ddl.SchemaExportTask"
          ???classpathref="project.class.path">
          ??</taskdef>
          ????? <!--
          ????? quiet=true?????????????????????? 不要把腳本輸出到stdout;
          ????? drop=true??????????????????????? 只進(jìn)行drop tables的步驟 ;
          ????? text=true??????????????????????? 不執(zhí)行在數(shù)據(jù)庫中運行的步驟 ;
          ????? output=my_schema.ddl???????????? 把輸出的ddl腳本輸出到一個文件 ;
          ????? config=hibernate.cfg.xml???????? 從XML文件讀入Hibernate配置 ;
          ????? properties=hibernate.properties? 從文件讀入數(shù)據(jù)庫屬性 ;
          ????? format=true????????????????????? 把腳本中的SQL語句對齊和美化 ;
          ????? delimiter=x????????????????????? 為腳本設(shè)置行結(jié)束符
          ????? -->
          ??<schemaexport properties="src/hibernate.properties"
          ? quiet="no"?text="no" drop="no"? output="schema-export.sql" >
          ???????? <fileset dir="${src.dir}">
          ???????????? <include name="**/*.hbm.xml"/>?
          ???????? </fileset>
          ??</schemaexport>
          ?</target>

          </project>

          posted @ 2006-06-12 08:59 nbt 閱讀(475) | 評論 (0)編輯 收藏

          將Ajax包裝成對象使用

          ?? Ajax目前是社區(qū)內(nèi)最熱門的話題之一了,最近在我們的項目中用了大量的Ajax,現(xiàn)在把我們的使用方法在這兒寫出來,希望大家能指教。

          因為要用到Ajax就肯定要用到XMLHttpRequest對象,但由于不同的瀏覽器版本,相應(yīng)的生成它的方法也有所不同,所以我們不得不對瀏覽器的版本進(jìn)行判斷,試想,如果我們要在很多地方都要寫那些繁瑣的代碼會覺的很麻煩,代碼的重用也很低,所以我們寫一個Ajax的對象。代碼如下:

          //*********************************************************
          // 目的:??? AJAX類
          // 輸入:??? 無
          // 返回:??? 返回XMLHttp對象
          // 例子:??? var myConn = new XHConn();
          //
          //?????????? if (!myConn) alert("XMLHTTP not available. Try a newer/better browser.");
          //
          //?????????? var fnWhenDone = function (oXML) { alert(oXML.responseText); };
          //
          //?????????? myConn.connect("mypage.php", "POST", "foo=bar&baz=qux", fnWhenDone);
          //
          //*********************************************************
          function XHConn()
          {
          ? var xmlhttp = false, bComplete = false;
          ? try
          ? {
          ? ?xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
          ? }
          ? catch (e)
          ? {
          ? ?try
          ? ?{
          ? ??xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
          ? ?}
          ??? catch (e)
          ??? {
          ? ??try
          ? ??{
          ? ???xmlhttp = new XMLHttpRequest();
          ? ??}
          ? ??catch (e)
          ? ??{
          ? ???xmlhttp = false;
          ? ??}
          ? ?}
          ? }
          ? if (!xmlhttp) return null;
          ? this.connect = function(sURL, sMethod, sVars, fnDone)
          ? {
          ??? if (!xmlhttp) return false;
          ??? bComplete = false;
          ??? sVars = (sVars == '') ? Math.random() : sVars + "&" + Math.random();
          ??? sMethod = sMethod.toUpperCase();

          ??? try
          ??? {
          ????? if (sMethod == "GET")
          ????? {
          ??????? xmlhttp.open(sMethod, sURL+"?"+sVars, true);
          ??????? xmlhttp.setRequestHeader("Content-Type", "text/html;charset=GB2312");
          ??????? sVars = "";
          ????? }
          ????? else
          ????? {
          ??????? xmlhttp.open(sMethod, sURL, true);
          ??????? xmlhttp.setRequestHeader("Method", "POST "+sURL+" HTTP/1.1");
          ??????? xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
          ????? }
          ????? xmlhttp.onreadystatechange = function()
          ????? {
          ??????? if (xmlhttp.readyState == 4 && !bComplete)
          ??????? {
          ????????? bComplete = true;
          ????????? fnDone(xmlhttp);
          ??????? }
          ????? };
          ?????
          ????? xmlhttp.send(sVars);
          ??? }
          ??? catch(z)
          ??? {
          ??? ?return false;
          ??? }
          ??? return true;
          ? };
          ?
          ? return this;
          }


          通過這個對象,我們把那些繁瑣的代碼都封裝到里面,這樣大大提高了代碼的重用性,每次要用Ajax時我們只需要在我們的頁面上 new一個XHConn()對象就行了,然后通過調(diào)用它的方法connect(sURL, sMethod, sVars, fnDone)就可以和服務(wù)器進(jìn)行異步交互了。

          posted @ 2006-06-09 16:50 nbt 閱讀(291) | 評論 (0)編輯 收藏

          JVM(JAVA虛擬機(jī)介紹)

          Java虛擬機(jī)(JVM)是可運行Java代碼的假想計算機(jī)。只要根據(jù)JVM規(guī)格描述將解釋器移植到特定的計算機(jī)上,就能保證經(jīng)過編譯的任何Java代碼能夠在該系統(tǒng)上運行。本文首先簡要介紹從Java文件的編譯到最終執(zhí)行的過程,隨后對JVM規(guī)格描述作一說明。

            一.Java源文件的編譯、下載、解釋和執(zhí)行
            Java應(yīng)用程序的開發(fā)周期包括編譯、下載、解釋和執(zhí)行幾個部分。Java編譯程序?qū)ava源程序翻譯為JVM可執(zhí)行代碼—字節(jié)碼。這一編譯過程同C/C++的編譯有些不同。當(dāng)C編譯器編譯生成一個對象的代碼時,該代碼是為在某一特定硬件平臺運行而產(chǎn)生的。因此,在編譯過程中,編譯程序通過查表將所有對符號的引用轉(zhuǎn)換為特定的內(nèi)存偏移量,以保證程序運行。Java編譯器卻不將對變量和方法的引用編譯為數(shù)值引用,也不確定程序執(zhí)行過程中的內(nèi)存布局,而是將這些符號引用信息保留在字節(jié)碼中,由解釋器在運行過程中創(chuàng)立內(nèi)存布局,然后再通過查表來確定一個方法所在的地址。這樣就有效的保證了Java的可移植性和安全性。
          運行JVM字節(jié)碼的工作是由解釋器來完成的。解釋執(zhí)行過程分三部進(jìn)行:代碼的裝入、代碼的校驗和代碼的執(zhí)行。裝入代碼的工作由"類裝載器"(class loader)完成。類裝載器負(fù)責(zé)裝入運行一個程序需要的所有代碼,這也包括程序代碼中的類所繼承的類和被其調(diào)用的類。當(dāng)類裝載器裝入一個類時,該類被放在自己的名字空間中。除了通過符號引用自己名字空間以外的類,類之間沒有其他辦法可以影響其他類。在本臺計算機(jī)上的所有類都在同一地址空間內(nèi),而所有從外部引進(jìn)的類,都有一個自己獨立的名字空間。這使得本地類通過共享相同的名字空間獲得較高的運行效率,同時又保證它們與從外部引進(jìn)的類不會相互影響。當(dāng)裝入了運行程序需要的所有類后,解釋器便可確定整個可執(zhí)行程序的內(nèi)存布局。解釋器為符號引用同特定的地址空間建立對應(yīng)關(guān)系及查詢表。通過在這一階段確定代碼的內(nèi)存布局,Java很好地解決了由超類改變而使子類崩潰的問題,同時也防止了代碼對地址的非法訪問。
          隨后,被裝入的代碼由字節(jié)碼校驗器進(jìn)行檢查。校驗器可發(fā)現(xiàn)操作數(shù)棧溢出,非法數(shù)據(jù)類型轉(zhuǎn)化等多種錯誤。通過校驗后,代碼便開始執(zhí)行了。
            Java字節(jié)碼的執(zhí)行有兩種方式:
            1.即時編譯方式:解釋器先將字節(jié)碼編譯成機(jī)器碼,然后再執(zhí)行該機(jī)器碼。
            2.解釋執(zhí)行方式:解釋器通過每次解釋并執(zhí)行一小段代碼來完成Java字節(jié)碼程 序的所有操作。
            通常采用的是第二種方法。由于JVM規(guī)格描述具有足夠的靈活性,這使得將字節(jié)碼翻譯為機(jī)器代碼的工作具有較高的效率。對于那些對運行速度要求較高的應(yīng)用程序,解釋器可將Java字節(jié)碼即時編譯為機(jī)器碼,從而很好地保證了Java代碼的可移植性和高性能。

            二.JVM規(guī)格描述
            JVM的設(shè)計目標(biāo)是提供一個基于抽象規(guī)格描述的計算機(jī)模型,為解釋程序開發(fā)人員提很好的靈活性,同時也確保Java代碼可在符合該規(guī)范的任何系統(tǒng)上運行。JVM對其實現(xiàn)的某些方面給出了具體的定義,特別是對Java可執(zhí)行代碼,即字節(jié)碼(Bytecode)的格式給出了明確的規(guī)格。這一規(guī)格包括操作碼和操作數(shù)的語法和數(shù)值、標(biāo)識符的數(shù)值表示方式、以及Java類文件中的Java對象、常量緩沖池在JVM的存儲映象。這些定義為JVM解釋器開發(fā)人員提供了所需的信息和開發(fā)環(huán)境。Java的設(shè)計者希望給開發(fā)人員以隨心所欲使用Java的自由。
            JVM定義了控制Java代碼解釋執(zhí)行和具體實現(xiàn)的五種規(guī)格,它們是:
            JVM指令系統(tǒng)
            JVM寄存器
            JVM棧結(jié)構(gòu)
            JVM碎片回收堆
            JVM存儲區(qū)
            2.1JVM指令系統(tǒng)
          JVM指令系統(tǒng)同其他計算機(jī)的指令系統(tǒng)極其相似。Java指令也是由 操作碼和操作數(shù)兩部分組成。操作碼為8位二進(jìn)制數(shù),操作數(shù)進(jìn)緊隨在操作碼的后面,其長度根據(jù)需要而不同。操作碼用于指定一條指令操作的性質(zhì)(在這里我們采用匯編符號的形式進(jìn)行說明),如iload表示從存儲器中裝入一個整數(shù),anewarray表示為一個新數(shù)組分配空間,iand表示兩個整數(shù)的"與",ret用于流程控制,表示從對某一方法的調(diào)用中返回。當(dāng)長度大于8位時,操作數(shù)被分為兩個以上字節(jié)存放。JVM采用了"big endian"的編碼方式來處理這種情況,即高位bits存放在低字節(jié)中。這同 Motorola及其他的RISC CPU采用的編碼方式是一致的,而與Intel采用的"little endian "的編碼方式即低位bits存放在低位字節(jié)的方法不同。
            Java指令系統(tǒng)是以Java語言的實現(xiàn)為目的設(shè)計的,其中包含了用于調(diào)用方法和監(jiān)視多先程系統(tǒng)的指令。Java的8位操作碼的長度使得JVM最多有256種指令,目前已使用了160多種操作碼。
            2.2JVM指令系統(tǒng)
          所有的CPU均包含用于保存系統(tǒng)狀態(tài)和處理器所需信息的寄存器組。如果虛擬機(jī)定義較多的寄存器,便可以從中得到更多的信息而不必對棧或內(nèi)存進(jìn)行訪問,這有利于提高運行速度。然而,如果虛擬機(jī)中的寄存器比實際CPU的寄存器多,在實現(xiàn)虛擬機(jī)時就會占用處理器大量的時間來用常規(guī)存儲器模擬寄存器,這反而會降低虛擬機(jī)的效率。針對這種情況,JVM只設(shè)置了4個最為常用的寄存器。它們是:
            pc程序計數(shù)器
            optop操作數(shù)棧頂指針
            frame當(dāng)前執(zhí)行環(huán)境指針
            vars指向當(dāng)前執(zhí)行環(huán)境中第一個局部變量的指針
          所有寄存器均為32位。pc用于記錄程序的執(zhí)行。optop,frame和vars用于記錄指向Java棧區(qū)的指針。
            2.3JVM棧結(jié)構(gòu)
            作為基于棧結(jié)構(gòu)的計算機(jī),Java棧是JVM存儲信息的主要方法。當(dāng)JVM得到一個Java字節(jié)碼應(yīng)用程序后,便為該代碼中一個類的每一個方法創(chuàng)建一個棧框架,以保存該方法的狀態(tài)信息。每個棧框架包括以下三類信息:
            局部變量
            執(zhí)行環(huán)境
            操作數(shù)棧
          局部變量用于存儲一個類的方法中所用到的局部變量。vars寄存器指向該變量表中的第一個局部變量。
            執(zhí)行環(huán)境用于保存解釋器對Java字節(jié)碼進(jìn)行解釋過程中所需的信息。它們是:上次調(diào)用的方法、局部變量指針和操作數(shù)棧的棧頂和棧底指針。執(zhí)行環(huán)境是一個執(zhí)行一個方法的控制中心。例如:如果解釋器要執(zhí)行iadd(整數(shù)加法),首先要從frame寄存器中找到當(dāng)前執(zhí)行環(huán)境,而后便從執(zhí)行環(huán)境中找到操作數(shù)棧,從棧頂彈出兩個整數(shù)進(jìn)行加法運算,最后將結(jié)果壓入棧頂。
          操作數(shù)棧用于存儲運算所需操作數(shù)及運算的結(jié)果。
            2.4JVM碎片回收堆
            Java類的實例所需的存儲空間是在堆上分配的。解釋器具體承擔(dān)為類實例分配空間的工作。解釋器在為一個實例分配完存儲空間后,便開始記錄對該實例所占用的內(nèi)存區(qū)域的使用。一旦對象使用完畢,便將其回收到堆中。
          在Java語言中,除了new語句外沒有其他方法為一對象申請和釋放內(nèi)存。對內(nèi)存進(jìn)行釋放和回收的工作是由Java運行系統(tǒng)承擔(dān)的。這允許Java運行系統(tǒng)的設(shè)計者自己決定碎片回收的方法。在SUN公司開發(fā)的Java解釋器和Hot Java環(huán)境中,碎片回收用后臺線程的方式來執(zhí)行。這不但為運行系統(tǒng)提供了良好的性能,而且使程序設(shè)計人員擺脫了自己控制內(nèi)存使用的風(fēng)險。
            2.5JVM存儲區(qū)
          JVM有兩類存儲區(qū):常量緩沖池和方法區(qū)。常量緩沖池用于存儲類名稱、方法和字段名稱以及串常量。方法區(qū)則用于存儲Java方法的字節(jié)碼。對于這兩種存儲區(qū)域具體實現(xiàn)方式在JVM規(guī)格中沒有明確規(guī)定。這使得Java應(yīng)用程序的存儲布局必須在運行過程中確定,依賴于具體平臺的實現(xiàn)方式。
            JVM是為Java字節(jié)碼定義的一種獨立于具體平臺的規(guī)格描述,是Java平臺獨立性的基礎(chǔ)。目前的JVM還存在一些限制和不足,有待于進(jìn)一步的完善,但無論如何,JVM的思想是成功的。

            對比分析:如果把Java原程序想象成我們的C++原程序,Java原程序編譯后生成的字節(jié)碼就相當(dāng)于C++原程序編譯后的80x86的機(jī)器碼(二進(jìn)制程序文件),JVM虛擬機(jī)相當(dāng)于80x86計算機(jī)系統(tǒng),Java解釋器相當(dāng)于80x86CPU。在80x86CPU上運行的是機(jī)器碼,在Java解釋器上運行的是Java字節(jié)碼。
            Java解釋器相當(dāng)于運行Java字節(jié)碼的“CPU”,但該“CPU”不是通過硬件實現(xiàn)的,而是用軟件實現(xiàn)的。Java解釋器實際上就是特定的平臺下的一個應(yīng)用程序。只要實現(xiàn)了特定平臺下的解釋器程序,Java字節(jié)碼就能通過解釋器程序在該平臺下運行,這是Java跨平臺的根本。當(dāng)前,并不是在所有的平臺下都有相應(yīng)Java解釋器程序,這也是Java并不能在所有的平臺下都能運行的原因,它只能在已實現(xiàn)了Java解釋器程序的平臺下運行。

          posted @ 2006-06-09 16:25 nbt 閱讀(225) | 評論 (0)編輯 收藏

          Java中一些關(guān)于日期、日期格式、日期的解析和日期的計算 (轉(zhuǎn))

          跑系統(tǒng)時,難免遇到了數(shù)據(jù)量大的情況,只好讓愛機(jī)徹夜工作了,自己閃人。畢竟對它不放心,這時得用到日志,日志里的時間肯定是要的啦。至少得知道他什么時候罷工吧(今天一來,我電腦就在昨天不明時間罷工了!)。下面是轉(zhuǎn)自一位網(wǎng)友的:

          Java中一些關(guān)于日期、日期格式、日期的解析和日期的計算

          Java 語言的Calendar(日歷),Date(日期), 和DateFormat(日期格式)組成了Java標(biāo)準(zhǔn)的一個基本但是非常重要的部分. 日期是商業(yè)邏輯計算一個關(guān)鍵的部分. 所有的開發(fā)者都應(yīng)該能夠計算未來的日期, 定制日期的顯示格式, 并將文本數(shù)據(jù)解析成日期對象. 我們寫了兩篇文章, 這是第一篇, 我們將大概的學(xué)習(xí)日期, 日期格式, 日期的解析和日期的計算.

          我們將討論下面的類:

          1、具體類(和抽象類相對)java.util.Date
          2、抽象類java.text.DateFormat 和它的一個具體子類,java.text.SimpleDateFormat
          3、抽象類java.util.Calendar 和它的一個具體子類,java.util.GregorianCalendar

          具體類可以被實例化, 但是抽象類卻不能. 你首先必須實現(xiàn)抽象類的一個具體子類.

          Date 類從Java 開發(fā)包(JDK) 1.0 就開始進(jìn)化, 當(dāng)時它只包含了幾個取得或者設(shè)置一個日期數(shù)據(jù)的各個部分的方法, 比如說月, 日, 和年. 這些方法現(xiàn)在遭到了批評并且已經(jīng)被轉(zhuǎn)移到了Calendar類里去了, 我們將在本文中進(jìn)一步討論它. 這種改進(jìn)旨在更好的處理日期數(shù)據(jù)的國際化格式. 就象在JDK 1.1中一樣, Date 類實際上只是一個包裹類, 它包含的是一個長整型數(shù)據(jù), 表示的是從GMT(格林尼治標(biāo)準(zhǔn)時間)1970年, 1 月 1日00:00:00這一刻之前或者是之后經(jīng)歷的毫秒數(shù).

          一、創(chuàng)建一個日期對象

          讓我們看一個使用系統(tǒng)的當(dāng)前日期和時間創(chuàng)建一個日期對象并返回一個長整數(shù)的簡單例子. 這個時間通常被稱為Java 虛擬機(jī)(JVM)主機(jī)環(huán)境的系統(tǒng)時間.
          //------------------------------------------------------
          import java.util.Date;

          public class DateExample1
          {
          public static void main(String[] args)
          {
          // Get the system date/time
          Date date = new Date();

          System.out.println(date.getTime());
          }
          }
          //------------------------------------------------------

          1145681088396


          在星期六, 2001年9月29日, 下午大約是6:50的樣子, 上面的例子在系統(tǒng)輸出設(shè)備上顯示的結(jié)果是 1001803809710. 在這個例子中,值得注意的是我們使用了Date 構(gòu)造函數(shù)創(chuàng)建一個日期對象, 這個構(gòu)造函數(shù)沒有接受任何參數(shù). 而這個構(gòu)造函數(shù)在內(nèi)部使用了System.currentTimeMillis() 方法來從系統(tǒng)獲取日期.

          那么, 現(xiàn)在我們已經(jīng)知道了如何獲取從1970年1月1日開始經(jīng)歷的毫秒數(shù)了. 我們?nèi)绾尾拍芤砸环N用戶明白的格式來顯示這個日期呢? 在這里類java.text.SimpleDateFormat 和它的抽象基類 java.text.DateFormat 就派得上用場了.

          二、日期數(shù)據(jù)的定制格式

          假如我們希望定制日期數(shù)據(jù)的格式, 比方星期六-9月-29日-2001年. 下面的例子展示了如何完成這個工作:

          //------------------------------------------------------
          import java.text.SimpleDateFormat;
          import java.util.Date;

          public class DateExample2
          {

          public static void main(String[] args)
          {

          SimpleDateFormat bartDateFormat =
          new SimpleDateFormat("EEEE-MMMM-dd-yyyy");

          Date date = new Date();

          System.out.println(bartDateFormat.format(date));
          }
          }
          //------------------------------------------------------

          星期六-四月-22-2006


          只要通過向SimpleDateFormat 的構(gòu)造函數(shù)傳遞格式字符串"EEE-MMMM-dd-yyyy", 我們就能夠指明自己想要的格式. 你應(yīng)該可以看見, 格式字符串中的ASCII 字符告訴格式化函數(shù)下面顯示日期數(shù)據(jù)的哪一個部分. EEEE是星期, MMMM是月, dd是日, yyyy是年. 字符的個數(shù)決定了日期是如何格式化的.傳遞"EE-MM-dd-yy"會顯示 Sat-09-29-01. 請察看Sun 公司的Web 站點獲取日期格式化選項的完整的指示.

          三、將文本數(shù)據(jù)解析成日期對象

          假設(shè)我們有一個文本字符串包含了一個格式化了的日期對象, 而我們希望解析這個字符串并從文本日期數(shù)據(jù)創(chuàng)建一個日期對象. 我們將再次以格式化字符串"MM-dd-yyyy" 調(diào)用SimpleDateFormat類, 但是這一次, 我們使用格式化解析而不是生成一個文本日期數(shù)據(jù). 我們的例子, 顯示在下面, 將解析文本字符串"9-29-2001"并創(chuàng)建一個值為001736000000 的日期對象.

          //------------------------------------------------------
          import java.text.SimpleDateFormat;
          import java.util.Date;

          public class DateExample3
          {

          public static void main(String[] args)
          {
          // Create a date formatter that can parse dates of
          // the form MM-dd-yyyy.
          SimpleDateFormat bartDateFormat =
          new SimpleDateFormat("MM-dd-yyyy");

          // Create a string containing a text date to be parsed.
          String dateStringToParse = "9-29-2001";

          try {
          // Parse the text version of the date.
          // We have to perform the parse method in a
          // try-catch construct in case dateStringToParse
          // does not contain a date in the format we are expecting.
          Date date = bartDateFormat.parse(dateStringToParse);

          // Now send the parsed date as a long value
          // to the system output.
          System.out.println(date.getTime());
          }
          catch (Exception ex) {
          System.out.println(ex.getMessage());
          }
          }
          }
          //------------------------------------------------------

          1001692800000



          四、使用標(biāo)準(zhǔn)的日期格式化過程

          既然我們已經(jīng)可以生成和解析定制的日期格式了, 讓我們來看一看如何使用內(nèi)建的格式化過程. 方法 DateFormat.getDateTimeInstance() 讓我們得以用幾種不同的方法獲得標(biāo)準(zhǔn)的日期格式化過程. 在下面的例子中, 我們獲取了四個內(nèi)建的日期格式化過程. 它們包括一個短的, 中等的, 長的, 和完整的日期格式.

          //------------------------------------------------------
          import java.text.DateFormat;
          import java.util.Date;

          public class DateExample4
          {

          public static void main(String[] args)
          {
          Date date = new Date();

          DateFormat shortDateFormat =
          DateFormat.getDateTimeInstance(
          DateFormat.SHORT,
          DateFormat.SHORT);

          DateFormat mediumDateFormat =
          DateFormat.getDateTimeInstance(
          DateFormat.MEDIUM,
          DateFormat.MEDIUM);

          DateFormat longDateFormat =
          DateFormat.getDateTimeInstance(
          DateFormat.LONG,
          DateFormat.LONG);

          DateFormat fullDateFormat =
          DateFormat.getDateTimeInstance(
          DateFormat.FULL,
          DateFormat.FULL);

          System.out.println(shortDateFormat.format(date));
          System.out.println(mediumDateFormat.format(date));
          System.out.println(longDateFormat.format(date));
          System.out.println(fullDateFormat.format(date));
          }
          }
          //------------------------------------------------------

          01-9-29?上午12:00
          2001-9-29?0:00:00
          2001年9月29日?上午12時00分00秒
          2001年9月29日?星期六?上午12時00分00秒?CST


          注意我們在對 getDateTimeInstance的每次調(diào)用中都傳遞了兩個值. 第一個參數(shù)是日期風(fēng)格, 而第二個參數(shù)是時間風(fēng)格. 它們都是基本數(shù)據(jù)類型int(整型). 考慮到可讀性, 我們使用了DateFormat 類提供的常量: SHORT, MEDIUM, LONG, 和 FULL. 要知道獲取時間和日期格式化過程的更多的方法和選項, 請看Sun 公司W(wǎng)eb 站點上的解釋.

          運行我們的例子程序的時候, 它將向標(biāo)準(zhǔn)輸出設(shè)備輸出下面的內(nèi)容:
          9/29/01 8:44 PM
          Sep 29, 2001 8:44:45 PM
          September 29, 2001 8:44:45 PM EDT
          Saturday, September 29, 2001 8:44:45 PM EDT

          五、Calendar 類

          我們現(xiàn)在已經(jīng)能夠格式化并創(chuàng)建一個日期對象了, 但是我們?nèi)绾尾拍茉O(shè)置和獲取日期數(shù)據(jù)的特定部分呢, 比如說小時, 日, 或者分鐘? 我們又如何在日期的這些部分加上或者減去值呢? 答案是使用Calendar 類. 就如我們前面提到的那樣, Calendar 類中的方法替代了Date 類中被人唾罵的方法.

          假設(shè)你想要設(shè)置, 獲取, 和操縱一個日期對象的各個部分, 比方一個月的一天或者是一個星期的一天. 為了演示這個過程, 我們將使用具體的子類 java.util.GregorianCalendar. 考慮下面的例子, 它計算得到下面的第十個星期五是13號.

          //------------------------------------------------------
          import java.util.GregorianCalendar;
          import java.util.Date;
          import java.text.DateFormat;

          public class DateExample5
          {

          public static void main(String[] args)
          {
          DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL);

          // Create our Gregorian Calendar.
          GregorianCalendar cal = new GregorianCalendar();

          // Set the date and time of our calendar
          // to the system&s date and time
          cal.setTime(new Date());

          System.out.println("System Date: " +
          dateFormat.format(cal.getTime()));

          System.out.println("Befor Setting Day of Week to Friday: " +
          dateFormat.format(cal.getTime())); ?

          // Set the day of week to FRIDAY
          cal.set(GregorianCalendar.DAY_OF_WEEK,
          GregorianCalendar.FRIDAY);
          System.out.println("After Setting Day of Week to Friday: " +
          dateFormat.format(cal.getTime()));

          int friday13Counter = 0;

          while (friday13Counter <= 10)
          {

          // Go to the next Friday by adding 7 days.
          cal.add(GregorianCalendar.DAY_OF_MONTH, 7);

          // If the day of month is 13 we have
          // another Friday the 13th.
          if (cal.get(GregorianCalendar.DAY_OF_MONTH) == 13)
          {
          friday13Counter++;
          System.out.println(dateFormat.format(cal.getTime()));
          }
          }
          }
          }
          //------------------------------------------------------

          ??? Befor Setting Day of Week to Friday: 2006年4月22日 星期六
          After?Setting?Day?of?Week?to?Friday:?2006年4月21日?星期五
          2006年10月13日?星期五
          2007年4月13日?星期五
          2007年7月13日?星期五
          2008年6月13日?星期五
          2009年2月13日?星期五
          2009年3月13日?星期五
          2009年11月13日?星期五
          2010年8月13日?星期五
          2011年5月13日?星期五
          2012年1月13日?星期五
          2012年4月13日?星期五



          在這個例子中我們作了有趣的函數(shù)調(diào)用:
          cal.set(GregorianCalendar.DAY_OF_WEEK,
          GregorianCalendar.FRIDAY);

          和:
          cal.add(GregorianCalendar.DAY_OF_MONTH, 7);

          set 方法能夠讓我們通過簡單的設(shè)置星期中的哪一天這個域來將我們的時間調(diào)整為星期五. 注意到這里我們使用了常量 DAY_OF_WEEK 和 FRIDAY來增強(qiáng)代碼的可讀性. add 方法讓我們能夠在日期上加上數(shù)值. 潤年的所有復(fù)雜的計算都由這個方法自動處理.

          我們這個例子的輸出結(jié)果是:
          System Date: Saturday, September 29, 2001
          當(dāng)我們將它設(shè)置成星期五以后就成了: Friday, September 28, 2001
          Friday, September 13, 2002
          Friday, December 13, 2002
          Friday, June 13, 2003
          Friday, February 13, 2004
          Friday, August 13, 2004
          Friday, May 13, 2005
          Friday, January 13, 2006
          Friday, October 13, 2006
          Friday, April 13, 2007
          Friday, July 13, 2007
          Friday, June 13, 2008

          六、時間掌握在你的手里

          有了這些Date 和Calendar 類的例子, 你應(yīng)該能夠使用 java.util.Date, java.text.SimpleDateFormat, 和 java.util.GregorianCalendar 創(chuàng)建許多方法了.

          posted @ 2006-06-09 16:00 nbt 閱讀(474) | 評論 (1)編輯 收藏

          僅列出標(biāo)題
          共9頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 
          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導(dǎo)航

          統(tǒng)計

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          相冊

          收藏夾

          Java技術(shù)網(wǎng)站

          友情鏈接

          國內(nèi)一些開源網(wǎng)站

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 连山| 彝良县| 绥滨县| 盐边县| 正蓝旗| 县级市| 响水县| 辰溪县| 航空| 天峻县| 霸州市| 宁海县| 鄂伦春自治旗| 溧阳市| 杨浦区| 包头市| 达尔| 思南县| 连江县| 清涧县| 海晏县| 滨海县| 称多县| 武平县| 思茅市| 晋宁县| 赤壁市| 福建省| 丰都县| 利津县| 宁武县| 游戏| 满城县| 呼图壁县| 察哈| 张家口市| 吴旗县| 班玛县| 米脂县| 贵州省| 平乐县|