随笔-10  评论-22  文章-1  trackbacks-0
  2009年3月13日
Annotation是JavaSE5开始引入的,在Java的世界已是大行其道,各大开源框架Hibernate、Spring等都对它无缝集成,足见其份量了。。
其实很早就出现在程序员的视野,只是关注的比较少:@Override、@SuppressWarnings("unchecked"),开始主要觉得没什么用处,后来公司的框架用到它,感觉还不错。。于是来一记:

在网上搜Annotation的学习资料不是很多,还是用的人不多,比较经典的入门就是这个:实战篇:设计自己的Annotation,很清楚,通俗易懂,这里我就不赘述了。然而仅仅是弄懂它是怎么回事,具体还是没什么用处,这也是大多数开发人员的感觉。

在现在的公司的经历两次框架升级,第一次没有用到Annotation,xml配置文件大行其道:Action跳转、Ibatis sqlmapper、Form表单(我们的表单都是从后台生成的),整个项目xml眼花缭乱,每个模块都有自己专属的配置文件,然后集中到一起处理,而我们最痛苦的莫过于写那大量重复的配置文件。

后来公司接了个ERP的单子,技术总监马上意识到框架该升级了,他技术很牛,我们公司的框架就是他一人写的,两周之后,新框架出炉,xml只保留三分之一:Action跳转、Form表单都不再使用xml配置,而是Annotation横空出世,给我的感觉:它就像一个救世主,让我们的框架重生,它就是这次升级的最大亮点,只有sqlmapper依然保留,这无可厚非,因为它原本是ibatis封装的,Action控制器既不是Struts1,Struts2,也不是Webwork,是总监自己封装的Servlet,Form表单都由后台生成js组件抛到前端,通过反编译看到源码,其实还是很基础的,贴些代码上来看下吧:

1.Action请求部分:
    /**
     * 显示新增页面
     * author YuWenLin
     * date 2010-5-13 上午10:31:57
     * 
@param data
     
*/
    @Action(
"/add.shtml")
    @Permission(
"client.ContractType.add")
    
public void add(ActionData data){
        FormBuilder builder 
= data.getService(FormBuilder.class);
        builder.append(Type.
class);
        builder.setAction(
"client/contract/type/add.do");
        data.put(
"script", builder);
        
//向页面抛出cookie提示信息
        MessageUtil.putMessage(data);
        data.setResulter(
"template");
        data.setPath(
"client/contract/type/type.shtml");
    }
可能大家看得不太明白(每个公司都有自己框架),没有关系,就两句:
@Action("/add.shtml")
它就是负责请求显示新增的页面,就这一句,不需要像我们以前的action.xml(类似Struts2的跳转),干净利索吧,当然底层后台有处理,但是公共的,不需我们管,至于
@Permission("client.ContractType.add")
就是用来处理权限管理的,也是Annotation的使用,就这一句。就权限管理,后面我也会记述。。。

2.再来看看@Action底层的定义:
package org.plugbase.action;

import java.lang.annotation.Annotation;

public interface Action
    
extends Annotation
{

    
public abstract String value();
}
说明下:extends Annotation跟 @interface是一样的效果,只不过前者手动extends,后者自动的。
怎么样,很基础吧,跟jdk源码是一样的。。。

3.JavaBean生成表单:
    @Widget(value="TextBox")
    @Valider({
"notempty","len(2,8)"})
    
public void setName(String name) {
        
this.name = name;
    }
给setter方法加Annotation,@Widget是组件,@Valider是验证
意思就是给name字段生成TextBox组件,并做验证处理,后台有相应的公共js组件,验证控件库调用,我们所有的表单组件都是这样生成的,说实话,这样生成一个页面真有点繁锁,既要写js,又要写后台,前端还要配,还真是有技术含量,呵呵。。。但是它保证一致性,所有表单组件,验证控件,如TextBox我们只有一套,所有人都去调用这一套,不得再重造,因为它是框架。。。

4.@Widget底层定义:
import java.lang.annotation.Annotation;

public interface Widget
    
extends Annotation
{

    
public abstract String value();

    
public abstract String defaultValue();

    
public abstract String dataType();

    
public abstract String dataSource();
}
@Valider类似,当然这些都只是定义、声明,具体怎么用,这里就不贴了,毕竟是人家东西嘛

怎么样,看到这些,似乎觉得Annotation开始起作用了,其实我一直觉得,Annotation就是为xml所生,因为它们俩是死对头,不管单一地用谁,都有缺陷,
只有结合才是完善,正所谓,没有最好,只有更好,合理就行。

在这里我可能没有贴出什么@Annotation技术含量的东西,但是我想要表达的是一种思想,一种框架的思想,并不是什么地方都能用到Annotation,一般的中小型项目根本没必要用它,因为xml就搞定,所以用在需要用的地方,将它的能量发挥到最大。。。

以上仅为一家之言,欢迎拍砖。。。

