随笔 - 4  文章 - 10  trackbacks - 0
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(1)

随笔档案

文章分类

文章档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

Struts学习心得之Struts流程篇(1) 
刚接触Struts,刚接触MVC架构,或者刚接触任何新东西,我觉得首先要搞清楚流程,要对新事物有一个大概的、总体的认识,先有感性认识,先培养起来兴趣是非常重要的。下面就把我学习Struts的总体业务流程通过一个实例来进行概括,有什么错误和不妥之处,请你发表评论指教!
(1)搭建环境
   1、获得struts的支持包。struts是apache开源基金组织的一个子项目,你可以从http://struts.apache.org/download.cgi 下载struts的source或者Binaries,目前最新版本是1.2.4。
  2、使用Tomcat作为jsp/Servlet容器。本文使用Tomcat,如果没有此软件,请从http://jakarta.apache.org/tomcat/index.html 下载。
  3、在Tomcat中建立站点(相当于MS IIS虚拟目录)。譬如下面的代码在Tomcat中建立一个站点study,建好以后此站点的地址即为:http://127.0.0.1:8080/study 。Tomcat的全局配置文件server.xml位于安装目录的conf文件夹下。
  <Context path="/study" docBase="g:\java\webapps" debug="0" crossContext="true" reloadable="true">            
 
</Context>
从站点配置可以看出,此站点的绝对路径位于g:\java\webapps\下,关于tomcat配置的详细信息,请参阅相关文章。
 4、在站点(绝对路径)下创建web站点的目录结构。此步省略
 5、将struts的支持包struts.jar拷贝到站点的lib目录下,即g:\java\webapps\WEB-INF\lib;将struts的标记库描述文件拷贝到/WEB-INF/tag/目录下,这个路径和将来导入标记库有关,在后面也有描述。
 6、站点的配置文件web.xml;此步的目的是让tomcat将*do的请求转发到org.apache.struts.action.ActionServlet,然后读入struts的配置文件struts-config.xml。配置信息如下:
<!-- ========== Struts Configuration ======================== -->
  
    
<servlet>
      
<servlet-name>action</servlet-name>
      
<servlet-class>
        org.apache.struts.action.ActionServlet
      
</servlet-class>
      
<init-param>
        
<param-name>config</param-name>
        
<param-value>
         /WEB-INF/struts-config.xml
        
</param-value>
      
</init-param>
      
<load-on-startup>1</load-on-startup>
    
</servlet>

     
<servlet-mapping>
      
<servlet-name>action</servlet-name>
      
<url-pattern>*.do</url-pattern>
    
</servlet-mapping>
可以看出,struts的配置文件位于g:\java\webapps\WEB-INF目录下。

   到此,前期配置工作基本完成,关于strus的配置文件struts-config.xml的使用和详细信息,请见下一节。
 上一节我们搭建了Struts的运行和开发环境。这一节着重讲述MVC的基本概念和与使用JSP/JavaBean模式开发Web应用的比较。
(1)Tomcat的启动。
        从上一节的Tomcat的配置文件中,我们可以看到关于Struts的配置,当Tomcat启动时,会加载Struts的配置文件struts-config.xml,关于配置文件的内容请见
 (2)JSP/JavaBean开发Web应用
     在asp的时代,我们还没有讨论什么开发模式,也没有顾及MVC(虽然MVC的概念早已出现)。用asp开发不外乎以下两种情况,一、就是直接将代码集成到asp文件中,经验多的话,会将常用的函数放至一起,引用时只需include即可;二、对于复杂的应用,如文件上传等,我们会用其他语音如VB、Delphi等写一个控件(ADO即属于此类)。
     当java流行,JSP逐渐成熟,也正是模式、框架流行的时代,所以我们不管是看java的类库,还是看现在流行的框架,无一没有模式的存在。当你初接触JSP的时候,就可以看到书上说“尽量少的在jsp中插入Java代码”,这句话已是模式运用的端倪。
      下面我们先不管MVC,先从JSP/JavaBean来看Web的开发。这种模式很想上面提到的asp开发的第二种情况,我们将业务逻辑放到JavaBean中,只用JSP去表示页面。
       有过asp经验都知道,在接收表单数据的时候,我们不得不一个一个将数据接收过来,以至于有很长的一段如:CustomId = request("CustomId")的代码。而在JSP中,我们不用这么繁琐,一个我们可以用EL直接表示即可,另外我们可以利用javaBean的introspection机制。直接将表单的数据映射到javabean的private变量中,当然javabean中必须包含getter和setter函数(有很幸运,很多的开发工具可以自动生成,又减少了工作量)。下面是一个示例。
       
