在struts2的action中使用字段级参数注入

上篇我们提到了使用SetAndGet注解进行自动生成set/get方法,那么在开发模式下, 我们所使用的IDE,在进行了代码修改之后,会自动地进行重新编译代码并进行hotswap操作。这个操作会使得在启动时生成的set/get失效或者被删除。解决这个问题的一个方法,就是使用字段级参数注入,即我们在开发模式下不需要生成set/get,而是直接使用相应的字段进行操作。

在当前的struts2版本中,默认是不支持字段设置值的,但是ognl本身是支持的。在ognl中,提供了以下2个方法来完成字段的获取和设置。

OgnlRuntime.setFieldValue(ognlContext, o, name.toString(), value);//设置字段的值
OgnlRuntime.getFieldValue(ognlContext, o, name.toString());//获取字段的值

那么,我们可以通过相应的处理。让在开发模式下,在使用常规参数处理之后,再启用字段级参数处理就达到相应的目的了。在整个处理中,我们需要保证以下2点就可以达到目的了。

  1. 在action进行参数注入时,可以支持字段级的注入,涉及的访问器为CompoundRootAccessor
  2. 在相应的字段为null时,我们可以按照常规的处理自动创建相应的值,以便进行注入,涉及的处理器为InstantiatingNullHandler

继续阅读“在struts2的action中使用字段级参数注入”

使用代码生成技术避免在struts2 action中大量的set/get方法

在使用struts2进行功能开发时,我们经常碰到的问题就是如果这个类有很多个参数,这里就需要有很多个get/set方法.如果你发现你的一个action中很上百行的set/get方法,那无疑让人抓狂,因此会让真正的业务方法隐藏其中,不管是开发还是维护都难以查找.
从业务开发的角度,action中的方法只能够表现于与业务的一一对应,如果没有相应的业务,则不相关的方法都不应该出现在当前这个类中.只不过,我们使用了struts2,这就表示必须有比业务方法数大得多的set/get充斥其中.

本文即通过一种代码生成(或称之为代码改写)使得我们在开发的时候不需要编写相应的set/get,而在运行时自动产生这些方法,相应的问题就可以解决了.具体结果可参考如下:

public class UserAction {
/** 表示要操作的用户信息 */
@SetAndGet(set=true,get=true)
private String user;
@SetAndGet(get=false)
private long idx;
}