posted @ 2010-08-10 16:47 独孤行 阅读(1682) | 评论 (1)编辑 收藏
     摘要: 在项目中使用ibatis有一段时间了,之前一直用jdbc、hibernate。自我感觉ibatis是介于jdbc和hibernate之间的非常实用的轻量级框架,相信用过的人都有同感吧。对搞java的来说,上手是非常快的,只要你具备sql基础,再加一点ORM的思想,夏昕的《ibatis开发指南》是不错的选择。 今天项目搞完了,我就把所学的,以及在项目中用到拿来贴一番,也是对我个人技术的总结吧,怎样...  阅读全文
posted @ 2010-04-01 11:35 独孤行 阅读(3333) | 评论 (0)编辑 收藏
thickbox是jQuery的一个插件,其作用是弹出对话框、网页框,使用户体验度更加愉悦,下面就来简单介绍它的几种用法。
声明一下:这只是个人的总结记载而已。
准备工作:你需要三个文件:thickbox.js、thickbox.css、jquery.js,网上到处可下
具体使用:
第一步:将这三个文件引入到你要使用thickbox的页面
<script type="text/javascript" src="jquery.js"></script> 
    
<script type="text/javascript" src="thickbox.js"></script>
    
<link rel="stylesheet" href="thickbox.css" type="text/css" />
第二步:一般简单使用就是给<a>标签和Button添加样式:class=thickbox
还有就是通过thickbox函数调用:如tb_init()、tb_show();见下文。
几种不同用法:
1.点击显示图片:
 <a href="001.jpg" class="thickbox"><img src="001.jpg"/></a>
ok,就这样搞定
2.点击按钮或链接:
<input alt="#TB_inline?height=300&width=400&inlineId=div1" title="shawnliu" class="thickbox" type="button" value="Show" />   
   
<a href="#TB_inline?height=155&width=300&inlineId=div2&modal=true" class="thickbox">Show hidden modal content.</a>
   
   
<div id="div1" style="display:none">
   
<P>
     这是一个非模式对话框。
   
</P>
   
</div>

   
<div id="div2" style="display:none">
   
<P>
     这是一个模式对话框。
     
<p style="TEXT-ALIGN: center"><INPUT id="Login" onclick="tb_remove()" type="submit" value="  Ok  " /></p>
   
</P>
   
</div>
说明:给你要使用thickbox的<a>或button添加"#TB_inline?height=300&width=400&",#TB_inline是thickbox固定用法,height和width是显示弹出对话框的大小参数,inlineId是你要显示的标签或组件,modal是模式与非模式的选择,当然你还可以接很多你自定义的参数
3.一般在项目中用得比较多的就是加载form的页面,如添加,编辑在同一个list列表页面,这时我们就可以将添加和编辑都做成thickbox形式,如下图:

怎样做呢一样的,给添加链接加thickbox样式:
<a href="add.shtml?width=300&height=250" class="thickbox">新增</a>
前提是你得将要显示的页面(add.shtml)做好,然后指定你要显示的大小
编辑同样是一样:先将原信息提取出来,再让用户修改:

代码也一样:
<a href="edit.shtml?width=300&height=250&nid=item.nid" class="thickbox">编辑</a>
4.能自己定位到需要用thickbox的元素,不使用样式,可以用函数,如:
<div id="PicList">
<a href="Pic01.jpg"><img src="Pic01s.jpg" border="0"/></a>
<a href="Pic02.jpg"><img src="Pic01s.jpg" border="0"/></a>
</div>

$(function() {
tb_init(
"#PicList a[img]");});
5.通过ajax加载的页面,thickbox样式会失效,解决办法:
只要在AJAX载入HTML并更新到页面后执行下以下代码:
tb_init('.thickbox');
6.自定义函数调用:
如点击缩图,要显示大图,缩略图URL只不过在大图URL的后缀前加了s:
<div id="PicList">
<img src="Pic01s.jpg" border="0"/>
<img src="Pic01s.jpg" border="0"/>
</div>

$(function() {
$(
"#PicList img").click(function() {
tb_show(
"",this.src.substring(0,this.src.length-5)+'.jpg',false);
});});
另外,如果想用其它事件,还可以将click改成你想触发thickbox的事件。
下班勒,大概记录到这,以后再加吧。。。


posted @ 2010-03-26 17:47 独孤行 阅读(4619) | 评论 (2)编辑 收藏

在域模型(实体域)中,关联关系是类与类之间最普遍的关系。根据UML语言,关系是有方向的。下面以客户(Customer)和订单(Order)的关系为例,阐述一下ORM的中的一对多映射:
我们知道,在关系数据库中,只存在外键参照关系,而且总是由“many”方参照“one“方。
1.建立多对一单向关联——Order(many)--->Customer(one):
-------------------------------Order.java--------------------------------

pack mypack;
import java.io.Serializable;
public class Order implements Serializable{
   
private int id;
   
private String orderNumber;
   
private Customer customer;
   
   
//构造方法及set方法get方法
   
}
在以上代码中customer属性要使用<many-to-one>来映射:
多对一单向关联(many方)
<many-to-one>
    name 
