注解方式的参数使用过滤器进行过滤
最近做项目时,页面传递给后台的特殊字符很烦人,想写一个公共方法来给需要使用的地方调用,但是后来发现,要调用的地方实在太多,万一有什么变动的话,改起来烦死人。后来发现使用过滤器可以完成这个功能。
?
过滤器中的主要代码如下:
?
@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; chain.doFilter(new HTMLCharacterRequest(req), resp);}?其中?HTMLCharacterRequest 是继承与 HttpServletRequest包装类的:
?
?
public class HTMLCharacterRequest extends HttpServletRequestWrapper {public HTMLCharacterRequest(HttpServletRequest request) {super(request);}@Overridepublic String getParameter(String name){return filter(super.getParameter(name)); }/** * 过滤请求参数值 * @param parameter * @return */private String filter(String parameter) {if(StringHelper.isNullOrEmpty(parameter)){return null;}return StringEscapeUtils.escapeSql(StringHelper.unescape(parameter));} }?StringHelper.unescape()方法内容如下:
?
public static String unescape(String src) {StringBuffer tmp = new StringBuffer();tmp.ensureCapacity(src.length());int lastPos = 0, pos = 0;char ch;while (lastPos < src.length()) {pos = src.indexOf("%", lastPos);if (pos == lastPos) {if (src.charAt(pos + 1) == 'u') {ch = (char) Integer.parseInt(src.substring(pos + 2, pos + 6), 16);tmp.append(ch);lastPos = pos + 6;} else {ch = (char) Integer.parseInt(src.substring(pos + 1, pos + 3), 16);tmp.append(ch);lastPos = pos + 3;}} else {if (pos == -1) {tmp.append(src.substring(lastPos));lastPos = src.length();} else {tmp.append(src.substring(lastPos, pos));lastPos = pos;}}}return tmp.toString();}?
这样做完之后,前端传递过来的escape("xxx") 就可以在Controller中可以使用request.getParameter("xxx")的形式获取到解码之后并且对数据库操作无影响的字符串了。
截图如下:
可以看到request的真正类型是?HTMLCharacterRequest?,并且 通过?request.getParameter("provinceName") 获取到的值 也是 解码并且对数据库无影响的值。

?
但是,这个时候就有个问题了,如下:

方法参数列表中 使用 @RequestParam 获取到的参数 却是未解码的。
为什么呢???
?
后来跟踪Annotation源码发现了如下的一段代码:
(详见:org.springframework.web.bind.annotation.support.HandlerMethodInvoker ?的 resolveRequestParam方法)
?
if (paramValue == null) {String[] paramValues = webRequest.getParameterValues(paramName);if (paramValues != null) {paramValue = (paramValues.length == 1 ? paramValues[0] : paramValues);}}if (paramValue == null) {if (defaultValue != null) {paramValue = resolveDefaultValue(defaultValue);}else if (required) {raiseMissingParameterException(paramName, paramType);}paramValue = checkValue(paramName, paramValue, paramType);}?
由此发现,在源码中是使用 getParameterValues 方法来获取参数值的,而不是 getParameter方法
所以需要在?HTMLCharacterRequest ?中再 ?@override 一下?getParameterValues? 的方法:
?
?
@Override public String[] getParameterValues(String name) { return filter(super.getParameterValues(name)); }/** * 过滤请求参数值 * @param parameters * @return */private String[] filter(String[] parameters) {if(parameters.length == 0){return null;}for (int i=0; i<parameters.length; i++) {parameters[i] = StringEscapeUtils.escapeSql(StringHelper.unescape(parameters[i]));}return parameters;} ?
这个时候再来看 @RequestParam 注解的参数值 就是 解码之后的了:
