当前位置: 代码迷 >> Web前端 >> Struts2(Webwork2)一些实战开发技艺
  详细解决方案

Struts2(Webwork2)一些实战开发技艺

热度:639   发布时间:2012-11-11 10:07:57.0
Struts2(Webwork2)一些实战开发技巧

?

<!---->一. <!---->使用反射动态取出 Pojo 的属性

这一招在一些特殊的场合下非常管用.比如说,用户在第一个页面,选择了某个实体其中要显示出来的几个属性,那个这个时候用反射是非常不错的选择,少了大量 if 语句:

?

package com.leo.util;

import java.lang.reflect.Method;

public class HelloWorldBean {

	private String word;

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getWord() {
		return word;
	}

	public void setWord(String word) {
		this.word = word;
	}

	public HelloWorldBean() {
		name = "superleo";
		word = "Hello World!!!";
	}

	public String getProperty(String name) throws Exception {
		if (name != null && !name.equals("")) {
			Character ch = name.charAt(0);
			name = Character.toUpperCase(ch) + name.substring(1, name.length());
			Class cls = Class.forName("com.leo.util.HelloWorldBean");
			Method meth = cls.getMethod("get" + name, null);
			Object retobj = meth.invoke(this, null);
			return (String) retobj;

		}
		throw new RuntimeException();
	}

	public static void main(String[] args) throws Exception {
		HelloWorldBean bean = new HelloWorldBean();
		bean.setName("superleo");
		bean.setWord("name");
		System.out.println(bean.getProperty("name"));
		System.out.println(bean.getProperty("word"));
	}

}

?

?

OK ,假设我们在 HelloAction 使用了这个 HelloWorldBean ,并且运行后,跳转到相应页面,你可以这样去取 HelloWorldBean word name 属性了:

?

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
	<body>
		<h3>
			正常方法:<s:property value="helloWorld.name" /> <br />
			<s:property value="helloWorld.word" /> <br />
			反射方法:<s:property value="helloWorld.getProperty('name')" /> <br />
			<s:property value="helloWorld.getProperty('word')" />
		</h3>
	</body>
</html>

?

?

对于公共属性,还可以将此方法移到父类。

?

?

?

<!---->二. <!----> iterator 迭代 Map 对象

?

?

这对显示 Hibernate 多表连接的查询结果非常管用。

?

以前,在使用 Hibernate 的时候,因为涉及到多个表查询是很普遍的,每个表取一些字段,想显示在页面,比较好的办法是新建一个 VO 对象,专门用来显示查询的结果.但缺点就是,如果这样的查询很多, VO 类会越来越多(如果不断的往一个 VO 增加字段的话,那么这个 VO 也越来越大,构造函数会特别夸张),咱们来看一个例子:

?

List list = session.createQuery("select new MyVO(a.name, b.name, c.id) from .....").list();

?

?

这样返回的 List 直接就可以在页面上用 iterator 标签迭代了,但假如现在要取 10 呢?不仅 HQL 语句要修改,而且 MyVO 也要修改.下面是一种更好的做法:

?

List list = session.createQuery("select new Map(a.name as fristName, b.name as secondName, c.id as id from .....").list();

?

?

这里改用 Map 了,注意每个属性都用“ as ”重新启了一个别名,这个非常重要,否则在页面显示时,很费劲.

?

现在来看页面调用代码:

?

<s:iterator value="list" id="maps">
      <tr class="row1">
      <input type="checkbox" name="ids" value="<s:property value="#maps.get('id')" />" />
      <td align="center"><s:property value="#maps.get('fristName')" /></td>
      <td align="center"><s:property value="#maps.get('secondName')" /></td>
    </tr>
    </s:iterator>
?

?

?

注意上面的页面中 Map 的取值就是当时 hql 语句中“ as ”后的别名.

虽然相对于以往的 JSTL 来说,要写的标签代码更多了,但强大的 OGNL 表达式也让你在视图层拥有更强大的灵活性与扩展性.

?

顺序无关,如果你使用了 select new List(...) 也能达到类似效果,但因为 List 是有序的,所以在页面显示非常不灵活,不推荐使用.

?

?

<!---->三. <!----> if 标签判断汉字问题

?

这个问题具体原因不明,先看下面一段代码:

<s:if test="user.name == '程序'">
...

?

这样就算 user.name 等于“程序”也是无法通过的,需要修改成以下代码:

<s:if test="user.name == \'程序\'">
...

?

?

如果“程序”是你系统的一个常量,更推荐的作法是:

<s:if test="user.name == @com.leo.util.Constants@TYPE ">
...
?

我不知道原因是不是因为版本问题?希望有知道的,回复一下.

?

?

<!---->四. <!----> iterator 双重循环

?

这个也很常用,相信很多人都轻车熟路,那我们来回顾一下。假设 lists 装的都是 Group 对象, Group 持有一个 List<User> 那个我们接下来可以:

<ww:iterator value="lists" id="top">
<ww:iterator value="users" id="sub">
组名:<s:property value="#top.name" />,成员名:<s:property value="#sub.name" />
</ww:iterator>
  应该组总数:<s:property value="users.size" />
</ww:iterator>

?

?

上面的写法有很多种,但效果都是一样的,有兴趣可以多看看 OGNL

?

?

还有一些没有及时整理好,下次统一再给大家分享一下.

1 楼 simon1118 2008-06-12  
public String getProperty(String name) throws Exception {   
        if (name != null && !name.equals("")) {   
            Character ch = name.charAt(0);   
            name = Character.toUpperCase(ch) + name.substring(1, name.length());   
            Class cls = Class.forName("com.leo.util.HelloWorldBean");   
            Method meth = cls.getMethod("get" + name, null);   
            Object retobj = meth.invoke(this, null);   
            return (String) retobj;   
  
        }   
        throw new RuntimeException();   
    }  

这一段返回类型如果不是String类型的怎么办?
2 楼 huobao89 2008-09-18  
不错不 错
3 楼 pxpaul 2008-10-30  
   如果除了String类型的变量还有其他类型的话,就要用instanceof判断是哪种类型的,还是要用if判断的,不过比直接判断是哪个变量要简单些。
      还有就是如果有Boolean类型变量就要自己写对应的get方法了,因为Eclipse、MyEclipse生成的Boolean型变量的get方法是is打头的。
  相关解决方案