`
ye5562402
  • 浏览: 7887 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

二次绑定

阅读更多
在SpringSide 3 中,使用的MVC框架是Struts 2。Struts 2 向对于Struts 1 来说,具有相当多的优点,有很多人都说,用过Struts 2之后,再也不想看Struts 1了。然而,任何东西都有它的复杂性,Struts 2也不例外,SpringSide 3做了很多工作来简化Struts 2 的使用。

先来说说Struts 2的特点:
1、编写Action变得简单了,Action变成了简单的POJO,再也不用和ActionForm、ActionForward打交道了,返回的时候直接返回字符串即可。如果要访问Servlet API,则直接使用ServletActionContext类的静态方法。
2、Struts 2提供了插件机制,允许我们自己为它编写插件,当然,要我自己写是不现实的,但是面对别人写的琳琅满目的插件,我一样会昏头。再网上随便一搜,就可以发现40多种Struts 2插件。SpringSide 3选择的CodeBehind,就是一种Struts 2插件,它的目的是为了简化配置。
3、Struts 2提供了拦截器机制,之所以编写Action的任务那么简单,靠的都是这些拦截器,比如它们可以自动解析Web表单和URL参数,把它们注入到Action中。
4、Struts 2提供了丰富的taglib,当然,丰富也代表着我们要化更多的时间去学习。
5、Struts 2依然提供了Validator和i18n支持。
等等...

下面,我们来看看SpringSide 3是怎么使用Struts 2的吧。SpringSide 3的主要目标是降低我们使用Struts 2的复杂性,所以,它选择了这些办法:
1、没有使用Validator和i18n,对数据的验证交给了JQuery,这变成了表现层的任务,而且JQuery也可以使用AJAX从服务器端进行验证。至于i18n,江南白衣说小网站用不上。
2、没有使用Struts 2的UI标签,当然也就没有使用FreeMaker或SiteMesh了。

当然,省掉了一些东西,就省掉了我们不少的学习时间。对于Struts 2核心的一些东西,我们看看它是怎么做的:

1、使用CodeBehind插件来简化配置。使用CodeBehind后,我们就可以不用配置result了,它可以根据我们Action的返回值自动猜测返回的视图页面,它猜测的规则是这样的:返回页面的路径为struts.codebehind.pathPrefix + package namespace + action name + action returnvalue + .jsp,action returnvalue为success时,值为空,为其他时,值为"-" + return type。我们来看看SpringSide 3生成的项目中关于Struts 2的配置文件:

其中struts.codebehind.pathPrefix设置为“/WEB-INF/jsp/”,package的namespace没有设置,所以,如果我们的Action为UserAction,则返回success时,就会返回到/WEB-INF/jsp/user.jsp,如果返回input,则返回到/WEB-INF/jsp/user-input.jsp。这里江南白衣玩了一个狡猾,他把所有的jsp页面放到WEB-INF目录中,别人就没有办法直接访问了,这样就可以简化Acegi的配置工作。

2、关于拦截器栈
在上面讲Struts 2的特点时,我已经说了Struts 2中拦截器的重要作用,在上面的截图中,package的配置没有做别的什么事,主要就是配置了拦截器栈。那么拦截器栈是怎么使用的呢?它是在Action类中通过@ParentPackage指定的,如下面的代码:


下面,我来具体说一下拦截器有什么作用。
例子一、我们知道Struts 2中的Action是和Servlet API解耦的,那么如果我们要在Action中访问Servlet API怎么办呢?一种办法就是使用ServletActionContext,如下图:

另外一种办法,就是让我们的Action实现ServletRequestAware接口,如下代码:

public   class  MyAction  implements  ServletRequestAware {
    private  HttpServletRequest request;
    public   void  setServletRequest(HttpServletRequest request) {
         this .request  =  request;
   }
    public  String execute()  throws  Exception {
         //  do the work using the request 
         return  Action.SUCCESS;
   }
} 
这时候,ServletConfigInterceptor 拦截器就会把request对象注入到我们的Action中。

例子二、ParametersInterceptor 拦截器会自动解析web表单或URL参数,并把它们注入到Action中。但是很多时候,我们不愿意我们的Action具有太多的属性,因为一大堆的get、set方法看起来太乱糟糟,我们希望有一个专门的Model对象来存储这些值,而且刚好我们为Hibernate设计的Entity类用来做Model正合适。这时,我们可以让我们的Action实现ModelDriven接口,让getModel()方法返回我们的entity对象即可。这正是SpringSide 3采取的方法,如下图的代码片断:

这时候,ModelDrivenInterceptor拦截器就会帮助我们把解析的URL参数或表单数据注入到entity的属性中,而不是Action中。

例子三、Preparable 接口联合PrepareInterceptor拦截器一起工作,可以让action在执行execute() 方法前, 执行一个prepare()方法,这也正是SpringSide 3的工作方式。

3、关于Action
有了上面对CodeBehind的理解和对拦截器栈的理解后,再来理解SpringSide 3中的Action就再简单不过了,SpringSide 3中Action的继承树如下:


其中ActionSupport类是Struts 2提供的,另外两个类是白衣自己扩展的。其中SimpleActionSupport主要是提供了一些绕过jsp页面直接输出字符串的方法,不值一谈。而CRUDActionSupport就比较复杂,如下:
public abstract class CRUDActionSupport<T> extends SimpleActionSupport implements ModelDriven<T>, Preparable {
    /**
     * 进行CUD操作后,以redirect方式重新打开action默认页的result名.
     */
    public static final String RELOAD = "reload";

    /**
     * Action函数,默认action函数,默认指向list函数.
     */
    @Override
    public String execute() throws Exception {
        return list();
    }

    /**
     * Action函数,显示Entity列表.
     * return SUCCESS.
     */
    public abstract String list() throws Exception;

    /**
     * Action函数,新增或修改Entity. 
     * return RELOAD.
     */
    public abstract String save() throws Exception;

    /**
     * Action函数,删除Entity.
     * return RELOAD.
     */
    public abstract String delete() throws Exception;

    /**
     * 在save()前执行二次绑定.
     */
    public void prepareSave() throws Exception {
        prepareModel();
    }

    /**
     * 在input()前执行二次绑定.
     */
    public void prepareInput() throws Exception {
        prepareModel();
    }

    /**
     * 屏蔽公共的二次绑定.
     */
    public void prepare() throws Exception {
    }

    /**
     * 等同于prepare()的内部函数. 
     */
    protected abstract void prepareModel() throws Exception;
}
第一,它做了把CRUD操作放到了同一个Action中的操作,这样可以少写几个Action。这个工作难度不大,我觉得白衣此举,主要是为了规范CRUD函数的命名。在Struts 2中,如果我们要访问的不是默认的excute方法,可以使用如/user!save.action的格式,这样访问的就是UserAction的save方法。
第二,它实现了ModelDriven接口和Preparable接口,关于这两个接口,我在前面讲拦截器的时候已经提到过了,所以很容易理解。我们可以把我们为Hibernate设计的entity类作为Model,也可以把初始化这些entity的工作放到prepareSave()和prepareInput()方法中,这两个方法将会在save()和input()方法执行前自动执行。
第三,它定义了一个静态变量RELOAD,定义这个变量的目的是为了定义一个result的需要。CodeBehind中,大部分的result可以自己猜测,对于不能猜测的,需要使用@Results指定,如下代码:




好了,对SpringSide 3中Struts 2的分析就写到这里了。总之,使用SpringSide 3时,对于Action这一块非常简单,如果不设及到CRUD操作,就继承SimpleActionSupport,如果涉及到CRUD操作,就继承CRUDActionSupport,并在getModel()\save()\prepareSave\input()\prepareInput()等框框中填入适当的代码即可。

无论是将Action中的变量渲染页面中,或者从request中将内容回传到Action中变量的过程,统称参数绑定。  

1. 最原始的Struts2会直接赋值Action中的变量。 如hello.action?id=1,会将action中的id属性赋值。


       2. 如果参数较多,而且都属于同一个对象的,可以将所有属性都放入一个对象中,比如hello.action?user.id
          会为action中的User对象的id属性赋值。


       3. ModelDriven接口,如果不想写太多"user."前缀,如${user.id},可以实现ModelDriven接口的getModel函数,
           返回user对象。则Struts2碰到{id}时,就会尝试调用getModel() 获得user对象再获取其id属性。


       4. Prepareable接口,还有一种情况Hibernate常用的情况,一个对象可能有很多属性(比如有10个属性),
           但页面上可能只显示5个属性的输入框。如果按上面的方法,先new一个User类,然后从页面上赋值。
           保存此对象时就会将不在页面上修改的5个属性清空了。这时就需要两次的binding,一开始user变量为空,
           只绑定了action的id属性,然后在prepare()函数中查出有完整10个属性的对象,然后二次绑定时再将页面的那5个属性
           复制到user对象中。


       prepare()函数有两种作用,一种专门为了二次binding,一种是作为公共的数据准备函数。但是,
       一个action内有多个method,不是每一个method都需要执行prepare,比如list()方法,如果这种method较多,
       或者会造成冲突时,还有另外一种方式来定义二次binding函数。比如prepareSave() 函数,就会默认的在执行save()
       前执行,此时,专门实现prePareMethodName() 方法再调度一个内部的prepare函数,而将prepare()函数留空。


转载 http://www.blogjava.net/youxia/archive/2008/12/24/248051.html
分享到:
评论

相关推荐

    HyperMesh二次开发脚本绑定电脑物理地址

    为开发的的代码加一层保护-绑定电脑物理地址,识别是否为想开发权限的物理地址,如果是,执行开发程序,如果不是,报错提示。

    javascript重复绑定事件造成的后果说明.docx

    // 第二次绑定 button.addEventListener('click', function() { alert('Clicked again!'); }); ``` #### 五、解决策略 为了避免重复绑定事件造成的问题,可以采取以下几种策略: 1. **检查现有绑定**:使用原生...

    使软件绑定机器生成注册码软件俗称二次加密

    别人的软件我们二次加密,就可以实现绑定机器,再拿去。。。换MONEY哦~~~

    Python-ssrfssrf内网地址fuzzdns二次rebinding支持ipv4ipv6支持ip地址转码dns记录污染

    DNS二次绑定(DNS Rebinding)是SSRF攻击的一种高级形式,它涉及到修改DNS缓存记录,使得原本指向内网地址的域名在用户浏览器中重新解析为外网可访问的IP地址。攻击者可以利用这种方法绕过浏览器的同源策略,让内部...

    Revit二次开发之创建共享参数及绑定共享参数

    Revit二次开发,实现了创建共享参数并写入属性值。

    解决LayUI加上form.render()下拉框和单选以及复选框不出来的问题

    首先: 引入需要的css和js &lt;link rel="stylesheet" href="${ctx}/adminthemes/version3/plugins/layui/css/layui.css" rel="external nofollow" /&gt; [removed][removed] layui.use('form',function){ ...

    revit二次开发之浅见

    Revit 二次开发浅见 在本篇文章中,我们将探讨 Revit 二次开发中的一些浅见,包括结构模型中编程创建墙饰条、在工艺模型中创建管道类型、可停靠对话框的使用界面以及参数的更新等。 结构模型中编程创建墙饰条 在 ...

    codesoft二次开发API含源代码

    **codesoft二次开发API含源代码** 在IT行业中,二次开发是指基于现有的软件或平台进行功能扩展、定制或优化的过程。codesoft是一款专业的条码标签设计软件,它提供了丰富的功能来满足不同用户对标签设计的需求。...

    PHP二级域名绑定管理平台

    【3.0主要更新】增加了对iis 7 的支持,增加配置文件安全机制,系统始终会备份最新的配置文件,当由于高级配置不当导致站点无法打开时,可以直接恢复到上一次正确配置【V2.5新功能】新增301模式,一键设置301跳转,...

    U9二次开发技术资料文档说明

    《U9二次开发技术资料文档说明》是一份全面介绍U9系统二次开发的教程资源,旨在帮助学习者掌握U9C二次开发的核心技能。这份资料涵盖了档案开发、单据开发、BE插件开发、UI插件开发、接口调用、报表及打印开发等多个...

    二次封装WebUpLoader兼容一切浏览器

    本教程将详细介绍如何进行WebUploader的二次封装,以实现全面的浏览器兼容性,以及如何利用其特性进行多选、异步文件上传。 一、WebUploader简介 WebUploader是基于Flash和HTML5技术开发的文件上传组件,能够自动...

    联通手机开通黄钻二次确认(绑定)QQ号码方式.docx

    联通手机开通黄钻二次确认(绑定)QQ号码方式.docx

    一元二次方程求解MFC实现

    一元二次方程是数学中的基础概念,它通常表示为形式为 ax² + bx + c = 0 的方程,其中 a、b 和 c 是常数,a 不等于 0。MFC(Microsoft Foundation Classes)是微软提供的一个C++类库,用于构建Windows应用程序。在...

    WPF技术框架进行VisionMaster二次开发控件应用实例

    在VisionMaster的二次开发中,ViewModel可以封装VisionMaster的API调用,将图像处理的结果暴露为属性,然后在View中通过数据绑定显示这些结果。这样,UI的更新和逻辑处理被有效地解耦,使得代码更加易于理解和管理。...

    Bentley ORD(openroads designer) 二次开发(BIM)第三节 创建一个简单的项目

    在本节中,我们将深入探讨Bentley的OpenRoads Designer(ORD)的二次开发,这是一个强大的BIM(建筑信息模型)解决方案,专为公路、铁路、城市基础设施和其他土木工程项目的规划、设计和施工阶段而设计。我们将通过...

    struts2的新特性

    - **Prepareable接口**:适用于部分属性更新场景,先初始化对象,再通过二次绑定完成剩余属性的更新。 通过以上改进,Struts2不仅提升了开发效率,还提高了代码的可读性和可维护性。开发者可以更加专注于业务逻辑的...

    泛微ecology二次开发文件及资料_E8

    泛微ecology是一款知名的协同办公系统,其二次开发能力为用户提供了高度自定义和扩展的可能性。E8版本是泛微ecology的一个重要迭代,它在功能、性能和用户体验上都有所提升,尤其对于企业级应用来说,二次开发是实现...

    二次缓冲技术

    二次缓冲技术是计算机图形学和GUI编程中的一种优化策略,主要应用于动态图像的绘制和更新,以避免屏幕闪烁和不连续的视觉效果。在描述中提到的“老外编写的”可能是指某个开源库或者代码示例,它提供了一个方便的类...

    revit二次开发心得

    在Revit二次开发中,开发者通常需要深入理解Revit API并掌握特定的编程技巧来实现高效的功能扩展。以下是对标题和描述中所述四个要点的详细解释: 1. **编程创建墙饰条** 创建墙饰条是Revit二次开发中的常见任务,...

Global site tag (gtag.js) - Google Analytics