= "customer"   --待映射的持久化类属性名
    column 
= "customer_Id"  --数据库外键字段
    
class = "mypack.Customer"  --持久化类
    not
-null = "true"/>
a.  <many-to-one>的not-null属性 
not-null属性会影响Hiberntae的运行时行为,Hibernate在保存Order对象时,会先检查它的customer属性是否为null:
若为null:在执行session.save(Order)时会抛出PropertyValueException异常;
原因很简单:既然Customer为null,那么对应的外键Customer_Id也为null,试问外键都没有,Order表的数据能插得进去吗
若将not-null 属性设为false:表示外键引用可以为null,试想一下,数据库数据可以插进去吗?
我们来看:在执行session.save(Order)时,发出了sql语句:insert into......
但是当Hibernate自动清理(flush)缓存时,抛出新的异常:TransientObjectException
所谓清理是提交事务或手动Flush,将session与数据库保持同步,很显然不可能同步嘛,Order对象虽然持久化,但Customer没有.
    注:是否应该把<many-to-one>的not-null属性设为true,这根据实际业务而定。通常,订单总是由客户自己发出,因此建议设为true.
b.  级联保存与更新
默认情况下,Hibernate持久化一个对象,不会自动持久化所关联的其它临时对象,因此会有TransientObjectException,
想它关联也可以,<many-to-one>中加个属性cascade="save-update"即可.

2.建立一对多关联——Customer(one)--->Order(many):
-----------------------------Customer.java-------------------------------
package mypack;
import 
public calss Customer implements Serlizliab;e{
    
private int id;
    
private String name;
    
private Set orders = new HsahSet();

    
//构造方法及set方法get方法
}
一对多关联(one方)
<set 
      name 
= "orders"  --持久化对象的属性
      cascade 
= "save-update" --级联操作
      
<key cloumn = "customer_Id"/> --外键
      
<one-to-many class = "mypack.Order"/> --持久化类
</set>
a.  <set>元素的inverse属性
  在映射一对多的双向关联时,应该在“one”方把inverse属性设为true,这样可提高应用性能。
                    inverse:控制反转,为true表示反转,由它方负责;反之,不反转,自己负责;
                    如果不设,one和many两方都要负责控制,因此,会引发重复的sql语句以及重复添加数据,
        在建立两个象的双向关系时,应该同时修改关联两端的对象属性:
                    customer.getOrders().add(order);
                    order.setCustomer(customer);

        这样做可提高业务逻辑的独立性,使业务逻辑的程序代码不受Hibernate实现的影响。同理解除双向关系也一样。
b.  级联删除(从数据库删除相关表记录)
         当删除Customer对象时,及联删除Order对象.只需将cascad属性设为delete即可.
          注:删除后的对象,依然存在于内存中,只不过由持久化态变为临时态.
c.  父子关系(逻辑删除,只是解除了关联关系)
         自动删除不再和Customer对象关联的Order对象.只需将cascade属性设为delete-orphan.
                     customer.getOrders().remove(order);
                     order.setCustomer(null);
          注:当关联双方都存在父子关系,就可以把父方的cascade属性设为delete-orphan,所谓父子关系,是由父方来控制子方的生命周期.
                     
       


posted @ 2009-10-16 00:29 独孤行 阅读(3318) | 评论 (2)编辑 收藏

My97DatePicker是一款非常灵活好用的日期控件,在本次项目中我使用它暴露了很多问题:

首先来说使用步骤:

1.在My97DatePicker主页下载控件,

目前的版本是:4.2 正式版 发布于2008-12-03

http://www.my97.net/dp/down.asp

2.将文件解压包(一个文件都不要删除)拷贝到classpath/webroot下

3.直接使用<script />引入:

<script type="text/javascript" defer="defer" src="<%=request.getContextPath() %>/My97DatePicker/WdatePicker.js"></script>

4.在<input type="text"/>中调用:

<input type="text" name="time" onfocus="WdatePicker()">

其次来说一下我在使用中碰到的问题:

1.IE中 无法打开internet站点 。。。。。已终止操作

这个问题搞了好半天,网上到处查,最后才在csdn上看到解决办法:

a.如果页面有<base/>标签的:则要在第3步js引入后添加<base target="_self" />;

b.在<script/>中添加属性defer="defer"; //就是这具属性救了我

2.在步骤4中调用了,结果不出来:

开始以为是stuts1.2 标签的原因,结果不是,后来反复测试,才搞定了

其实调用的时候有很多方法,然而有的方法不一定出得来,所以要反复测试

这是My97DatePicker的主页:http://www.my97.net

里面有控件下载,使用演示,问题解决等

