开发者在线 Builder.com.cn 更新时间:2008-02-28作者:Nurhachi Jang 来源:
做过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
相关资源:敏捷开发V1.0.pptx