<jsp:useBean id="prof" scope="page" class="register.Profile" />
<jsp:setProperty name="prof" property="*" />
       我们只要表单的action页面中,直接插入以上代码(这些代码就不用解释了吧),就可以将表单中的数据映射到register.Profile这个javabean中,所以我们可以在javabean中实现业务逻辑,譬如数据的插入、修改、删除等。从而可以减小甚至消除JSP中的java代码量。
 (3)MVC模式
     上面提到的JSP/JavaBean与MVC模式很接近,但是还有很多差别。前者,我们可以看出,在javabean中有很多的逻辑代码,我们要控制页面的跳转,还是要在JSP中读取javabean中的某些标志,嵌入java代码来实现,这看起来显得有些笨拙。我们是否能在JSP和javabean中再加一层,专门来实现跳转即控制页面的输出呢?of course,这就是MVC的思想。
      Struts就是一个实现MVC模式的WEB开发框架,在Struts中用JSP作为Viewer,javabean继承自ActionForm来映射JSP表单数据,用继承自Action的类来实现Controller,而Model没有特殊定义,它可以是EJB,普通Bean或者Web服务,总之Model中集成了业务逻辑的实现,在Controller中去调用,完成后Controller控制显示页面(jsp文件)。
     这样一来,是不是业务流程非常的清晰?

     下面我们付诸实践,实现一个用户注册的简单实例!

Struts学习心得之Struts流程篇(3) -示例

    上一篇我们讲了Struts的配置以及运行环境,这一篇我们通过一个实例来说明Struts实现MVC的过程和Struts开发WEB应用的一般方法。
     (1)实例介绍
       这是《论文在线提交》系统的用户注册部分,用户填入用户名(userid)和Email地址(email)后,如果Email和userid在数据库中不存在,则注册成功,将系统生成的8位密码发送到用户的信箱里。数据表定义如下:
    
CREATE TABLE passwd (
  userid varchar(
20) DEFAULT '' NOT NULL,       #用户id
  password varchar(
16) DEFAULT '' NOT NULL,     #密码 使用PASSWORD()加密后的
  email  varchar(
50) DEFAULT '' NOT NULL,       #email
  PRIMARY KEY (userid),
  KEY password (password)
);

      (2)不使用MVC模式的实现
        有过ASP设计经验的开发人员,如果看到这样一个功能,那简直是太简单了。只要设计一个表单,然后post给一个asp页面,在这个页面中实现数据检查(检查email和用户名是否存在)及数据插入和email发送的功能。如果纯用jsp实现,基本流程也是一样的。这样做有什么不好呢?我们先看使用Struts的MVC来实现这样的功能,然后我们再做一下比较。
       (3)使用Struts MVC实现
         如果使用框架,我们就必须按照框架进行编程,而不是“自由”的编程,我们必须在实现中有M,有V、有C。下面看一下Struts实现MVC的一般流程。
         i. 这是HTML中表单的定义,action指定要将表单中的数据提交给谁进行处理,看以下几种情况:1. 纯用jsp,action肯定是一个jsp文件;2.使用jsp/JavaBean方式,action也是一个jsp,但是它将form中的数据映射到javaBean中,然后在jsp文件中进行获取和处理;3. 采用MVC方式,这要转变一下思路,脑子中要时刻清醒,M是什么,V是什么,C是什么,并且要理解它们的用途,不可用错和滥用。下面我们看一下Struts中MVC的表现方式和使用方法。
       ii 首先我们看M、V和C的表现。在Struts中,
          首先看viewer,这是表现层,主要有jsp、servelt和javabean组成。也就是说我们将表单的数据放到javabean中,这个过程都是viewer的工作;
          Controller,控制器主要是实现数据的验证,并且实现跳转,就是要将控制权交给“谁”。譬如:在用户注册中,当用户将数据传到bean,然后到action时,action去判断email是否存在,如果存在将页面跳转到error.jsp或者输出错误信息,如果不存在就跳转到注册成功的页面

       
  Model,这是业务逻辑,这在Struts中没有强制定义,主要功能就是实现业务逻辑,是功能体,譬如实现数据库的插入,删除等。可以是POJO,也可以是EJB等。
        (4)用Struts实现用户注册。
          第一步、实现viewer,有以下几个部分组成,signin.jsp(显示输入form和错误显示)、SignForm.java(一个javaBean,不过在Struts中要继承自ActionForm,实现数据映射和简单的验证)。一下是关键代码:
signin.jsp
<font color=red>
<html:errors/>   ---错误处理 详细信息见本blog《Struts中的错误处理流程》
font>
  
<html:form action="/sign.do">
  --- sign.do是一个Action,在解释Struts
-conf.xml时说明

         
<bean:message key="sign.userid"/><html:text property="userid"/><br>
         
<bean:message key="sign.email"/><html:text property="email"/>
        
<html:submit ><bean:message key="login.signup"/>html:submit>  

      
html:form>

说明:
<bean:message key="sign.userid"/>从资源文件中读取数据,详细信息见本blog的《struts中资源文件的使用》
SignForm.java
 1package user;
 2
 3import javax.servlet.http.HttpServletRequest;
 4
 5import org.apache.struts.action.ActionError;
 6import org.apache.struts.action.ActionErrors;
 7import org.apache.struts.action.ActionForm;
 8import org.apache.struts.action.ActionMapping;
 9
10/**//**
11 * @author han
12 * @company soochow university
13 * 注册bean
14 */

15
public class SignForm extends ActionForm {
16   private String userid = null;
17   private String email = null;
18   private String password = null;
19   
20   
21/**//**
22 * @return Returns the password.
23 */

24
public String getPassword() {
25    return password;
26}

27
/**//**
28 * @param password The password to set.
29 */

30
public void setPassword(String password) {
31    this.password = password;
32}

33
/**//**
34 * @return Returns the email.
35 */

36
public String getEmail() {
37    return email;
38}

39
/**//**
40 * @param email The email to set.
41 */

42
public void setEmail(String email) {
43    this.email = email;
44}

45
/**//**
46 * @return Returns the userid.
47 */

48
public String getUserid() {
49    return userid;
50}

51
/**//**
52 * @param userid The userid to set.
53 */

54
public void setUserid(String userid) {
55    this.userid = userid;
56}

57
58  public void reset(ActionMapping mapping, HttpServletRequest request){
59         userid = null;
60         email = null;
61  }

62
  //验证
63
  public ActionErrors validate(ActionMapping mapping, HttpServletRequest request){
64        ActionErrors errors = new ActionErrors();
65        
66        if(this.userid == null || this.userid.length()<1){
67              errors.add("userid"new ActionError("userid.required"));
68        }

69        
70        if(this.email == null || this.email.length() < 1){
71              errors.add("email"new ActionError("email.required"));
72        }

73        
74        return errors;
75  }

76
}

      从代码我们可以看出,SignForm除了实现bean的getter和setter功能外还实现了简单的验证,即验证userid和email是否为空,若空则出错!
      关于form的action,我们在讲action和编辑struts-config.xml文件时会进行说明。

Struts学习心得之Struts流程篇(3) -示例 续

     第二步:实现controller。在Struts中继承自Action。调用Model,实现数据的深层次检验(email是否存在)和数据的插入,程序的跳转等。代码如下:

