`
roruby
  • 浏览: 335232 次
  • 来自: ...
社区版块
存档分类
最新评论

Struts原理与实践(3)

阅读更多
一、JDBC的工作原理

Struts在本质上是java程序,要在Struts应用程序中访问数据库,首先,必须搞清楚Java Database Connectivity API(JDBC)的工作原理。正如其名字揭示的,JDBC库提供了一个底层API,用来支持独立于任何特定SQL实现的基本SQL功能。提供数据库访问的基本功能。它是将各种数据库访问的公共概念抽取出来组成的类和接口。JDBC API包括两个包:java.sql(称之为JDBC内核API)和javax.sql(称之为JDBC标准扩展)。它们合在一起,包含了用Java开发数据库应用程序所需的类。这些类或接口主要有:
Java.sql.DriverManager
Java.sql.Driver
Java.sql.Connection
Java.sql.Statement
Java.sql.PreparedStatement
Java.sql.ResultSet等

这使得从Java程序发送SQL语句到数据库变得比较容易,并且适合所有SQL方言。也就是说为一种数据库如Oracle写好了java应用程序后,没有必要再为MS SQL Server再重新写一遍。而是可以针对各种数据库系统都使用同一个java应用程序。这样表述大家可能有些难以接受,我们这里可以打一个比方:联合国开会时,联合国的成员国的与会者(相当我们这里的具体的数据库管理系统)往往都有自己的语言(方言)。大会发言人(相当于我们这里的java应用程序)不可能用各种语言来发言。你只需要使用一种语言(相当于我们这里的JDBC)来发言就行了。那么怎么保证各成员国的与会者都听懂发言呢,这就要依靠同声翻译(相当于我们这里的JDBC驱动程序)。实际上是驱动程序将java程序中的SQL语句翻译成具体的数据库能执行的语句,再交由相应的数据库管理系统去执行。因此,使用JDBC API访问数据库时,我们要针对不同的数据库采用不同的驱动程序,驱动程序实际上是适合特定的数据库JDBC接口的具体实现,它们一般具有如下三种功能:
  • 建立一个与数据源的连接
  • 发送SQL语句到数据源
  • 取回结果集

    那么,JDBC具体是如何工作的呢?

    Java.sql.DriverManager装载驱动程序,当Java.sql.DriverManager的getConnection()方法被调用时,DriverManager试图在已经注册的驱动程序中为数据库(也可以是表格化的数据源)的URL寻找一个合适的驱动程序,并将数据库的URL传到驱动程序的acceptsURL()方法中,驱动程序确认自己有连接到该URL的能力。生成的连接Connection表示与特定的数据库的会话。Statement(包括PreparedStatement和CallableStatement)对象作为在给定Connection上执行SQL语句的容器。执行完语句后生成ResultSet结果集对象,通过结果集的一系列getter就可以访问表中各列的数据。

    这里,是讲的JDBC的基本工作过程,实际应用中,往往会使用JDBC扩展对象如DataSource等,限于篇幅,就不在此详细讨论了。

    二、访问数据库所要做的基本配置

    我们以访问MS SQL Server2000数据库为例,介绍其基本的配置情况。首先,要到微软网站去下载JDBC的驱动程序,运行setup.exe将得到的三个文件:msbase.jar、mssqlserver.jar及msutil.jar放在
  • <catalina_home>/webapps/mystruts/WEB-INF/lib目录下。

    在struts-config.xml文件中配置数据源

    这里,有一点要引起大家的注意的,就是,struts-config.xml中配置的各个项目是有一定的顺序要求的,几个主要项目的顺序大致是这样的:

    <ccid_nobr>
    <ccid_code>data-sourcesform-beansaction-mappingsmessage-resourcesplug-in</ccid_code>
    </ccid_nobr>

    在配置时要遵守上述顺序

    <ccid_nobr>
    <ccid_code><data-sources>    <data-source key="A" type="org.apache.commons.dbcp.BasicDataSource">      <set-property property="driverClassName"          value="com.microsoft.jdbc.sqlserver.SQLServerDriver" />      <set-property property="url"          value="jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=mystruts;SelectMethod=cursor" />      <set-property property="username" value="sa" />      <set-property property="password" value="yourpwd" />      <set-property property="maxActive" value="10" />      <set-property property="maxWait" value="5000" />      <set-property property="defaultAutoCommit" value="false" />      <set-property property="defaultReadOnly" value="false" />    </data-source>  </data-sources></ccid_code>
    </ccid_nobr>

    我们来对这段配置代码做一个简单的说明:

    </catalina_home><data-source type="org.apache.commons.dbcp.BasicDataSource" key="A">这句中,如果您的struts应用程序中只配置一个数据源则key="A"可以不要,而配置多个数据源时就要用这个键值区别,也就是说,可以为一个应用程序配置多个数据源让它访问多个数据库。

    <ccid_nobr>
    <ccid_code><set-property property="url"         value="jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=mystruts;        SelectMethod=cursor" /></ccid_code>
    </ccid_nobr>

    这句中的sqlserver://127.0.0.1:1433;DatabaseName=mystruts;的数据库服务器名(本例是用代表本机的ip地址)和数据库名称要与您的具体情况相同。同时,还要注意访问数据库的用户名和口令也要合乎您的实际情况。

    </data-source><set-property property="maxActive" value="10">表示最大的活动连接数,这也说明这些连接是池化(pooling)的。

    </set-property><set-property property="defaultAutoCommit" value="false">表示对数据库的增、删、改操作必须显式地提交。即必须使用connect.commit();这样的命令才能真正让数据库表中的记录作相应的改变。设置成这样方便用户组织自己的数据库事务。

    三、现在我们就来扩展前面我们讲的那个登录的例子,让它访问存储在数据库表中的用户名和口令信息,同时也让它给出的出错信息更明确一些。

    为此,我们先要做一些准备工作,如果您还没有安装MS SQL Server2000请先安装,并下载最新的补丁包。再建一个名为mystruts的数据库,并在该数据库中建一个名为userInfo的表,该表有两个字段既:username和password,它们的字段类型都为varchar(10),其中username为主键。在该表中输入一条记录,username和password的字段值分别为lhb和awave。到此准备工作就基本做好了。

    为了访问数据库,首先,要修改Action类,修改后的代码清单如下:

    <ccid_nobr>
    <ccid_code>package action;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.Action;import org.apache.struts.action.ActionError;import org.apache.struts.action.ActionErrors;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import org.apache.struts.action.ActionServlet;import bussness.UserInfoBo;import entity.UserInfoForm;import javax.sql.DataSource;import java.sql.Connection;import java.sql.SQLException;public final class LogonAction extends Action {  public ActionForward execute(ActionMapping mapping,         ActionForm form,         HttpServletRequest request,         HttpServletResponse response)         throws IOException, ServletException {    UserInfoForm userInfoForm = (UserInfoForm) form;    //从web层获得用户名和口令    String username = userInfoForm.getUsername().trim();    String password = userInfoForm.getPassword().trim();    //声明错误集对象    ActionErrors errors = new ActionErrors();    //声明数据源和连接对象    DataSource dataSource;    Connection cnn=null;    //校验输入    if(username.equals("")){      ActionError error=new ActionError("error.missing.username");      errors.add(ActionErrors.GLOBAL_ERROR,error);    }    if(password.equals("")){      ActionError error=new ActionError("error.missing.password");      errors.add(ActionErrors.GLOBAL_ERROR,error);    }    //调用业务逻辑    if(errors.size()==0){      String validated = "";      try{        //取得数据库连接        dataSource = getDataSource(request,"A");        cnn = dataSource.getConnection();        UserInfoBo userInfoBo=new UserInfoBo(cnn);        validated =userInfoBo.validatePwd(username,password);        if(validated.equals("match")){          //一切正常就保存用户信息并转向成功的页面          HttpSession session = request.getSession();          session.setAttribute("userInfoForm", form);                return mapping.findForward("success");        }      }      catch(Throwable e){        //处理可能出现的错误        e.printStackTrace();        ActionError error=new ActionError(e.getMessage());        errors.add(ActionErrors.GLOBAL_ERROR,error);      }    }    //如出错就转向输入页面,并显示相应的错误信息    saveErrors(request, errors);    return new ActionForward(mapping.getInput());  }}</ccid_code>
    </ccid_nobr>

    注意:dataSource = getDataSource(request,"A");这句中,如果配置中只有一个数据源,且没有key="A",则这句应写为dataSource = getDataSource(request);

    从清单上可以看出,主要就是增加了访问数据库的代码。同时,我们的业务对象的形式也发生了一个变化,原来没有参数,现在有一个代表数据库连接的参数cnn,因此我们也要对业务对象进行适当地修改。

    更改后的业务对象代码清单如下:

    <ccid_nobr>
    <ccid_code>package bussness;import entity.UserInfoForm;import java.sql.Connection;import java.sql.SQLException;import java.lang.Exception;import db.UserInfoDao;public class UserInfoBo {  private Connection cnn=null;  public UserInfoBo(Connection cnn){    this.cnn=cnn;  }  public String validatePwd(String username,String password){    String validateResult="";       try{      UserInfoDao userInfoDao = new UserInfoDao(cnn);      validateResult=userInfoDao.validatePwd(username,password);      if(validateResult.equals("error.logon.invalid")){        //如果用户名与口令不匹配则报此错        throw new RuntimeException("error.logon.invalid");       }      else if(validateResult.equals("error.removed.user")){        //如果找不到用户则报此错,这样用户看到的出错信息会更详细        throw new RuntimeException("error.removed.user");       }    }    catch(Exception e){      throw new RuntimeException(e.getMessage());    }    finally{      try{        if(cnn!=null){          cnn.close();        }      }      catch(SQLException sqle){        sqle.printStackTrace();        throw new RuntimeException("error.unexpected");      }    }    return validateResult;  }}</ccid_code>
    </ccid_nobr>

    这个业务对象的代码还是比较简单的,重点要讲的就是它在validatePwd方法中调用了一个名叫UserInfoDao的对象,它就是真正进行数据库操作的数据访问对象。其代码清单如下:

    <ccid_nobr>
    <ccid_code>package db;import entity.UserInfoForm;import java.sql.*;public class UserInfoDao {  private Connection con;  public UserInfoDao(Connection con) {    this.con=con;  }    public String validatePwd(String username,String password){    PreparedStatement ps=null;    ResultSet rs=null;    String validated="error.logon.invalid";    UserInfoForm userInfoForm=null;    String sql="select * from userInfo where username=?";    try{      if(con.isClosed()){        throw new IllegalStateException("error.unexpected");      }      ps=con.prepareStatement(sql);      ps.setString(1,username);      rs=ps.executeQuery();      if(rs.next()){        if(!rs.getString("password").trim().equals(password)){          return validated;//口令不正确返回口令不匹配信息                  }        else{          validated = "match";//口令正确返回口令匹配信息          return validated;        }      }else{                validated="error.removed.user";//没有找到该用户        return validated;              }    }catch(SQLException e){        e.printStackTrace();        throw new RuntimeException("error.unexpected");    }finally{      try{        if(ps!=null)          ps.close();        if(rs!=null)          rs.close();      }catch(SQLException e){        e.printStackTrace();        throw new RuntimeException("error.unexpected");      }    }  }}</ccid_code>
    </ccid_nobr>

    下面,简单地分析一下数据访问对象的工作过程:

    要访问数据库,一般要经历的如下几个步骤:
    </set-property>
  • 获得到数据库的连接
  • 创建SQL语句
  • 执行SQL语句
  • 管理结果集

    其中,得到数据库的连接本例中是在Action类中完成的,代码如下:
    dataSource = getDataSource(request,"A");
    cnn = dataSource.getConnection();

    Action在调用业务对象时将连接作为一个参数传给业务对象,再由业务对象传给数据库访问对象。

    要说明一点的是,要将struts-legacy.jar文件放在<catalina_home>/webapps/mystruts/WEB-INF/lib目录下。

    我们要在</catalina_home><catalina_home>/webapps/mystruts/WEB-INF/classes目录下再建一个名叫db的子目录,将数据访问类以UserInfoDao.java文件名保存在该子目录中。按照上篇文章介绍的方法,编译各个包中的.java文件。就可以启动Tomcat重新运行您的程序了。

    细心一点的读者可能都注意到了,到目前为止,我们程序中的各种消息都不是用中文表示的,在下一篇文章中,我们将讨论Struts的国际化编程即所谓的i18n编程,对我们在编程中经常遇到的乱码问题也一同作些分析。

    参考文献:
    《JSP Web 编程指南》---电子工业出版社 Jayson Falkner等著 司光亚 牛红等译
    《Java数据库编程宝典》John O'Donahue等著 甑广启 于耀等译
    《Struts in Action》Ted Husted Cedric Dumoulin George Franciscus David Winterfeldt著
    《Programming Jakarta Struts》Chuck Cavaness著
    《Mastering Jakarta Struts》James Goodwill著
    《Struts Kick Start》James Turner Kevin Bedell著 </catalina_home>
  • 分享到:
    评论

    相关推荐

      Struts原理与实践.mht

      Struts原理与实践(1) - Java - New - JavaEye论坛.mht

      Struts原理与实践

      ### Struts原理与实践 #### 一、Struts框架概览 **Struts**框架,作为Java Web开发领域内的一款成熟且广泛应用的框架,自问世以来便受到开发者们的青睐。Struts框架的核心设计理念在于实现MVC(Model-View-...

      Struts原理与实践(罗会波)

      罗会波的《Struts原理与实践》这本书深入浅出地解析了Struts的核心概念和技术,帮助开发者全面理解和掌握这一框架。 1. **MVC设计模式**:Struts将Web应用的业务逻辑、数据模型和用户界面分离,使得开发者可以独立...

      Struts原理与实践(五).rar

      在本资料"Struts原理与实践(五)"中,我们将深入探讨Struts的核心概念、工作流程以及实际应用中的关键点。 首先,Struts框架的基础是MVC模式。Model代表业务逻辑,View负责显示,Controller则协调这两者。在Struts...

      struts原理与实践(三)

      本文主要讨论Struts中JDBC的工作原理以及在实践中的基本配置。 一、JDBC工作原理 JDBC是Java平台提供的一个标准API,它允许Java应用程序与各种类型的数据库进行通信。JDBC的核心包括两个包:java.sql和javax.sql。...

      Struts原理与实践(一) .rar

      Struts是Java Web开发中的一个开源框架,由Apache软件基金会维护。它主要基于Model-View-Controller(MVC)设计模式,旨在简化企业...通过阅读《Struts原理与实践(一)》PDF文档,可以更深入地了解和掌握Struts框架。

      struts原理与实践+指导JAVA学习阶段需研究的开源项目

      提供的文档可能涵盖了这些主题,从"struts原理与实践(1).doc"到"struts原理与实践(7).doc"逐步深入,"Java学习阶段需研究的开源项目.doc"则可能介绍了一些相关的Java学习资源。阅读这些文档将有助于全面理解和掌握...

      初探Struts原理与实践.doc

      6. ActionServlet与RequestDispatcher:Struts的ActionServlet接收请求后,通过RequestDispatcher将请求转发给相应的Action,Action执行完毕后,再通过Dispatcher返回响应到合适的视图。 通过Struts,开发者可以...

      Struts原理与实践(二).rar

      在"Struts原理与实践(二)"这个主题中,我们将深入探讨Struts框架的核心概念、工作原理以及实际应用。 **1. Struts框架的核心组件** - **ActionServlet**: Struts框架的核心控制器,负责接收HTTP请求,解析请求...

      struts原理与实践二)

      在本文中,我们将深入理解Struts的基本原理,并通过一个简单的登录示例来演示其工作流程。 首先,我们需要了解MVC模式。在MVC架构中,Model负责处理数据和业务逻辑,View负责展示用户界面,而Controller则作为两者...

      struts原理与实践(一)

      Struts 是一个开源的Java Web应用程序框架,专为构建企业级Web应用而设计。它遵循Model-View-Controller (MVC)设计模式,旨在...通过学习和实践Struts,开发者可以更好地理解和掌握Web应用的架构设计,提升自身技能。

      struts原理与实践(七)

      Struts 是一个基于MVC(Model-View-Controller)设计模式的Java Web应用程序框架,它主要负责处理用户请求,管理业务逻辑,以及与视图层的交互。在本篇文章中,我们将深入探讨如何利用Struts 实现一个文章发布系统,...

      Struts原理与实践(三).rar

      Struts 2继续发展,提供了与现代开发工具和实践的集成,如RESTful API支持、AJAX集成等。 通过深入理解Struts的工作原理,开发者可以更好地利用其特性,提高开发效率,同时也能为将来学习其他MVC框架打下坚实的基础...

      struts原理与实践(六)

      3. **资源绑定**: 提供本地化的标签和错误消息。这些消息通常存储在`ApplicationResources.properties`文件中,便于进行国际化(i18n)处理。 4. **Jsp tag**: 这些标签用于在JSP页面中生成JavaScript验证,以在...

      struts原理与实践(四)

      Struts 是一个流行的Java Web开发框架,主要用于...在实践中,开发者需要关注字符集的转换,确保在客户端和服务器之间传输数据时不会丢失或混淆信息。同时,合理地组织和管理资源文件,可以使代码更整洁,更容易维护。

      struts原理与实践(五)

      3. 根据用户的文化背景正确格式化日期时间、数字和货币符号等数据。 4. 快速适应新语言和地区的需求。 Struts 实现国际化主要通过两个组件: 1. 一个由应用程序控制器管理的消息类,它引用包含地区特定信息的资源包...

      struts2 原理与实践

      在本文中,我们将深入探讨Struts2的原理和实践,以一个简单的登录示例来阐述其关键组件和工作流程。 首先,我们来看一下开发Struts2应用的基本步骤: 1. **定义视图(Views)**:视图通常由JSP页面组成,负责展示...

      Struts+spring+hibernate学习笔记! - Struts原理与实践 - JavaEye知识库.files

      下面将详细介绍这三个框架的基本概念、工作原理以及它们如何协同工作。 首先,Struts 是 Apache 软件基金会的一个项目,它的主要目的是提供一种结构化的、可扩展的方式来构建基于 Java 的 Web 应用。Struts 通过 ...

    Global site tag (gtag.js) - Google Analytics