王朝网络
分享
 
 
 

运用Filter,ThreadLocal和Reflection,实现form到bean的填充

王朝other·作者佚名  2007-08-08
宽屏版  字体: |||超大  

© 2006 版权声明

1. 本文作者为 javafuns

2. 本文可经/不经作者许可,任意转载

3. 转载时请表明原作者及修改者,并附带本版权声明

4. 本文未经实践检验,故对由采用本文所述操作而引起的任何后果,本文作者均不作任何担保,亦不承担任何责任

做过web开发的人可能都有这种感觉,不时的需要从request中提取参数及数据,如果有一种方式可以省却这一步骤,是否会令你的开发工作更愉悦呢?本文在此做了如下的探讨。

很显然,从request中提取参数需要一个尽职尽责的,但是又很优雅的让我们感觉不到它的辛苦工作的模块来实现,它的任务就是,1)截取所有的request,2)从request取出数据并填充到bean留给其他人使用。大概你也会想到Filter,它的特性符合要求。

Filter截取了请求如何处理呢? 我想到了2种方式(当然,还有其它的),

1)request参数需要指明本次提交的数据要填充至哪个bean,且参数与bean的field严格匹配,这样利用 Reflection ,取出bean的field,然后从request.getParameter(field)取得数据进行填充。

2)采取配置文件进行request 的form数据到bean的映射,方式也是采用Reflection来完成填充工作。

2种方式各有优缺点,方式1不够灵活,方式2则对于某些人看来则是烦琐,毕竟还需要配置,也失去了本文简化request form处理的目的。因此本人推荐第一种方式,即使存在某些情况,也可以在bean中增加新方法来处理。

数据的有效性检查也放在bean里做,将数据无效的信息放在bean的error hashmap里,在filter填充完bean后,检查bean是否有效,有无效的数据,则直接返回客户端;否则,调用chain.doFilter(request, response)继续处理,并将这个bean放入ThreadLocal中,留待后续class访问,当这个线程结束后,bean会被垃圾收集器清除。

Filter样例:

/*

* SimpleFilter.java

*

* Created on 2006年9月20日, 下午2:54

*/

package org.openthoughts.testings;

import Java.io.*;

import Java.lang.reflect.Field;

import Java.lang.reflect.InvocationTargetException;

import Java.lang.reflect.Method;

import Java.util.HashMap;

import javax.servlet.*;

import javax.servlet.http.*;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import org.openthoughts.util.Form2BeanUtil;

/**

* Stuff a bean specified by request with form data.

*

* @author <a href="guangquanzhang@gmail.com">javafuns</a>

* @version

*/

public class SimpleFilter implements Filter {

// The filter configuration object we are associated with. If

// this value is null, this filter instance is not currently

// configured.

private FilterConfig filterConfig = null;

public SimpleFilter() {

}

/**

* Init method for this filter

*

*/

public void init(FilterConfig filterConfig) {

this.filterConfig = filterConfig;

}

/**

* Do actual work for filling.

*

* @param request The servlet request we are processing

* @param result The servlet response we are creating

* @param chain The filter chain we are processing

*

* @exception IOException if an input/output error occurs

* @exception ServletException if a servlet error occurs

*/

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain)

throws IOException, ServletException {

String beanName = ((HttpServletRequest)request).getParameter("formbean");

System.err.println(" form bean is " + beanName);

Class beanClazz = null;

Object beanObject = null;

boolean isValid = false;

if(beanName != null) {

try {

beanClazz = Class.forName(beanName);

if(beanClazz != null) {

beanObject = beanClazz.newInstance();

}

} catch (ClassNotFoundException ex) {

request.setAttribute("MainErrMsg", beanName + " not found");

this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);

return;

} catch (InstantiationException ex) {

request.setAttribute("MainErrMsg", beanName + " can not be instantiated");

this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);

return;

} catch (IllegalAccessException ex) {

request.setAttribute("MainErrMsg", beanName + " not access");

this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);

return;

}

}

if(beanObject != null) {

Field[] fields = beanClazz.getDeclaredFields();

for(Field field : fields) {

Method beanMethod = null;

String fieldName = field.getName();

String fieldValue = ((HttpServletRequest)request).getParameter(fieldName);

StringBuilder sb = new StringBuilder();

sb.append("set");

sb.append(fieldName.substring(0, 1).toUpperCase());

sb.append(fieldName.substring(1));

try {

beanMethod = beanClazz.getDeclaredMethod(sb.toString(), String.class);

} catch (SecurityException ex) {

request.setAttribute("MainErrMsg", " Security reason ");

this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);

return;

} catch (NoSuchMethodException ex) {

request.setAttribute("MainErrMsg", beanName + " does not have method named " + sb.toString());

this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);

return;

}

if(beanMethod != null) {

try {

beanMethod.invoke(beanObject, fieldValue);

} catch (IllegalArgumentException ex) {

request.setAttribute("MainErrMsg", "illegal argument for the method " + sb.toString() + " of " + beanName);

this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);

return;

} catch (InvocationTargetException ex) {

request.setAttribute("MainErrMsg", beanName + " invoke target exception ");

this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);

return;

} catch (IllegalAccessException ex) {

request.setAttribute("MainErrMsg", beanName + " illegal access to " + sb.toString());

this.filterConfig.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);

return;

}

}

}

Form2BeanUtil.put(beanObject);

Method getAllErrors = null;

try {

getAllErrors = beanClazz.getDeclaredMethod("getAllErrors");

} catch (SecurityException ex) {

System.err.println("Security exception when call getAllErrors()");

} catch (NoSuchMethodException ex) {

System.err.println("No such method named getAllErrors()");

}

if(getAllErrors != null) {

try {

isValid = ((HashMap)getAllErrors.invoke(beanObject)).isEmpty();

} catch (IllegalArgumentException ex) {

System.err.println("Illegal argument for getAllErrors()");

} catch (IllegalAccessException ex) {

System.err.println("Illegal Access to getAllErrors()");

} catch (InvocationTargetException ex) {

System.err.println("Invocation target exception");

}

}

}

if(beanName == null || isValid) {

chain.doFilter(request, response);

} else {

if(beanObject != null) {

request.setAttribute("formbean", beanObject);

}

this.filterConfig.getServletContext().getRequestDispatcher(getRequestURI(request)).forward(request, response);

}

}

/**

* Destroy method for this filter

*

*/

public void destroy() {

}

public String getRequestURI(ServletRequest request) {

String requestURI = ((HttpServletRequest)request).getRequestURI();

String queryString = ((HttpServletRequest)request).getQueryString();

return requestURI + queryString;

}

/**

* Return a String representation of this object.

*/

public String toString() {

if (filterConfig == null) return ("SimpleFilter()");

StringBuffer sb = new StringBuffer("SimpleFilter(");

sb.append(filterConfig);

sb.append(")");

return (sb.toString());

}

}

Bean样例:

/*

* SimpleBean.java

*

* Created on 2006年9月20日, 下午5:51

*/

package org.openthoughts.beans;

import Java.io.Serializable;

import Java.util.HashMap;

/**

* @author Administrator

*/

public class SimpleBean implements Serializable {

private String userName;

private String password;

public SimpleBean() {

}

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

//错误信息

public HashMap getAllErrors() {

return new HashMap();

}

}

ThreadLocal实现:

/*

* Form2BeanUtil.java

*

* Created on 2006年9月20日, 下午4:51

*

* To change this template, choose Tools | Template Manager

* and open the template in the editor.

*/

package org.openthoughts.util;

/**

* Hold formbean for appropriate thread via ThreadLocal.

*

* @author <a href="guangquanzhang@gmail.com">javafuns</a>

*/

public class Form2BeanUtil {

private static final ThreadLocal container = new ThreadLocal();

/**

* Put the form bean to ThreadLocal.

*/

public static void put(Object object) {

container.set(object);

}

/**

* Get the current thread's form bean.

*/

public static Object get() {

return container.get();

}

}

PS: 类似的方式在很多框架都有实现,比如struts的formbean

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有