posted @ 2009-05-14 00:28 独孤行 阅读(10430) | 评论 (9)编辑 收藏
     摘要: 七、AJAX开发   到这里,已经可以清楚的知道AJAX是什么,AJAX能做什么,AJAX什么地方不好。如果你觉得AJAX真的能给你的开发工作带来改进的话,那么继续看看怎么使用AJAX吧。 7.1、AJAX应用到的技术   AJAX涉及到的7项技术中,个人认为Javascript、XMLHttpRequest、DOM、XML比较有用。 A、XMLHttpRequest对象   XML...  阅读全文
posted @ 2009-03-29 20:11 独孤行 阅读(207) | 评论 (0)编辑 收藏

因为正在自学Ajax,看到作者柯自聪的这篇《AJAX开发简略》写得不错,就拿来转载一下:

         在使用浏览器浏览网页的时候,当页面刷新很慢的时候,你的浏览器在干什么?你的屏幕内容是什么?是的,你的浏览器在等待刷新,而你的屏幕内容是一片空白,而你在屏幕前苦苦的等待浏览器的响应。开发人员为了克服这种尴尬的局面,不得不在每一个可能需要长时间等待响应的页面上增加一个DIV,告诉用户“系统正在处理您的请求,请稍候……”。

  现在,有一种越来越流行越热的“老”技术,可以彻底改变这种窘迫的局面。那就是AJAX。如今,随着Gmail、Google-maps的应用和各种浏览器的支持,AJAX正逐渐吸引全世界的眼球。

一、AJAX定义
   AJAX(Asynchronous JavaScript and XML)其实是多种技术的综合,包括Javascript、XHTML和CSS、DOM、XML和XSTL、XMLHttpRequest。其中:

  使用XHTML和CSS标准化呈现,使用DOM实现动态显示和交互,使用XML和XSTL进行数据交换与处理,使用XMLHttpRequest对象进行异步数据读取,使用Javascript绑定和处理所有数据。

  在AJAX提出之前,业界对于上述技术都只是单独的使用,没有综合使用,也是由于之前的技术需求所决定的。随着应用的广泛,AJAX也成为香饽饽了。

二、现状与需要解决的问题
  传统的Web应用采用同步交互过程,这种情况下,用户首先向HTTP服务器触发一个行为或请求的呼求。反过来,服务器执行某些任务,再向发出请求的用户返回一个HTML页面。这是一种不连贯的用户体验,服务器在处理请求的时候,用户多数时间处于等待的状态,屏幕内容也是一片空白。如下图:

        自从采用超文本作为Web传输和呈现之后,我们都是采用这么一套传输方式。当负载比较小的时候,这并不会体现出有什么不妥。可是当负载比较大,响应时间要很长,1分钟、2分钟……数分钟的时候,这种等待就不可忍受了。严重的,超过响应时间,服务器干脆告诉你页面不可用。另外,某些时候,我只是想改变页面一小部分的数据,那为什么我必须重新加载整个页面呢?!当软件设计越来越讲究人性化的时候,这么糟糕的用户体验简直与这种原则背道而驰。为什么老是要让用户等待服务器取数据呢?至少,我们应该减少用户等待的时间。现在,除了程序设计、编码优化和服务器调优之外,还可以采用AJAX。

三、为什么使用AJAX
  与传统的Web应用不同,AJAX采用异步交互过程。AJAX在用户与服务器之间引入一个中间媒介,从而消除了网络交互过程中的处理—等待—处理—等待缺点。用户的浏览器在执行任务时即装载了AJAX引擎。AJAX引擎用JavaScript语言编写,通常藏在一个隐藏的框架中。它负责编译用户界面及与服务器之间的交互。AJAX引擎允许用户与应用软件之间的交互过程异步进行,独立于用户与网络服务器间的交流。现在,可以用Javascript调用AJAX引擎来代替产生一个HTTP的用户动作,内存中的数据编辑、页面导航、数据校验这些不需要重新载入整个页面的需求可以交给AJAX来执行。

使用AJAX,可以为ISP、开发人员、终端用户带来可见的便捷:

  • 减轻服务器的负担。AJAX的原则是“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器造成的负担。
  • 无刷新更新页面,减少用户心理和实际的等待时间。特别的,当要读取大量的数据的时候,不用像Reload那样出现白屏的情况,AJAX使用XMLHTTP对象发送请求并得到服务器响应,在不重新载入整个页面的情况下用Javascript操作DOM最终更新页面。所以在读取数据的过程中,用户所面对的不是白屏,是原来的页面内容(也可以加一个Loading的提示框让用户知道处于读取数据过程),只有当数据接收完毕之后才更新相应部分的内容。这种更新是瞬间的,用户几乎感觉不到。
  • 带来更好的用户体验。
  • 可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。
  • 可以调用外部数据。
  • 基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。
  • 进一步促进页面呈现和数据的分离。