SignAction.java
 1/**
 2 * @author han
 3 * soochow university
 4 * 实现Action,controller
 5 */

 6public class SignAction extends Action {
 7    
 8     public ActionForward execute(ActionMapping mapping, ActionForm form,
 9                HttpServletRequest request,HttpServletResponse response
10            ) throws Exception{    
11         
12         /*  参数说明:
13          *  ActionMapping 实现跳转,控制页面
14          *  ActionForm 在viewer中实现的bean,继承自ActionForm,获得form中的数据
15          *  HttpServletRequest   request
16          *  HttpServeletRsponse  response
17          */

18         
19         ActionErrors errors = new ActionErrors();  //错误处理,详细信息见本blog的《Struts错误处理》
20         
21         /*
22          *  得到form中的数据,因为form中的数据在SignForm中,做一类型转换即可;
23          *  这个要在struts-config.xml中进行说明
24          */

25         SignForm sf = (SignForm) form;
26         
27         /*
28          *  调用Model业务逻辑。
29          */

30         SignModel sign = new SignModel();
31         
32         sign.setEmail(sf.getEmail());
33         sign.setUserid(sf.getUserid());
34         
35         /*
36          *  调用Model的findUserByEmail 和 findUserByUserid 判断
37          *  email和userid是否存在。
38          *  如果存在,则添加出错信息,页面跳转到mapping.getInputforward(),需要在
39          *  struts-config.xml中定义。
40          *  关于错误的详细信息请参看本blog的《struts错误处理》文章。
41          */

42         //email existed
43         if (sign.findUserByEmail()){
44             errors.add("email.existed",new ActionError("email.existed", sign.getEmail()));
45             this.saveErrors(request, errors);
46             return mapping.getInputForward();             
47         }

48     
49         //userid existed
50         if (sign.findUserByUserid()){
51             errors.add("userid.existed"new ActionError("userid.existed",sf.getUserid()));
52             this.saveErrors(request, errors);
53             return mapping.getInputForward();
54         }

55         
56         /*
57          * 调用Model的sendPassword将系统生成的密码发送到用户信箱。
58          * 如果发生错误转到mapping.getInputForward(),这个需要在struts-config.xml中定义
59          * 详细信息见后面的struts-config.xml文件说明
60          */

61         if (sign.sendPassword()){
62             sign.saveNewUser();
63         }
else{  //邮件发送错误
64             errors.add("email.send.error"new ActionError("email.send.error", sf.getEmail()));
65             this.saveErrors(request, errors);
66             return mapping.getInputForward();
67         }

68                  
69        /*
70         *     如果注册成功,页面跳转到mapping.findForward("home")
71         *  这个需要在struts-config.xml中定义
72         *  详细信息见后面的struts-config.xml文件说明
73         */

74         return mapping.findForward("home");
75         
76         
77     }

78}

说明:
           1、SignAction实现MVC中的controller,通过mapping参数来实现跳转,在controller中调用了Model中的一些操作,根据操作结果来实现跳转。
            2、程序中包括了Struts的错误处理(请见本blog的《struts错误处理》)、资源文件的使用,并且好多处代码都和struts的配置文件struts-config.xml有联系
            3、关键代码处都有详细的注释,若还有疑问,请您留言,我们共同探讨。
     第三步:实现Model,业务逻辑。用户注册程序比较简单,主要实现findUserByUserid()、findUserByEmail()、sendPassword()、saveNewUser()等功能。代码如下:
    
SignForm.java 
  1/**
  2 * @author han
  3 * soochow university
  4 * 用户注册的Model
  5 */

  6public class SignModel {
  7   private String email;
  8   private String userid;
  9   private String MsgBox = ""
 10   private String password;
 11   private boolean sended;
 12   
 13   
 14/**
 15 * @return Returns the email.
 16 */

 17public String getEmail() {
 18    return email;
 19}

 20/**
 21 * @param email The email to set.
 22 */

 23public void setEmail(String email) {
 24    this.email = email;
 25}

 26/**
 27 * @return Returns the userid.
 28 */

 29public String getUserid() {
 30    return userid;
 31}

 32/**
 33 * @param userid The userid to set.
 34 */

 35public void setUserid(String userid) {
 36    this.userid = userid;
 37}

 38  
 39  //用户名和email是否存在
 40  public boolean findUserByUserid() throws Exception{
 41      String selectsql = "select userid from password where userid = ?";
 42    Mysql mysql = new Mysql(selectsql);
 43    try{        
 44        mysql.setString(1this.userid);
 45        ResultSet rs = mysql.executeQuery();
 46        if(!rs.next()) return false;
 47    }
 catch (Exception e){
 48        throw new Exception("user.select" + e.getMessage());
 49    }
 finally{
 50        mysql.close();
 51    }
        
 52    return true;
 53      
 54  }

 55  public boolean findUserByEmail() throws Exception{
 56      String selectsql = "select * from password where email = ?";
 57    Mysql mysql = new Mysql(selectsql);
 58    try{        
 59        mysql.setString(1this.email);
 60        ResultSet rs = mysql.executeQuery();
 61        if(!rs.next()) return false;
 62    }
 catch (Exception e){
 63        throw new Exception("user.select" + e.getMessage());
 64    }
 finally{
 65        mysql.close();
 66    }
        
 67    return true;
 68  }

 69  
 70  public void saveNewUser() throws HibernateException{
 71      Session session = HibernateUtil.currentSession();      
 72    
 73    Transaction transaction;
 74    try{
 75        transaction = session.beginTransaction();
 76        SignForm newUser = new SignForm();
 77        newUser.setEmail(this.email);
 78        newUser.setUserid(this.userid);
 79        
 80        newUser.setPassword(password);
 81        session.save(newUser);
 82        transaction.commit();
 83    }
catch(Exception e){
 84        //throw new Exception(e);
 85        e.printStackTrace();
 86    }
finally{
 87        HibernateUtil.closeSession();
 88    }

 89  }

 90  
 91  //发送email给用户初始密码
 92  public boolean sendPassword() throws Exception{
 93           
 94      SendMail sendMail = new SendMail();
 95 
 96      sendMail.setFrom(Constants.FROM);
 97      sendMail.setTo(this.email);
 98      sendMail.setSubject(Constants.SUBJECT);
 99      sendMail.setSmtpHost(Constants.smtpHost);
100      
101    //  生成密码
102    password = new RandStringGenerator(8).generatorString();
103      MsgBox = Constants.WELCOME_MESSAGE_HEAD + "\r用户名:"+this.userid+"\r密码:" + this.password + "\r" + Constants.WELCOME_MESSAGE_FOOT;
104      sendMail.setMsgText(MsgBox);
105      
106    
107    
108      try{
109          sendMail.sendnow();
110          sended = true;
111      }
catch (Exception e){
112          System.err.println("send mail error:" + e.getMessage());
113          //throw new Exception("send mail error" + e.getMessage());
114          sended = false;
115       }

116      return sended;
117  }

118}

