首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

批改HttpServletRequest的参数【转】

2012-12-18 
修改HttpServletRequest的参数【转】? 当我们在做web应用的时候都会处理客户端提交到服务器的数据,如去除前

修改HttpServletRequest的参数【转】

? 当我们在做web应用的时候都会处理客户端提交到服务器的数据,如去除前后空格,一些非常字符,SQL注入类似的东西,在这里我主要说前后空格我是怎么来解决的,其它也都可以照此方法快速、方便、有效的解决,但是我一般对于非法字符,都是采用了标签来解决它的,并没有使用Filter转义掉(纯属个人解决办法)。
????? 去除前后空格看似非常简单的事,但是有许多人可能就是因为这一个小问题,折磨自己半天,客户端提交到所有的东西,都是以字符串形式提交的,我们不知道客户是怎么操作的,他可能把一个age属性对应的值,在输入时多加了一个空格,而服务器age对应的却是Integer类型,如果你使用servlet这事也好解决,但是如果你使用的是MVC框架,自动封装时就会得到一个类型转换异常,然而这个时候你是否有好的解决办法呢?
????? 这里我使用Filter来解决这一问题,这是最简单方便有效的解决方式,因为你不需要对每一个属性在封装前都去trim(),因为这是一件非常乏味的事情。大家都知道filter可以过滤我们想要它过滤的每一个请求,在这请求中有HttpServletRequest、HttpServletResponse。我们知道服务器取得客户端发送的参数都是通过HttpServletRequest来获取的,那我们可不可以在使用HttpServletRequest取值的时候就为每一个客户端提交的属性去除前后空格,或者其它的一些过滤操作。这肯定是可以的,那我们先来了解一下服务器是怎么取得客户端的值的。

1.getParameter(name),返回单个值。
2.getParameterValues(name),返回一个数组。
3.getParameterMap(),把客户端提交参数封装为一个Map返回。K:name,V:value。

????? 当我们使用servlet的时候一般都是使用前两种,struts1使用的第2种,struts2(xwork)则使用的第3种,那么我们只要在这三个方法调用的时候处理前后空格,那么返回到服务器的参数就又减少了一分出bug的机会,看下面的实现。

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.");
????????????}
????????}
????}

????/**
?????*?该类继承之HttpServletRequestWrapper,并重写了对应取得客户端相当参数值的所有的方法。
?????*?<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便使用此方法取值
????????????//?该方法返回一个Map,Map映射了客户端请求对应的键值(K,V)。
????????????if?(pm2?==?null)?{
????????????????pm2?=?new?ParameterMap2(super.getParameterMap());
????????????}
????????????return?pm2;
????????}

????????public?String[]?getParameterValues(String?name)?{
????????????//?Struts1使用此方法取得所有的参数值
????????????if?(excludeNames?!=?null?&&?excludeNames.contains(name))?{
????????????????return?super.getParameterValues(name);
????????????}
????????????return?(String[])?trim(super.getParameterValues(name));
????????}
????}

????/**
?????*?该此继承自HashMap。
?????*?
?????*?@version?1.0/2010-6-10?上午11:30:13
?????*?@author?Aidan
?????*?@see?HashMap
?????*/
????@SuppressWarnings(?{?"unchecked",?"serial"?})
????private?class?ParameterMap2?extends?HashMap?{

????????private?Set?entrySet;

????????/**
?????????*?若要构造此类对象,则需要传入一个map参数,该map对应的客户端请求的参数(K,V)。
?????????*?
?????????*?@param?map
?????????*????????????映射客户端参数。
?????????*/
????????public?ParameterMap2(Map?map)?{
????????????super(map);
????????}

????????public?Set?entrySet()?{
????????????//?xwork使用了此方法取值
????????????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);
????????}

????}

????/**
?????*?去除一个Object类型对应的前后空格,因为客户端提交参数有两种,一种:String,另一种:String[],此方法会自动判断调用哪个方法。
?????*?
?????*?@param?value
?????*????????????需要处理的参数。
?????*?@return?处理后的值。
?????*/
????protected?Object?trim(Object?value)?{
????????if?(value?instanceof?String[])?{
????????????return?trim((String[])?value);
????????}
????????return?trim(value.toString());
????}

????/**
?????*?去除某个字符串的前后空格。
?????*?
?????*?@param?value
?????*????????????需要处理的参数。
?????*?@return?处理后的值。
?????*/
????protected?String?trim(String?value)?{
????????if?(value?!=?null?&&?value.length()?>?0)?{
????????????return?value.trim();
????????}
????????return?value;
????}

????/**
?????*?去除某个数组中所有的值的前后空格。
?????*?
?????*?@param?values
?????*????????????需要处理的数组。
?????*?@return?处理后的值,当数组的length为1时,则返回一个String,反之返回一个数组。
?????*/
????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?不处理的对象。
?????*/
????public?List<String>?getExcludeNames()?{
????????return?excludeNames;
????}

}

????? 这个Filter实现原理非常简单,我会过滤所有的请求,HttpServletRequestWrapper2继承自HttpServletRequestWrapper,在构造函数中需要一个HttpServletRequest对象(这个request是web窗口创建的),然后我重载了上面所说的3个方法,在方法内部每次会去过滤当前值,这是利用了Java多态特性。在使用getParameterMap时较为麻烦,原理一样。
????? 当然我们有时候可能有些特殊情况不需要过滤前后空格或者其它一些规则,这里我们可以使用exclude属性来判断是否过滤此属性。
DEMO:

<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;
????}
}

热点排行