四、谁在使用AJAX
  在应用AJAX开发上面,Google当仁不让是表率。Orkut、Gmail、Google Groups、Google Maps、Google Suggest都应用了这项技术。Amazon的A9.com搜索引擎也采用了类似的技术。

  微软也在积极开发更为完善的AJAX应用:它即将推出代号为Atlas的AJAX工具。Atlas的功能超越了AJAX本身,包括整合Visual Studio的调试功能。另外,新的ASP.NET控件将使客户端控件与服务器端代码的捆绑更为简便。Atlas客户脚本框架(Atlas Clent Script Framework)也使与网页及相关项目的交互更为便利。但Visual Studio 2005中并不包含此项功能。

  微软最近宣布Atlas客户脚本框架将包含如下内容(详细资料请访问Atlas计划网站):

  • 一个可扩展的核心框架,它添加了JavaScript功能:如生命同时期管理、继承管理、多点传送处理器和界面管理。
  • 一个常见功能的基本类库,有丰富的字符串处理、计时器和运行任务。
  • 为HTML附加动态行为的用户界面框架。
  • 一组用来简化服务器连通和网络访问的网络堆栈。
  • 一组丰富的用户界面开发控件,如:自动完成的文本框、动画和拖放。
  • 处理浏览器脚本行为差异的浏览器兼容层面。

        典型的,微软将AJAX技术应用在MSN Space上面。很多人一直都对MS Space服务感到很奇怪,当提交回复评论以后,浏览器会暂时停顿一下,然后在无刷新的情况下把我提交的评论显示出来。这个就是应用了AJAX的效果。试想,如果添加一个评论就要重新刷新整个页面,那可真费事。

  目前,AJAX应用最普遍的领域是GIS-Map方面。GIS的区域搜索强调快速响应,AJAX的特点正好符合这种需求。

五、用AJAX改进你的设计
   AJAX虽然可以实现无刷新更新页面内容,但是也不是什么地方都可以用,主要应用在交互较多、频繁读数据、数据分类良好的Web应用中。现在,让我们举两个例子,看看如何用AJAX改进你的设计。

例子1:数据校验
  在输入form表单内容的时候,我们通常需要确保数据的唯一性。因此,常常在页面上提供“唯一性校验”按钮,让用户点击,打开一个校验小窗口;或者等form提交到服务器端,由服务器判断后在返回相应的校验信息。前者,window.open操作本来就是比较耗费资源的,通常由window. showModalDialog代替,即使这样也要弹出一个对话框;后者,需要把整个页面提交到服务器并由服务器判断校验,这个过程不仅时间长而且加重了服务器负担。而使用AJAX,这个校验请求可以由XMLHttpRequest对象发出,整个过程不需要弹出新窗口,也不需要将整个页面提交到服务器,快速又不加重服务器负担。例子2:按需取数据—级联菜单
  以前,为了避免每次对菜单的操作引起的重载页面,不采用每次调用后台的方式,而是一次性将级联菜单的所有数据全部读取出来并写入数组,然后根据用户的操作用JavaScript来控制它的子集项目的呈现,这样虽然解决了操作响应速度、不重载页面以及避免向服务器频繁发送请求的问题,但是如果用户不对菜单进行操作或只对菜单中的一部分进行操作的话,那读取的数据中的一部分就会成为冗余数据而浪费用户的资源,特别是在菜单结构复杂、数据量大的情况下(比如菜单有很多级、每一级菜又有上百个项目),这种弊端就更为突出。

  现在应用AJAX,在初始化页面时我们只读出它的第一级的所有数据并显示,在用户操作一级菜单其中一项时,会通过Ajax向后台请求当前一级项目所属的二级子菜单的所有数据,如果再继续请求已经呈现的二级菜单中的一项时,再向后面请求所操作二级菜单项对应的所有三级菜单的所有数据,以此类推……这样,用什么就取什么、用多少就取多少,就不会有数据的冗余和浪费,减少了数据下载总量,而且更新页面时不用重载全部内容,只更新需要更新的那部分即可,相对于后台处理并重载的方式缩短了用户等待时间,也把对资源的浪费降到最低。

例子3:读取外部数据
  AJAX可以调用外部数据,因此,可以对一些开发的数据比如XML文档、RSS文档进行二次加工,实现数据整合或者开发应用程序。

六、AJAX的缺陷

AJAX不是完美的技术。使用AJAX,它的一些缺陷不得不权衡一下:

  • AJAX大量使用了Javascript和AJAX引擎,而这个取决于浏览器的支持。IE5.0及以上、Mozilla1.0、NetScape7及以上版本才支持,Mozilla虽然也支持AJAX,但是提供XMLHttpRequest的方式不一样。所以,使用AJAX的程序必须测试针对各个浏览器的兼容性。
  • AJAX更新页面内容的时候并没有刷新整个页面,因此,网页的后退功能是失效的;有的用户还经常搞不清楚现在的数据是旧的还是已经更新过的。这个就需要在明显位置提醒用户“数据已更新”。
  • 对流媒体的支持没有FLASH、Java Applet好。
  • 一些手持设备(如手机、PDA等)现在还不能很好的支持Ajax。

 