说明:
        1、saveNewUser()使用了Hibernate作为持久化工具,关于Hibernate请参阅相关资料,也可以留言我们共同讨论。
       2、sendPassword()使用JavaMail发送Email,本文件通过SendMail工具类实现。
       3、密码生成由RandStringGenerator()工具类生成。
       4、工具类可以点击这里下载。

    第四步:配置struts-config.xml。
<!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>
<global-forwards>   全局转发
    <!-- 对应SignAction.java 中的return mapping.findForward("home"); -->
  
<forward name="home" path="/index.jsp"/>
  
<forward name="userhome" path="/user/userhome.jsp"/>
</global-forwards>

<form-beans>
      <!--  bean的声明,这个在下面的Action设置中要用到  -->
         <form-bean name="signForm" type="user.SignForm" />
  
</form-beans>
  
  <!-- 设置Aciton -->
  
<action-mappings>                                
     
<action path="/sign"              对应<form action>中action的值,在signin.jsp中的action=/login.do
            name
="signForm"             设置的formBean,名称对应<from-bean>中的声明,在SignAction.java中对应输入参数ActionForm
            type="user.SignAction"     Action的类
         validate
="true"                  是否验证
            scope
="request"                作用域   这些应该不用解释了
           input
="/user/signin.jsp">      当发生错误时定向的页面,对应SignAction.java中的mapping.getInputForward()
       
     
</action>
  
</action-mappings>  
 
  
<!-- ========== 资源文件定义,详细信息在《Struts中资源文件使用》中说明=========== -->

  
<message-resources parameter="Application"/>
  
</struts-config>

     第五步:调试程序。经过上面的说明和代码示例是不是对Struts中的MVC架构有了比较清晰的了解,我们知道在java特别是j2ee的软件中,需要设置很多的配置文件,刚开始的时候非常烦,特别是频频出错的时候,那种感觉学java的人应该都尝过哦!但是当你彻底了解了配置文件的确切含义,并且能和代码中的内容进行联系时,就会豁然开朗了,就不会觉得象走进死胡同似的。

     有了上面struts-config.xml中的说明,相信你已经和代码联系起来了,如果将这个程序调试成功,那么你就可以说我已经对struts设计MVC Web程序入门了,一旦跨进了这个门槛,你会觉得学习起来是那么的轻松,一些来得是那么自然。

      好了,希望以上三篇文章能带你走进Struts,理解Struts,特别是熟悉Struts的基本流程,当然要想对一种模式由深入的了解,必须要多加实践,从实践中来体验到它的好处。

      最后,希望你能彻底了解Struts,能为你所用。如果有什么意见和评论,请留言,我们共同讨论,共同进步。
      谢谢你的阅读!

posted on 2007-08-17 16:46 冬天出走的猪 阅读(695) 评论(0)  编辑  收藏 所属分类: struts

只有注册用户登录后才能发表评论。


网站导航: