Struts1.x系列教程(1):用MyEclipse开发第一个Struts程序(二)

简介:
五、通过模型类操作数据库

     在这一节我们来编写用于操作数据库的模型类。由于本例子是 Web 程序,因此,建议在连接数据库时使用数据库连接池。在 <Tomcat 安装目录 >"conf"Catalina"localhost 目录中打开 samples.xml 文件(如果没有该文件,则建立一个 samples.xml 文件),在 <Context> 节点中加入如下的内容:
配置连接池(用于连接数据库 struts
   < Resource  name ="jdbc/struts"  auth ="Container"
                type
="javax.sql.DataSource"
                driverClassName
="com.mysql.jdbc.Driver"
                url
="jdbc:mysql://localhost:3306/struts?characterEncoding=GBK"
                username
="root"
                password
="1234"               
                maxActive
="200"
                maxIdle
="50"
                maxWait
="3000" />

本例中提供了两个可以操作数据库的模型类:Product SearchProduct 。其中Product 用于验证由客户端提交的产品信息,并向t_products 表中写入这些信息。而SearchProduct 类用于对t_products 表的product_name 字段进行模糊查询,并返回查询到的产品信息(包括产品ID 、产品名称和产品价格)。
    由于 Product SearchProduct 都需要使用数据库连接池来连接数据库,因此,可以将连接数据库的工作提出来作为一个父类 (Struts ) 提供,代码如下:

package  util;
import  java.sql.Connection;
public   class  Struts
{
    protected  javax.naming.Context ctx  =   new  javax.naming.InitialContext();
    protected  javax.sql.DataSource ds;
    
protected  Connection conn;
    
public  Struts()  throws  Exception
    {
        ds 
=  (javax.sql.DataSource) ctx.lookup( " java:/comp/env/jdbc/struts " );
        conn 
=  ds.getConnection();   //  从数据库连接池获得一个Connection
    }
}

     <samples 工程目录 >"src 目录中建立一个 Product.java 文件,代码所示:

   package  mystruts.model;
  
  
import  java.sql. * ;
  
import  mystruts.actionform. * ;
  
  
public   class  Product  extends  util.Struts
  {
      
private  ProductForm form;
  
      
public  Product(ProductForm form)  throws  Exception
      {
          
super ();
          
this .form  =  form;
          validate();
      }
      
//  验证客户端提交的数据
       public   void  validate()  throws  Exception
      {
          
if  (form.getProductID().trim().equals( "" ))
              
throw   new  Exception( " 产品ID不能为空! " );
          
if (form.getProductID().length()  >   4 )
              
throw   new  Exception( " 产品ID最长为4位! " );
          
if  (form.getProductName().trim().equals( "" ))
              
throw   new  Exception( " 产品名称不能为空 " );
          
if  (Float.compare(form.getPrice(),  0 <=   0 )
              
throw   new  Exception( " 产品价格必须大于0 " );
      }
      
//  将客户端提交的产品信息保存到t_products中
       public   void  save()  throws  Exception
      {
          
try
          {
              String productID 
=  form.getProductID();
              String productName 
=  form.getProductName();
              
float  price  =  form.getPrice();
              String sql 
=   " INSERT INTO t_products VALUES(' "   +  productID  +   " ', "
                      
+   " ' "   +  productName  +   " ', "   +  String.valueOf(price)  +   " ) " ;
              PreparedStatement pstmt 
=  conn.prepareStatement(sql);
              pstmt.executeUpdate();   
//  执行INSERT语句
              pstmt.close();
              conn.close();
          }
          
catch  (Exception e)
          {
              
throw   new  Exception(e.getMessage());
          }
      }
  }

     Product 类中使用了一个ProductForm 类,这个类是一个ActionForm 类,它的功能是保存客户端提交的数据。关于这个类将在下面详细介绍。Product 类通过构造方法的form 参数将客户端提交的数据传入Product 类的对象实例中,并在构造方法中验证这些数据,如果发现数据不合法,就会抛出一个异常。当客户端提交的数据合法后,成功建立了一个Product 类的对象实例,然后可以通过简单地调用save 方法将数据保存到t_products 表中。
     Product 类似,在 <samples 工程目录 >"src 目录中建立一个 SearchProduct.java 文件,代码如下:

   package  mystruts.model;
  
  
import  java.sql. * ;
  
import  java.util. * ;
  
import  mystruts.actionform. * ;
  
  
public   class  SearchProduct  extends  util.Struts
  {
      
private  ProductForm form;
  
      
public  SearchProduct(ProductForm form)  throws  Exception
      {
          
super ();
          
this .form  =  form;
      }    
      
//  查询产品信息,并通过List返回查询结果
       public  List < String[] >  search()  throws  Exception
      {
          List
< String[] >  result  =   new  LinkedList < String[] > ();
          String sql 
=   " SELECT * FROM t_products WHERE product_name like '% "  
+  form.getProductName()  +   " %' " ;
          PreparedStatement pstmt 
=   conn.prepareStatement(sql);
          ResultSet rs 
=  pstmt.executeQuery();   //  开始执行SELECT语句
           while (rs.next())
          {
              String[] row 
=   new  String[ 3 ];
              row[
0 =  rs.getString( 1 );
              row[
1 =  rs.getString( 2 );
              row[
2 =  rs.getString( 3 );
              result.add(row);
          }
          rs.close();
          conn.close();
          
return  result;
      }
  }

        SearchProduct 类也使用了 ProductForm 类,但在 SearchProduct 中并不会验证 ProductForm 对象实例中的数据,而只是将 ProductForm 对象作为传递查询请求信息(实际上只需要产品名称)的工具而已。

六、实现控制器

    
在这一节要实现的控制器是基于 Struts Web 程序的核心部分之一:控制器实质上也是普通的 Java 类,但这个 Java 类一般要从 org.apache.struts.action.Action 类继承。控制器的主要功能是接受并处理从JSP页面提交的数据、通过模型(Model)和数据库交互以及forward到相应的页面(可以是任何页面,如html、JSP和Servlet等)。在实现控制器之前,需要先实现一个ActionForm类, 这个类的作用是保存JSP页面提交的数据。在<samples工程目录>"src目录中建立一个ProductForm.java文件,代码如下:

   package  mystruts.actionform;
  
  
import  org.apache.struts.action. * ;
  
  
public   class  ProductForm  extends  ActionForm
  {
      
private  String productID;   //  产品ID
       private  String productName;  //  产品名称
       private   float  price;   //  产品价格
       public  String getProductID()
      {
          
return  productID;
      }
      
public   void  setProductID(String productID)
      {
          
this .productID  =  productID;
      }
      
public  String getProductName()
      {
          
return  productName;
      }
      
public   void  setProductName(String productName)
      {
          
this .productName  =  productName;
      }
      
public   float  getPrice()
      {
          
return  price;
      }
      
public   void  setPrice( float  price)
      {
          
this .price  =  price;
      }
  }

     从上面的代码可以看出,ActionForm 类一般从 org.apache.struts.action.ActionForm 类继承,而且在类中需要按着需要保存的数据表字段添加属性。如产品ID的属性是productName。在MyEclipse中可以只定义三个private变量,然后使用MyEclipse的 Source  >  Generate Getters and Setters... 】功能自动产生getter setter 方法。但在给这些属性取名时要注意,private 变量的名子和数据表的字段名没有直接的关系,但必须和JSP 页面中的<html> 标签的property 属性值一致,如<html:text property="productName" /> 表示输入产品名称的文本框,其中property 属性的值就是ProductForm 类中的productName 变量。如果不一致,将会抛出异常。其他和ProductForm 类的属性对应的<html> 标签可以查看上面的代码。
    
光有ActionForm 类还不够,还需要在struts-config.xml 中的<struts-config> 节点中添加如下的内容:
< form-beans >
     < form-bean  name ="saveProductForm"  type =" mystruts.actionform.ProductForm"   />
     < form-bean  name ="searchProductForm"  type ="mystruts.actionform.ProductForm"   />
</ form-beans >

     上面的代码所配置的两个 ActionForm 实际上指的是同一个 ProductForm 类,但这个 ProductForm 类在后面要讲的两个动作里都要使用,为了更容易理解,为这个 ProductForm 起了两个不同的别名( saveProductForm searchProductForm )。
    
下面来实现 saveProduct 动作的代码。 Struts Action 类必须一般从 org.apache.struts.action.Action 类继承。一般在 Struts Action 类需要覆盖 Action 类的 execute 方法。这个方法有每次客户端访问 Struts Action 时调用。我们可以在方法中处理客户端提交的数据,访问数据库等工作。这个方法返回一个 ActionForward 类型的值,表明在执行完 execute 后,要 forward 到的页面。描述 saveProduct 动作的类叫 SaveProductAction 。代码如下:

   package  mystruts.action;
  
  
import  javax.servlet.http. * ;
  
import  org.apache.struts.action. * ;
  
import  mystruts.actionform. * ;
  
import  mystruts.model. * ;
  
  
public   class  SaveProductAction  extends  Action
  {
      
//  在客户端访问saveProduct动作时执行该方法
       public  ActionForward execute(ActionMapping mapping, ActionForm form,
              HttpServletRequest request, HttpServletResponse response)
      {
          ProductForm saveProductForm 
=  (ProductForm) form;
          
try
          {
              Product product 
=   new  Product(saveProductForm);
              product.save();  
//  保存产品信息
              request.setAttribute( " info " " 保存成功! " );   
          }
          
catch  (Exception e)
          {
              request.setAttribute(
" info " , e.getMessage());
          }
          
return  mapping.findForward( " save " );
      }
  }

     SaveProductAction 类中使用了模型类 Product 验证并保存产品信息。并将操作结果信息保存在 request 的属性中, key 为“ info ”。在 execute 的最后,使用了 ActionMapping 类的 findForward 方法在 struts-config.xml 中寻找一个叫“ save ”的 forward 。这个 forward 是一个 JSP 页,用于显示是否将产品信息保存成功的信息。为了可以在 struts-config.xml 中查找这个 forward ,需要在 struts-config.xml <action-mappings> 节点中加入如下的内容。

< action  name ="saveProductForm"  path ="/saveProduct" scope ="request"  type =" mystruts.action.SaveProductAction" >
    < forward  name ="save"  path ="/mystruts/save.jsp"   />
</ action >

     从上面的代码可以看出,那个用于显示保存状态信息的 JSP 页面叫 save.jsp 。在 <samples 工程目录 >"mystruts 目录中建立一个 save.jsp 文件,代码如下:

   < %@ page  pageEncoding ="GBK" % >
  ${requestScope.info}

     IE 中输入如下的URL

    http://localhost:8080/samples/mystruts/newProduct.jsp

    
在文本框中输入相应的信息后,点“保存”按钮,如果输入的数据是合法的,就会将数据保存在t_products 中,否则会显示出错的原因。    searchProduct动作的实现和saveProduct差不多,也会为三步:实现动作类(SearchProductAction)、在struts-config.xml中添加配置信息和实现用于显示查询结果的JSP文件。下面的代码分别显示了这三步所要编写的代码。

SearchProductAction.java
   package  mystruts.action;
  
  
import  javax.servlet.http. * ;
  
import  org.apache.struts.action. * ;
  
import  mystruts.actionform. * ;
  
import  mystruts.model. * ;
  
import  java.util. * ;
  
  
public   class  SearchProductAction  extends  Action
  {
  
      
public  ActionForward execute(ActionMapping mapping, ActionForm form,
              HttpServletRequest request, HttpServletResponse response)
      {
          ProductForm searchProductForm 
=  (ProductForm) form;
          
try
          {
              SearchProduct searchProduct 
=   new  SearchProduct(searchProductForm);
              List
< String[] >  result  =  searchProduct.search();   //  查询产品信息
               if  (result.size()  >   0 )   //  有符合条件的产品信息
              {
                  request.setAttribute(
" result " , result);
                  request.setAttribute(
" info " " 记录数: "   +  String.valueOf(result.size()));
              }
              
else    //  没有查到任何产品信息
                  request.setAttribute( " info " " 没有符合要求的记录! " );
          }
          
catch  (Exception e)
          {
              request.setAttribute(
" info " , e.getMessage());
          }
          
return  mapping.findForward( " search " );
      }
  }
struts-config.xml 中配置 searchProduct 动作
< action  name ="searchProductForm"  path ="/searchProduct"  scope ="request"  type ="mystruts.action.SearchProductAction" >
    < forward  name ="search"  path ="/mystruts/search.jsp"   />
</ action >

search.jsp
   <% @ page pageEncoding = " GBK " %>
  
<% @ taglib uri = " http://struts.apache.org/tags-logic "  prefix = " logic " %>
  
<% @ taglib uri = " http://java.sun.com/jsp/jstl/core "  prefix = " c " %>
  
< html >
      
< body >
<% --  从request的result中取出查询结果  -- %>
          
< c:set  var ="result"  value ="${requestScope.result}"   />
          
< table  width ="100%" >
              
< tr  align ="center" >
                  
< td >
                      ${requestScope.info}
                  
</ td >
              
</ tr >
              
< tr  align ="center" >
                  
< td >
                      
< logic:present  name ="result" >
                          
< table  border ="1" >
                              
< tr  align ="center" >
                                  
< td >  产品ID  </ td >
                                  
< td >  产品名称  </ td >
                                  
< td >  价格  </ td >
                              
</ tr >
                              
< logic:iterate  id ="row"  name ="result" >
                                  
< tr >   < td >  ${row[0]}  </ td >
                                      
< td >  ${row[1]}  </ td >
                                      
< td >  ${row[2]}  </ td >
                                  
</ tr >
                              
</ logic:iterate >
                          
</ table >
                      
</ logic:present >
                  
</ td >
              
</ tr >
          
</ table >
      
</ body >
  
</ html >

     IE 中输入如下的URL

    http://localhost:8080/samples/%20mystruts/searchProduct.jsp

    
在“产品名称”文本框中输入产品名称的一部分,程序就会查询出所有包含输入的产品名称的产品信息,并将结果显示出来。

七、解决 ActionForm 的乱码问题
 
     到现在为止,程序的功能部分已经全部实现完了。但还存在一个问题。当我们在产品名称中输入中文时,虽然将客户端提交的数据成功保存到数据库中,但是在t_products 表中的product_name 字段显示的都是乱码。产生这个问题的原因只有一个,就是客户端提交的数据的编码格式和数据库的编码格式不一致造成的。当然,解决这个问题的方法有很多,但笔者认为最容易的就是使用过滤器。所谓过滤器,就是在客户端提交数据后,在交由服务端处理之前所执行的一段服务端代码(一般为Java 代码)。一个过滤器是一个实现javax.servlet.Filter 接口的类。在本例中要使用的过滤器类叫EncodingFilter ,实现代码如下:

EncodingFilter.java

   package  filter;
  
import  java.io.IOException;
  
import  javax.servlet. * ;
  
public   class  EncodingFilter  implements  Filter
  {
      
public   void  destroy() {  }
      
public   void  doFilter(ServletRequest request, ServletResponse response,
              FilterChain chain) 
throws  IOException, ServletException
      {
          request.setCharacterEncoding(
" GBK " );   //  将客户端提交的数据设为GBK编码格式
          //  继续处理客户端提交的数据,如果不写这条语句,Servlet引擎将不会处理所过滤的页面
          chain.doFilter(request, response);      
      }
      
public   void  init(FilterConfig filterConfig)  throws  ServletException {   }  
  }
    Filter 接口的doFilter 方法是过滤器的核心方法。其中FilterChain 类的doFilter 方法允许继续处理客户端提交的数据。我们还可以使用这个方法来临时关闭Web 站点的某个或全部的页面(根据过滤器的设置而定)。由于本书的数据库使用的是GBK 编码格式,因此,需要使用ServletRequest setCharacterEncoding 方法将客户端提交的数据也设为GBK 编码格式。
     除了实现过滤器类,我们还需要在web.xml 中的<web-app> 节点加入如下的配置信息才能使过滤器生效:
web.xml 中配置过滤器

< filter >
    < filter-name > EncodingFilter </ filter-name >
    < filter-class >
        filter.EncodingFilter
    </ filter-class >
</ filter >
< filter-mapping >
    < filter-name > EncodingFilter </ filter-name >
    < url-pattern > /* </ url-pattern >
</ filter-mapping >

    在重新启动Tomcat后,重新输入一条带中文的产品信息,看看是否可以将中文保存在数据库中?




 本文转自 androidguy 51CTO博客,原文链接:http://blog.51cto.com/androidguy/215248,如需转载请自行联系原作者


相关文章
|
存储 Java 关系型数据库
JSP考试质量分析系统myeclipse开发mysql数据库bs框架java编程web网页结构
JSP 考试质量分析系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0,使用java语言开发,系统主要采用B/S模式开发。
223 1
|
Java 关系型数据库 MySQL
JSP考试报名管理系统myeclipse开发mysql数据库bs框架java编程web网页结构
二、功能介绍 (1)权限管理:对权限信息进行添加、删除、修改和查看 (2)用户管理:对用户信息进行添加、删除、修改和查看 (3)公告管理:对公告信息进行添加、删除、修改和查看 (4)考试科目管理:对考试科目信息进行添加、删除、修改和查看 (5)考试安排管理:对考试安排信息进行添加、删除、修改和查看 (6)报名管理:对报名信息进行添加、删除、修改和查看,审核, (7)用户登录、身份验证 三、注意事项 1、管理员账号:admin密码:admin 数据库配置文件DBO.java 角色:普通用户,管理员 2、开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql
148 0
|
Java 关系型数据库 MySQL
JSP在线客户服务支持管理系统myeclipse开发mysql数据库bs框架java编程jdbc
JSP 在线客户服务支持管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。
76 0
|
Java 关系型数据库 MySQL
JSP 科研管理系统myeclipse开发mysql数据库bs框架java编程jdbc
JSP 科研管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0,使用java语言开发。系统主要采用B/S模式开发。
57 0
|
Java 关系型数据库 MySQL
JSP实践教学平台系统myeclipse开发mysql数据库bs框架java编程jdbc
JSP 实践教学平台系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0,数据库文件名是jspskcsjpt.sql,系统名称kcsjpt,使用java语言开发系统主要采用B/S模式开发。
72 0
|
Java 数据库连接 数据库
JSP奖学金管理系统myeclipse开发sqlserver数据库bs框架java编程jdbc
JSP 奖学金管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为SQLSERVER2008,使用java语言开发,系统主要采用B/S模式开发。
67 0
|
SQL Java 数据库连接
JSP商品进出库管理系统myeclipse开发sql数据库bs框架java编程jdbc
JSP 商品进出库管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为SQLSERVER2008,使用java语言开发,系统主要采用B/S模式开发。
83 0
|
SQL Java 数据库连接
JSP婚纱影楼管理系统myeclipse开发sql数据库bs框架java编程jdbc
JSP 婚纱影楼管理系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为SQLSERVER2008,使用java语言开发,系统主要采用B/S模式开发。
79 0
|
Java 关系型数据库 MySQL
JSP学生交流论坛系统myeclipse开发mysql数据库bs框架java编程jdbc
JSP 学生交流论坛系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0,使用java语,言开发系统主要采用B/S模式开发。 https://www.bilibili.com/video/BV1jB4y1q7Ut?spm_id_from=333.999.0.0
98 0
|
SQL Java 数据库连接
JSP网上相亲交友系统myeclipse开发sql数据库bs框架java编程jdbc
JSP 网上相亲交友系统是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为sqlserver2008,使用java语言开发,系统主要采用B/S模式开发。
104 0