posted @ 2009-03-29 16:27 独孤行 阅读(213) | 评论 (0)编辑 收藏
Struts中有四种不同Action,分别如下:
1.Action
2.DispatchAction
3.LookupDispatchAction
4.MappingDispatchAction
关于Action在Struts中的工作流程,这里我就不多说了,只针对各种不同的Action详解
    第一种Action:是最普通、也是我们最先接触的一种,但它仅支持一种业务方法,Action中只能允许有一个execute(),所有比较单一,有局限性,平时的项目中也用的少,或者说,它针对的是一个表单,一个Submit
关于用法:Action中就一个execute(),而strut-config.xml也只需配置一具最普通的<action/>节点,就够了
<!-- Action -->
    
<action
      attribute
="loginForm"
      name
="loginForm"
      path
="/login"
      scope
="request"
      type
="org.svse.struts.action.LoginAction">
      
<forward name="ok" path="/ok.jsp"></forward>
      
<forward name="error" path="/error.jsp"></forward>      
      
</action>
    第二种DispatchAction:这是我们在平时的学习和项目中用的最多的一种,因为它支持多个业务方法的扩展,使用起来也方便,或者说,它针对的是一个表单,多个Button
关于用法:Action中需要几个业务方法,就复制几个execute(),然后改名即可,比如我们做加、减、乘、除,有四个方法,即:add(),sub(),mul(),div();而struts-config.xml中也只需配一个<action/>节点;当然,在涉及到有的业务是否需要表单验证时,可以单独再添加节点嘛
<!-- DispatchAction -->
    
<action
      attribute
="calForm"
      name
="calForm"
      parameter
="method"
      path
="/cal"
      scope
="request"
      type
="org.svse.struts.action.CalAction">
      
<forward name="result" path="/cal_result.jsp"></forward>
      
</action>
parameter参数对应的就是我们的业务方法了,在三种DispatchAction中都要用到它,因为有了它,就可实现多业务的调用;
哪我们在视图层,是如何调用的呢?很简单:/cal.do?method=方法名(add、sub)
<script type="text/javascript">
        function dosubmit(url)
{
            var myform 
= document.myform;
            myform.action 
= url;
            myform.submit();
        }

    
</script>
  
</head>
  
  
<body>
  
<!-- 一个表单多个按钮 -->
  
<form method="post" name="myform">
       第一个数:
<input type="text" name="num1"><br>
       第二个数:
<input type="text" name="num2"><br>
       
<input type="button" value="" onclick="dosubmit('cal.do?method=add')">
       
<input type="button" value="" onclick="dosubmit('cal.do?method=sub')">
    
<input type="button" value="" onclick="dosubmit('cal.do?method=mul')">
       
<input type="button" value="" onclick="dosubmit('cal.do?method=div')"> 
  
</form>
  
</body>
    第三种LookupDispatchAction:此种Action恐怕是我们平时用的最少的一种了,尽管它也支持多业务,或者说,它针对的是一个表单,多个Submit;
但用起来非常麻烦,需要struts标签,资源文件,Action中要Map集合;这里就大概说一下
Actoin中业务方法跟上面一样,只不过多一个包含Map的方法:
//通过资源文件的key(button.add),来找到业务方法add(),sub()
    protected Map getKeyMethodMap() {
        Map map 
= new HashMap();
        map.put(
"button.add","add");
        map.put(
"button.sub","sub");
        
return map;
    }
资源文件:
# Resources for parameter 'org.svse.struts.ApplicationResources'
# Project ch03
button.add
=add
button.sub
=sub
struts-config.xml也跟上面一样,根据method来找;
哪视图组件如何来调用呢?
<!-- 一个表单多个提交 -->
    
<form action="cal2.do" method="post">
          num1:
<input type="text" name="num1"/><br>
          num2:
<input type="text" name="num2"/><br>
          
<html:submit property="method">
              
<bean:message key="button.add"/>
          
</html:submit>
          
<html:submit property="method">
              
<bean:message key="button.sub"/>
          
</html:submit>
    
<form>
怎么样够麻烦的吧。。。
    第四种MappingDispatchAction:我自认为它比DispatchAction差不多好用,只是它够灵活(这里针对<action/>节点,想咋配咋配),或者说,它针对的是多个表单,多个Submit;
关于用法,也比较简单:
Action中的业务实现跟DispatchAction一样,strut-config.xml则要灵活些,针对每一个业务方法,配一个<action/>节点:
<!-- MappingDispatchAction -->
    
<!-- add -->
    
<action
      attribute
="calForm"
      name
="calForm"
      parameter
="add"
      path
="/add"
      scope
="request"
      type
="org.svse.struts.action.Cal3Action">
      
<forward name="result" path="/cal_result.jsp" />
    
</action>
    
<!-- sub -->
    
<action
      attribute
="calForm"
      name
="calForm"
      parameter
="sub"
      path
="/sub"
      scope
