去除前后I格看似非常单的事,但是有许多h可能是因ؓq一个小问题Q折自己半天,客户端提交到所有的东西Q都是以字符串Ş式提交的Q我们不知道客户是怎么操作的,他可能把一个age属性对应的|在输入时多加了一个空|而服务器age对应的却是IntegercdQ如果你使用servletq事也好解决Q但是如果你使用的是MVC框架Q自动封装时׃得到一个类型{换异常,然而这个时候你是否有好的解军_法呢Q?br />
q里我用Filter来解册一问题Q这是最单方便有效的解决方式Q因Z不需要对每一个属性在装前都去trim()Q因是一仉怹味的事情。大安知道filter可以qo我们惌它过滤的每一个请求,在这h中有HttpServletRequest、HttpServletResponse。我们知道服务器取得客户端发送的参数都是通过HttpServletRequest来获取的Q那我们可不可以在用HttpServletRequest取值的时候就为每一个客L(fng)提交的属性去除前后空|或者其它的一些过滤操作。这肯定是可以的Q那我们先来了解一下服务器是怎么取得客户端的值的?br />
1.getParameter(name)Q返回单个倹{?br />
2.getParameterValues(name)Q返回一个数l?br />
3.getParameterMap()Q把客户端提交参数封装ؓ一个Mapq回。KQnameQVQvalue?br />
当我们用servlet的时候一般都是用前两种Qstruts1使用的第2U,struts2(xwork)则用的W?U,那么我们只要在这三个Ҏ(gu)调用的时候处理前后空|那么q回到服务器的参数就又减了一分出bug的机会,看下面的实现?br />
public class RequestParameterFilter implements Filter {
private static Log log = LogFactory.getLog(RequestParameterFilter.class);
private List<String> excludeNames;
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//
request = new HttpServletRequestWrapper2((HttpServletRequest) request);
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
String exclude = config.getInitParameter("exclude");
// not is null.
if (exclude != null && exclude.length() > 0) {
excludeNames = Arrays.asList(exclude.split(","));
if (log.isDebugEnabled()) {
log.debug("initialize arguments.");
}
}
}
/**
* 该类l承之HttpServletRequestWrapperQƈ重写了对应取得客L(fng)相当参数值的所有的Ҏ(gu)?br />
* <ul>
* <li>getParameter</li>
* <li>getParameterValues</li>
* <li>getParameterMap</li>
* </ul>
*
* @version 1.0/2010-6-10 上午11:25:47
* @author Aidan
* @see HttpServletRequestWrapper
*/
private class HttpServletRequestWrapper2 extends HttpServletRequestWrapper {
private ParameterMap2 pm2;
public HttpServletRequestWrapper2(HttpServletRequest request) {
super(request);
}
public String getParameter(String name) {
if (excludeNames != null && excludeNames.contains(name)) {
return super.getParameter(name);
}
return trim(super.getParameter(name));
}
@SuppressWarnings("unchecked")
public Map getParameterMap() {
// xwork便用此Ҏ(gu)取?br />
// 该方法返回一个MapQMap映射了客L(fng)h对应的键?K,V)?/span>
if (pm2 == null) {
pm2 = new ParameterMap2(super.getParameterMap());
}
return pm2;
}
public String[] getParameterValues(String name) {
// Struts1使用此方法取得所有的参数?/span>
if (excludeNames != null && excludeNames.contains(name)) {
return super.getParameterValues(name);
}
return (String[]) trim(super.getParameterValues(name));
}
}
/**
* 该此l承自HashMap?br />
*
* @version 1.0/2010-6-10 上午11:30:13
* @author Aidan
* @see HashMap
*/
@SuppressWarnings( { "unchecked", "serial" })
private class ParameterMap2 extends HashMap {
private Set entrySet;
/**
* 若要构造此cd象,则需要传入一个map参数Q该map对应的客L(fng)h的参?K,V)?br />
*
* @param map
* 映射客户端参数?br />
*/
public ParameterMap2(Map map) {
super(map);
}
public Set entrySet() {
// xwork使用了此Ҏ(gu)取?/span>
if (entrySet == null) {
entrySet = new HashSet();
Set temSet = super.entrySet();
for (Iterator iterator = temSet.iterator(); iterator.hasNext();) {
Map.Entry me = (Map.Entry) iterator.next();
Entry2 entry = new Entry2(me);
entrySet.add(entry);
}
}
return entrySet;
}
// 若直接从map使用key取得
public Object get(Object key) {
Object value = super.get(key);
// 不过滤此对象
if (excludeNames != null && excludeNames.contains(key)) {
return value;
}
if (value != null) {
return trim(value);
}
return null;
}
}
@SuppressWarnings("unchecked")
private class Entry2<K, V> implements Map.Entry<K, V> {
private Map.Entry me;
private boolean isTrim = true;
public Entry2(Map.Entry me) {
if (me == null) {
throw new IllegalArgumentException(
"Map.Entiry argument not null.");
}
this.me = me;
// 不过滤此对象
if (excludeNames != null && excludeNames.contains(me.getKey())) {
isTrim = false;
}
}
public K getKey() {
return (K) me.getKey();
}
public V getValue() {
if (isTrim) {
return (V) trim(me.getValue());
}
return (V) me.getValue();
}
public V setValue(V value) {
return (V) me.setValue(value);
}
}
/**
* 去除一个Objectcd对应的前后空|因ؓ客户端提交参数有两种Q一U:StringQ另一U:String[]Q此Ҏ(gu)会自动判断调用哪个方法?br />
*
* @param value
* 需要处理的参数?br />
* @return 处理后的倹{?br />
*/
protected Object trim(Object value) {
if (value instanceof String[]) {
return trim((String[]) value);
}
return trim(value.toString());
}
/**
* 去除某个字符串的前后I格?br />
*
* @param value
* 需要处理的参数?br />
* @return 处理后的倹{?br />
*/
protected String trim(String value) {
if (value != null && value.length() > 0) {
return value.trim();
}
return value;
}
/**
* 去除某个数组中所有的值的前后I格?br />
*
* @param values
* 需要处理的数组?br />
* @return 处理后的|当数l的length?Ӟ则返回一个StringQ反之返回一个数l?br />
*/
protected Object trim(String[] values) {
if (values != null && values.length > 0) {
int len = values.length;
for (int i = 0; i < len; i++) {
values[i] = trim(values[i]);
}
}
if (values.length == 1) {
return values[0];
}
return values;
}
/**
*
* @return 不处理的对象?br />
*/
public List<String> getExcludeNames() {
return excludeNames;
}
}
q个Filter实现原理非常单,我会qo所有的hQHttpServletRequestWrapper2l承自HttpServletRequestWrapperQ在构造函C需要一个HttpServletRequest对象(q个request是webH口创徏?Q然后我重蝲了上面所说的3个方法,在方法内部每ơ会去过滤当前|q是利用了Java多态特性。在使用getParameterMap时较为麻烦,原理一栗?br />
当然我们有时候可能有些特D情况不需要过滤前后空格或者其它一些规则,q里我们可以使用exclude属性来判断是否qo此属性?br />
DEMOQ?br />
<form action="test!create.action" method="post">
name:
<input name="name" value=" My name is haha.. " />
<br />
<!-- This is a String,isn't number. -->
age:
<input name="age" value=" 15 " />
<br />
email:
<input name="email" value=" grasszring@gmail.com " />
<br />
email2:
<input name="email" value=" grasszring@foxmail.com " />
<br />
<input type="submit" value=" submit " />
</form>
web.xml
<filter>
<filter-name>requestParameter</filter-name>
<filter-class>com.onlyeffort.commons.web.filter.RequestParameterFilter</filter-class>
<init-param>
<!-- 不需要过滤此参数 -->
<param-name>exclude</param-name>
<param-value>email</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>requestParameter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
action
@Action(params = { "actionName", "test" })
@Result(location = "http://www.google.com", type = "redirect")
@SuppressWarnings("serial")
public class TestController extends ActionSupport {
private String name;
private Integer age;
private String[] email;
//.. get set method.
@Override
public String create() throws CreateFailureException {
System.out.println(name);
System.out.println(age);
for (String mail : email) {
System.out.println(mail);
}
return SUCCESS;
}
}
OK,如果大家有什么问题或有什么意见都管留言Q感Ȁ不尽?br />

]]>