本文向您展示Java反射机制的一个实例,该实例持简单EL的taglib,基本上实现了多级bean的属性的访问。
JSP的规范中,有个表达式语言(Expression Language, 简称EL),可以算是一个微型的语言,其中对request, page, session, application中预存的JavaBean对象的引用方式很是简单。最近正好需要写一个支持简单EL的taglib,所以就研究了下Java反射机制,目前基本上实现了多级bean的属性的访问,经测试,还是可以用的。如:
public static void main(String[] args){
UserBean bean = new UserBean();
bean.setName("John Abruzzi");
bean.setNick("Abruzzi");
bean.setAge(24);
AddressBean addr = new AddressBean();
addr.setZip("0086");
addr.setStreet("Bell Street #12");
bean.setAddress(addr);
System.out.println(BeanParser.doParse(bean, "bean.address.street"));
System.out.println(BeanParser.doParse(bean, "bean.address.zip"));
System.out.println(BeanParser.doParse(bean, "bean.name"));
System.out.println(BeanParser.doParse(bean, "bean.nick"));
System.out.println(BeanParser.doParse(bean, "bean.age"));
}
需要可以输出:
Bell Street #12
0086
John Abruzzi
Abruzzi
24
反射,即由一个抽象的对象(如Object),取出这个具体对象的属性或者方法(就EL中关于Bean的引用来说,这个定义已经够了)。在EL中,对一个Bean的某字段进行引用,只需 ${bean.field},当然,这个bean是已经被set到容器中的,这就是Java反射机制。
我们从容器中取出以bean为名字的Object,通过Java反射机制知道它的真实类型,然后通过field以javabean规范拼出方法名,进行调用,如果这个表达式是多级的,如${bean.field.field},其中第一个field本身就是一个bean对象,同样需要递归的进行解析。
大概原理就是这些了,看代码吧:
现有一个UserBean, 其中的一个字段Address本身又是一个AddressBean。
package elparser;
public class AddressBean {
private String street;
private String zip;
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
然后是UserBean
ackage elparser;
public class UserBean {
private String name;
private String nick;
private AddressBean address;
private int age;
public int getAge(){
return this.age;
}
public void setAge(int age){
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNick() {
return nick;
}
public void setNick(String nick) {
this.nick = nick;
}
public AddressBean getAddress() {
return address;
}
public void setAddress(AddressBean address) {
this.address = address;
}
}
Bean都是很简单的,考虑到对基本类型的支持,所以在UserBean中加入一个int型的字段age
好了,看看怎么通过一个串和一个对象来取出其中的字段来:
kage elparser;
import java.lang.reflect.Method;
public class BeanParser {
private static String getMethodName(String property, String prefix){
String prop = Character.toUpperCase(property.charAt(0))+property.substring(1);
String methodName = prefix + prop;
return methodName;
}
private static Object parse(Object bean, String expr){
Class beanClass = bean.getClass();
Method method = null;
Object result = null;
try{
//这两步是关键,get方法不需要传入参数,所以只是new出两个空数组传入
method = beanClass.getMethod(getMethodName(expr, "get"), new Class[]{});
result = method.invoke(bean, new Object[]{});
}catch(Exception e){
System.out.println(e.getMessage());
}
return result;
}
public static Object doParse(Object bean, String expr){
String keys[] = expr.split("\\.");
Object obj = null;
for(int i = 1; i < keys.length;i++){
obj = parse(bean, keys[i]);
bean = obj;
}//递归parse
return obj;
}
public static void main(String[] args){
UserBean bean = new UserBean();
bean.setName("John Abruzzi");
bean.setNick("Abruzzi");
bean.setAge(24);
AddressBean addr = new AddressBean();
addr.setZip("0086");
addr.setStreet("Bell Street #12");
bean.setAddress(addr);
System.out.println(BeanParser.doParse(bean, "bean.address.street"));
System.out.println(BeanParser.doParse(bean, "bean.address.zip"));
System.out.println(BeanParser.doParse(bean, "bean.name"));
System.out.println(BeanParser.doParse(bean, "bean.nick"));
System.out.println(BeanParser.doParse(bean, "bean.age"));
}
}
分享到:
相关推荐
NULL 博文链接:https://abruzzi.iteye.com/blog/306242
NULL 博文链接:https://abruzzi.iteye.com/blog/299305
Let's Go 服务器的基线这是一个简单的 RESTFul 服务器,用于 Let' Go 在线商店服务器,它现在是用 Ruby 编写的。 它包含一些快速开始 Web 开发的基本部分。 作为 Web 服务器作为 ORM Sqlite3 作为数据库(单文件...
Let's Go 服务器的基线这是一个简单的 RESTFul 服务器,用于 Let' Go 在线商店服务器,它现在是用 Ruby 编写的。 它包含一些快速开始 Web 开发的基本部分。 作为 Web 服务器作为 ORM Sqlite3 作为数据库(单文件...
Let's Go 服务器的基线这是一个简单的 RESTFul 服务器,用于 Let' Go 在线商店服务器,它现在是用 Ruby 编写的。 它包含一些快速开始 Web 开发的基本部分。 作为 Web 服务器作为 ORM Sqlite3 作为数据库(单文件...
NULL 博文链接:https://abruzzi.iteye.com/blog/416049
一个非常简单的 Reveal.js 模板 对于那些只想创建新幻灯片的人 git clone然后在浏览器中打开 index.html,就是这样。 其实你可以更进一步,试着生动地编辑你的幻灯片(见下面的部分)。 $ git clone git@github....
An Architecture for High Performance Network Analysis Fulvio Risso and Loris Degioanni Dipartimento di Automatica e Informatica – Politecnico di Torino Corso Duca degli Abruzzi, 24 – 10129 ...
文件中有 2 个占位符: <!-- include source files here... --> <!-- include spec files here... --> 您应该记住的一件事是, source代码应该在针对它的specification测试BEFORE放置。 玩得开心!
git clone git@github.com:abruzzi/tw-testable-javascript.git 并初始化环境: cd tw-testable-javascript bower install 安装完成后,您应确保后端服务按预期工作: curl ...