="request"
      type
="org.svse.struts.action.Cal3Action">
      
<forward name="result" path="/cal_result.jsp" />
    
</action>
视图组件的调用就很能够方便了:直接跟/path路径名.do:
<form action="add.do" method="post">
        num1:
<input type="text" name="num1"><br>
        num2:
<input type="text" name="num2"><br>
        
<input type="submit" value="">
    
</form>
Struts中四种Action用法基本完毕,此纯属本人在学习过程中自己的总结,若有不当之处,愿不令赐教!!!
posted @ 2009-03-16 10:43 独孤行 阅读(1966) | 评论 (7)编辑 收藏

常用的Struts标签库有以下五大类:

1.HTML Tag:

用来创建能够和Struts框架以及其它相应的HTML标签交互的HTML输入表单;

如:<html:form></html:form>,<html:text/>,<html:password/>,<html:radio/>,<html:checkbox/>,<htmlmultibox>

2.Bean Tag

该标签库包含的标签可以用来创建bean、访问bean和访问bean的属性。

 如:<bean:write/>:用于将bean的属性输送到jsp页面,<bean:define/>定义一个新的bean

3.Logic Tag

该标签库包含的标签可以用来进行逻辑判断、集合迭代和流程控制。

如:<logic:iterate/>:用来循环迭代,<logic:eaual/>:用来进行逻辑判断

4.Nested:增强对其他Struts标签的嵌套使用能力

该标签库建立在前三个标签库的基础上,具有前三个标签库的所有功能,只是允许标签间的嵌套。

5.Template Tag

随着Titles框架包的出现,此标记已开始减少使用

下面介绍几个最常用的标签:

<html:check box/>一般用于一个选项的复选框

<html:multibox/>一般用于多个选项的复选框

<bean:write name="user" property="username"/>等同于EL表达示:${user.username}

<bean:define id="inter" name="user" property="interest" type="java.lang.String"/>定义一个bean

<bean:message key=" " arg0=" "/> key 定义在资源文件中,args0[1,2]为参数

<logic:iterate name="list" id="user"> 等同于JSTL的:<c:foeach item=${list} var="user"/>

<logic:equal name="user" property="sex" value="0"/>等同于JSTL的:<c:when test=""/>

<logic:empty />标签是用来判断是否为空的。如果为空,该标签体中嵌入的内容就会被处理

<logic:empty name="listForm" property = "persons">
<div>集合persons为空!</div>
</logic:empty>

1.下面给一个表单的完整代码:

<body>
    
<center>
        
<html:form action="/user">
        用户名:
<html:text property="user.username"></html:text><p/>
        密码:
<html:text property="user.pwd"></html:text><p/>
        性别:
<html:radio property="user.sex" value=""></html:radio>
            
<html:radio property="user.sex" value=""></html:radio><p/>
        城市:
<html:select property="user.city">
            
<html:option value="">请选择</html:option>
            
<html:option value="武汉">武汉</html:option>
            
<html:option value="上海">上海</html:option>
            
<html:option value="北京">北京</html:option>
        
</html:select><p/>
        爱好:
<html:multibox property="interest" value="看书"/>看书
            
<html:multibox property="interest" value="游戏"/>游戏
            
<html:multibox property="interest" value="睡觉"/>睡觉<p/>
            
<html:submit/><html:cancel/>
        
</html:form>
    
</center>
    
</body>

使用html标签作为表单输入,可以方便的使用验证框架即:<html:errors property="username">

2.下面给一个显示数据的代码:

<table align="center" border="1" width="600">
        
<caption>用户注册信息</caption>
        
<tr>
            
<td>用户名</td>
            
<td>密码</td>
            
<td>性别</td>
            
<td>城市</td>
            
<td>爱好</td>
            
<td colspan="2" align="center">操作</td>
        
</tr>
        
<logic:iterate name="list" id="user">
        
<tr>
            
<td><bean:write name="user" property="username"/></td>
            
<td><bean:write name="user" property="pwd"/></td>
            
<td><bean:write name="user" property="sex"/></td>
            
<td><bean:write name="user" property="city"/></td>
            
<td>
                
<bean:define id="interest" name="user" property="interest" type="java.lang.String"></bean:define>
                
<logic:iterate id="inter" collection="<%=StringUtil.stringChange2(interest)%>">
                    $
{inter}
                
</logic:iterate>
            
</td>
            
<td><a href="del.do?userid=${user.userid}">删除</a></td>
            
<td><a href="upd.do?userid=${user.userid}">修改</a></td>
        
</tr>
        
</logic:iterate>
    
</table>

作为显示数据,Struts标签并不比Jstl与EL方便,因此,本人更习惯用后者

其实Struts标签的好处,并不是上面这些,而是它可利用ActionForm来填充数据

比如我们在做页面数据修改的时候,会让当前页面数据显示到显示修改页面,这样利于客户端修改

以前我们这样做的:根据id从数据库查出,然后使用html的value属性填充,现在有了Struts标签,就不需要那么麻烦了