在工程进行启动时,就即会相应的处理器自动处理相应的action,然后根据这些注解信息自动生成相应的set/get,这样即可以满足struts2的规范要求,又可以避免代码海洋,同时进行维护时也可以直接查找到相应的业务,直接查看字段信息,即可以了解这些属性有什么用(如用于数据返回(只需要get,或参数传递(需要set/get)).

继续阅读“使用代码生成技术避免在struts2 action中大量的set/get方法”

struts2 Action的参数处理和应用(数据访问和处理)-技术培训

这是一次为部门作的技术培训ppt,以下将其贴出,以方便大家查看。
下载地址:http://download.csdn.net/download/fly_m/5562553

本培训从最基本的数据如何进行访问和如何调用方法开始,逐步深入,讲解在数据处理当中涉及到的数据访问,转换,封装以及数据创建等内容。然后结合struts2,讲解在struts2中是如何运用这些理论来处理这些事项,并且是如何运行的;最后讲解了一个之前提到过如何在sturts2中使用带参数进行方法调用,并且是如何作到的。
涉及到以下主题

基本的数据访问
数据链
Request请求中的数据处理
数据转换和封装
泛型映射
Struts2中的数据处理
方法参数映射
Struts2中的数据增强处理

继续阅读“struts2 Action的参数处理和应用(数据访问和处理)-技术培训”

xwork classFinder在jboss 7环境不能正确处理url resource的问题以及解决方法

在struts2中,有一个组件为classFinder,它可以在整个项目中查找任意一个指定条件的类。如查找实现了某一个接口的所有实现类,或者查找有指定注解的所有类。这个组件的好处自不用说,但是在jboss7环境下,即会出现查找不到对象的问题。

如以下的条件就不能查找任何信息:只查找以com.iflym包名开头的满足指定条件的类。那么,这个classFinder的构建方法就是:

    public ClassFinder(ClassLoaderInterface classLoader, String... dirNames) {
        this(classLoader, getURLs(classLoader, dirNames));
    }

这个方法,会按照指定的包名,组装多个url地址,那么在jboss7中,就会组装成以下的一个地址:

jboss/standalone/tmp/vfs/deplymentxxx/iflym.jar-xxx/contents/com/iflym

那么,在这个目录下,肯定没有任何东西。那么xword在实现jboss vfs的查找时,会使用以下方法进行定位:

            if (s.startsWith("class org.jboss.vfs.VirtualFile")) { // JBoss 7 and probably JBoss 6
                File physicalFile = readJBossPhysicalFile(content);
                return physicalFile.toURI().toURL();

    private static File readJBossPhysicalFile(Object content) throws Exception {
        Method method = content.getClass().getDeclaredMethod("getPhysicalFile");
        return (File) method.invoke(content);
    }

这样就会返回以上的文件目录的一个url对象,而实现上,这个url对象下面没有任何class文件,自然就不会返回任何信息。
以上的问题,只存在于我们要查找的类在一个jar中的情况,如果在classes目录下,是没有问题的。

解决这个问题,我们需要使用另一个组件:reflections。官方地下:http://code.google.com/p/reflections/

继续阅读“xwork classFinder在jboss 7环境不能正确处理url resource的问题以及解决方法”

使用struts2标签定制ajax版的分页组件

上一文中,我们介绍了如何使用page.jsp界面输出分页信息,那么针对于像动态表格,或者需要局部刷新的界面又如何处理呢。道理其实还是很简单,我们只需要按照需求让它按指定的动作进行即可以了。

具体的作法也很简单,我们只需要将所有的链接修改为一个点击函数就可以了,那么当点击链接时,具体界面怎么跳转,以及刷新哪个部分,这其实就与分页组件无关了。我们只需要将相应的链接传递给调用方,让调用方自行处理就行了,这样也可以保证分页组件的通用性。

在实现层面,原来的链接就是一个href链接,那么修改为ajax版之后,我们就将这个href链接当成一个参数传递给调用方,比如可以定义一个clickPage函数,然后把href传递给clickPage即可,当然,你也可以同时传递当前的页码,具体实现由需求决定。
简单参考代码如下所示:

<s:url id="goto"><s:param name="page.currentPage" value="1"/></s:url>
<s:a href="%{goto}" onclick="clickPage('' + this.href);return false;" title="首页"></s:a>

继续阅读“使用struts2标签定制ajax版的分页组件”

使用struts2开发通用分页组件

由于在使用struts2中经常碰到分页的场景,因此这里讲述一个如何使用通用jsp分页组件的界面,其中包括可使用代码和相应的原理。

这个组件写于5年前,不过现在还是可以使用的,简而言之,它使用了struts2中标签的url标签。简单介绍一下url标签的作用,附如下所示:

名称 必填 缺省 类型 描述
value false   Object/String value如果不提供就用当前action
action false   Object/String 用来生成url的action,如果没有则使用value
namespace false   Object/String 命名空间
id false   Object/String 该元素标识

仔细看url的介绍,其中有几个值值得注意,一是action及namespace和value值,如果不传就使用当前界面的请求值;另一个则是param属性,如果不写就使用当前界面的所有参数值,如果写了,就将设置了的进行覆盖。这里我们将这两个特性应用到我们的分页当中,就会发现这实际上就是专门为分页准备的,分页中,只需要变化分页参数,其它一切不变。

通过上面我们可以看出其中一个关键的参数,id值,文档上为如果id值不为null,而将相应的路径信息传递给id值,并将id值保存在上下文中。那么,我们在分页组件中就可以先定义这个id值,即某一页的链接,然后再将这个链接值传递到某一个a链接即可。

具体在实现上,我们肯定需要一个page对象,里面的属性大家都懂的,第几页,一页多少条,总记录数,然后就是根据这些参数处理是否有上一页,是否有下一页等。

那么,正式的代码即可如下所示,即如何输出首页:

<s:url id="goto"><s:param name="page.currentPage" value="1"/></s:url>
<s:a href="%{goto}" title="首页"></s:a>

继续阅读“使用struts2开发通用分页组件”