一.
<!---->使用反射动态取出 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")); ??
- ????} ??
- ??
- }??
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>??
<%@ 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 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();??
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>??
<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?==?'程序'"> ??
- ...??
<s:if test="user.name == '程序'"> ...
?
这样就算 user.name 等于“程序”也是无法通过的,需要修改成以下代码:
- <s:if?test="user.name?==?\'程序\'">??
- ...??
<s:if test="user.name == \'程序\'"> ...
?
?
如果“程序”是你系统的一个常量,更推荐的作法是:
- <s:if?test="user.name?==?@com.leo.util.Constants@TYPE?">??
- ...??
<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>??
<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 。