反射——reflect,也称为类的解剖机制。在学习完servlet、jsp后,一般,请求信息的传递都是通过四大作用域来实现再结合EL表达式去实现bean的field字段值的解析。本文使用反射来实现EL表达式的解析过程。
说到反射去模拟EL表达式的解析过程,也就是通过请求参数的内容去提取信息,然后对有效信息部分进行分析,最终得到我们想要的属性字段field以及拼接出po类的相关字段的set或get方法,再通过反射机制去解析bean的setXxx和getXxx成员方法的过程。
下面就通过简单的实例来模拟一下:
首先,构建Po类User[User.java]
package com.jjyy.beanparse.po;
public class User {
private String name;
private String phone;
private Integer age;
private Department department;
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
}
然后,就是实现对Bean的解析操作的方法,写一个ParseBean的类,专门处理解析操作——ParserBean.java
package com.jjyy.beanparse.util;
import java.lang.reflect.Method;
/**
* //利用反射机制实现bean的解析
* @author Administrator--jiangyu 2014-8-15
* 下午09:43:50
*/
public class ParseBean {
/**
* 拼接出方法名
* @param pre 方法的前缀 一般取属性的值为“get”
* @param field bean中的属性字段名
* @return
*/
public static String generateMethodName(String pre,String field){
//获得属性字段名 xxx 转为Xxx
String prop = Character.toUpperCase(field.charAt(0))+field.substring(1);
//拼接出方法名
String methodName = pre+prop;
return methodName;
}
/**
* 解析请求信息 获取属性字段的值
* @param bean 传入的要解析的bean对象
* @param expr 要解析的请求信息
* @return 返回取到对应字段的值
*/
public static Object parse(Object bean,String expr){
//获得bean的一个
Class beanClass = bean.getClass();
Method method = null;
Object value = null;
try {
//通过放射机制 获得方法 并执行[由于get访问器没有参数,所以直接传入null]
method = beanClass.getMethod(generateMethodName("get",expr),null);
//调用get方法 获得值
value = method.invoke(bean, null);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
/**
* @param bean 传入的要解析的bean对象
* @param expr 要解析的请求信息
* @return 属性字段的名称
*/
public static Object parseRequestString(Object bean,String expr){
//一般属性都是以xxx.xxx的方式来获取的,所以对其进行切割
String keys[] = expr.split("\\.");
Object value = null;
value = parse(bean, keys[1]);
return value;
}
最后,通过简单的测试,运用一下上面的方法:
TestParse.java
import com.jjyy.beanparse.po.User;
import com.jjyy.beanparse.util.ParseBean;
public class TestParse {
public static void main(String[] args) {
User user = new User();
user.setName("jjyy");
user.setPhone("1552304");
user.setAge(22);
System.out.println(ParseBean.parseRequestString(user,"user.name"));
System.out.println(ParseBean.parseRequestString(user,"user.phone"));
System.out.println(ParseBean.parseRequestString(user,"user.age"));
}
结果为:
jjyy
1552304
22
通过以上的测试,基本上是实现了解析的过程。但是,有时候我们的请求信息中不是xxx.xxx形式,而是xxx.xxx.xxx形式,也就是说,我们涉及到的是多表之间的映射,有关联,上面的解析过程就有问题了。所以为了解决多层次的引用,我们可以对上面的parseRequestString方法做一点改进:
首先,为了引出xxx.xxx.xxx的引用形式,需要在建一个Po类,例如:Department
Department.java
package com.jjyy.beanparse.po;
public class Department {
private String name;
private String add;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAdd() {
return add;
}
public void setAdd(String add) {
this.add = add;
}
}
同理,User.java中也要将Department作为一个属性字段,其实前面已经加入了。下面是改进后的解析方法:
/**
* @param bean 传入的要解析的bean对象
* @param expr 要解析的请求信息
* @return 属性字段的名称
*/
public static Object parseRequestString2(Object bean,String expr){
//一般属性都是以xxx.xxx的方式来获取的,所以对其进行切割
String keys[] = expr.split("\\.");
Object value = null;
//递归parse
for (int i = 1; i < keys.length; i++) {
value = parse(bean, keys[i]);
bean = value;//处理xxx.xxx.xxx的形式的请求,比如"user.department.name"
}
return value;
}
然后,我们再测试一下,该方法是不是可行。
package com.jjyy.beanparse.test;
import com.jjyy.beanparse.po.Department;
import com.jjyy.beanparse.po.User;
import com.jjyy.beanparse.util.ParseBean;
public class TestParse {
public static void main(String[] args) {
User user = new User();
user.setName("jjyy");
user.setPhone("1552304");
user.setAge(22);
System.out.println(ParseBean.parseRequestString(user,"user.name"));
System.out.println(ParseBean.parseRequestString(user,"user.phone"));
System.out.println(ParseBean.parseRequestString(user,"user.age"));
Department department = new Department();
department.setName("科技部");
department.setAdd("北京");
user.setDepartment(department);
System.out.println(ParseBean.parseRequestString2(user, "user.department.name"));
System.out.println(ParseBean.parseRequestString2(user, "user.department.add"));
}
}
执行之后的结果为:
jjyy
1552304
22
科技部
北京
通过以上模拟EL表达式的过程,我们可以知道一种表达是内部的实现机制基本上是通过反射来实现的。所谓的站在反射的高度去看待java中的一切,或许会有一样的发现。
本人由于在开发实战经验等方面不足,如果有什么不到位的地方,恳请各位前辈出来指点指点。
如果读者对反射机制感兴趣或者不是很清楚,可以看一下本人转载的一篇关于反射的讲解博文。
分享到:
相关推荐
el 表达式el 表达式el 表达式el 表达式el 表达式
关于学习el表达式的使用问题,详细简单,易于学习和理解。
EL表达式详细解析,EL表达式详细解析!
EL表达式详解,包含EL表达式简介,EL语法,EL隐含对象,EL运算符,Functions
el表达式介绍 el表达式使用帮助文档 el表达式介绍 el表达式使用帮助文档
这是一个El表达式;一些常用的写法实例代码;
el表达式,EL表达式言语和JSTL 很不错的资料啊
El表达式的用法机器语法的介绍!EL表达式被解析成数值表达式和方法表达式。其中,取值表达式去引用一个值,而方法表达式则是关联一个方法。一旦被解析之后,表达式能够被优化地计算一次或多次。
jspEL表达式 jspEL表达式 jspEL表达式 jspEL表达式
EL表达式的简单介绍 一、JSP EL语言定义 E L(Expression Language) 目的:为了使JSP写起来更加简单。 表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP 中简化表达式的方法。它是一种...
EL表达式使用文档,方便快速使用EL表达式
EL表达式总是用大括号括起,而且前面有一个美元符($)前缀:${expression}。 表示式中第一个命名变量要么式一个隐式对象,要么是某个作用域(页面作用域、请求作用域、会话作用域或应用作用域)中的一个属性.........
EL表达式的说明以及它在页面上的应用练习
关于EL表达式语言的简单总结,里面结合有EL表达式的各种使用方法,以及EL表达式配合JSTL的使用
EL表达式的一些操作。包括字符串处理,时间日期的格式化,数字处理
el表达式的相关介绍el表达式的相关介绍el表达式的相关介绍el表达式的相关介绍el表达式的相关介绍el表达式的相关介绍el表达式的相关介绍el表达式的相关介绍el表达式的相关介绍el表达式的相关介绍
让你掌握el表达式的所有语法,你可能用到的,或者不常见的应有尽有,可以说是对El表达式的诠释,让你摆脱EL表达式的困扰
EL表达式PPT,详细讲解了EL表达式用法
JSTL EL表达式语言,大致的介绍了表达式语言的使用,可作为日常参考用书,需要非常详细的了解每个标签的含义出处的,请勿下载本书,以免浪费自己的资源分!
关于jsp中EL(Expression Language)表达式的相关简介