直接在Action里填充ActionForm的数据就搞定了

public ActionForward upd(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response) 
{
        UserForm userForm 
= (UserForm) form;
        
int userid = Integer.parseInt(request.getParameter("userid"));
        UserInfo user 
= biz.findUser(userid);
        String[]interest 
= StringUtil.stringChange2(user.getInterest());
        
//将用户信息填充到ActionForm
        userForm.setUser(user);
        userForm.setInterest(interest);
        
return mapping.findForward("upd");
    }
然后在修改页面显示,请往下看:
<html:form action="/doupd">
        用户名:
<html:text property="user.username"></html:text><p/>
        密码:
<html:text property="user.pwd"></html:text><p/>
        性别:
<html:radio property="user.sex" value=""></html:radio>
            
<html:radio property="user.sex" value=""></html:radio><p/>
        城市:
<html:select property="user.city">
            
<html:option value="">请选择</html:option>
            
<html:option value="武汉">武汉</html:option>
            
<html:option value="上海">上海</html:option>
            
<html:option value="北京">北京</html:option>
        
</html:select><p/>
        爱好:
<html:multibox property="interest" value="看书"/>看书
            
<html:multibox property="interest" value="游戏"/>游戏
            
<html:multibox property="interest" value="睡觉"/>睡觉<p/>
            
<html:submit value="修改"/>
        
</html:form>
怎么样,简单方便吧,其实Struts标签还是有它的好处的。
posted @ 2009-03-14 23:47 独孤行 阅读(1572) | 评论 (1)编辑 收藏

Struts中最常用的七种ActionForm如下:

1.ActionForm

2.ValidatorForm

3.ValidatorActionForm

4.DynaActionForm

5.DynaValidatorForm

6.DynaValidatorActionForm

7.LazyValidatorForm

由命名来看,就总体使用规律如下:

1.带有Validator的,但都可使用验证框架;

2.以Dyna开头的,都是自动生成相应的form,只需在Struts-config.xml中配置属性即可

3.中间是否有Action的,表示validation.xml中的form的name名,是跟formbean的名称,还是/path路径

下面按规律逐个介绍:

1.ActionForm,DynaActionForm此类不支持验证框架,需手动创建form,并实现自定义的validate()方法

但DynaActionForm是特例(它自动生成form),所以没有validate()方法,所以也就不能验证
2.ValidatorForm,ValidatorActionForm,DynaValidatorForm

DynaValidatorActionForm,LazyValidatorForm 此大类都是支持验证框架的,当然也可以完成自定义的validate()方法,来覆盖验证框架的方法,其中:

ValidatorForm,DynaValidatorForm,LazyValidatorForm  没有Action,是针对form来验证的,即凡是用到该form的页面,都必须验证;

反之,ValidatorActionForm,DynaValidatorActionForm,则是针对Action的,要验证哪个Action,就跟那个/path路径,validation.xml代码如下:

<form-validation>
    
<formset>
        
<!-- 此时针对Action验证,name跟/path路径--!>
        
<!--如果是针对form验证,name则跟formbean的名称--!>
        
<form name="/login">
            
<field property="username" depends="required">
                
<msg name="required" key="username"/>
            
</field>
            
<field property="pwd" depends="required,minlength">
                
<msg name="required" key="pwd"/>
                
<msg name="minlength" key="pwd1"/>
                
<var>
                    
<var-name>minlength</var-name>
                    
<var-value>6</var-value>
                
</var>
            
</field>
        
</form>
    
</formset>
</form-validation>

针对七种ActionForm,我们要灵活运用,需要验证谁,就让它停下,不需要的,让它通过。

 另外介绍下验证框架的使用步骤

1.在validator-rules.xml中引入验证插件的代码:

<!--引入验证框架--!>
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
        
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,
                                                  /WEB-INF/validation.xml"/>
      </plug-in>
2.创建并配置validation.xml 文件,代码如下:
<!DOCTYPE form-validation PUBLIC
          
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
          
"http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">
<form-validation>
    
<formset>
        
<form name="loginForm">
            
<field property="username" depends="required">
                
<msg name="required" key="username"/>
            
</field>
            
<field property="pwd" depends="required,minlength">
                
<msg name="required" key="pwd"/>
                
<msg name="minlength" key="pwd1"/>
                
<var>
                    
<var-name>minlength</var-name>
                    
<var-value>6</var-value>
                
</var>
            
</field>
        
</form>
    
</formset>
</form-validation>
3.描述.properties资源文件,来指明验证提示,当然也可不用,直接声明变量
# Resources for parameter 'ApplicationResources'
# Project ch07
username
=username is null
pwd
=pwd is null
pwd1
=pwd is less than 6
以上来自各方面的学习,加上自己的整合,希望与各位豪杰共同探讨
posted @ 2009-03-13 17:03 独孤行 阅读(485) | 评论 (0)编辑 收藏