一、背景
在做管理后台页面查询,我们经常会遇到多条件查询的情况,而且每个条件字段,对应的value值类型也可能不同, 可能是整型,也可能是字符串类型,也可能是null。 总结下查询传入后端接口的值有 null, "", undefined,正常的数字,正常的字符串。常规的做法,会在每个查询接口的入口处(正式做业务逻辑前)做参数校验,只接收预期的值。这样实现起来,会发现一堆的if else,如果查询接口多的话,会看起来非常的臃肿。
二、如何优雅实现处理
我们知道对客户端请求过滤有两种方式,如下:
-
过滤器Filter: 类级别,粒度较粗
-
拦截器intecepter: 方法级别, 粒度较细
由于针对的是所有类接口,选用过滤器进行粗粒度参数过滤即可。Filter可以过滤想要它过滤的每一个请求,在这请求中有HttpServletRequest、HttpServletResponse, 我们知道服务器取得客户端发送的参数都是通过HttpServletRequest来获取的。 但遗憾的是HttpServletRequest没有提供对应的setParameter方法,允许修改客户端发送过来的值。因此我们需要自定义HttpServletRequestWrapper来包装一下当前HttpServletRequest请求, 自定义HttpServletRequestWrapper的提供可修改客户端值的setParameter方法。
/**
*
*自定义HttpServletRequestWrapper
*/
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.HashMap;
import java.util.Map;
public class MyHttpServletRequestWapper extends HttpServletRequestWrapper {
/**
* 用于存储请求参数
*/
private Map<String , String[]> params = new HashMap<String, String[]>();
/**
* 包装一下当前请求
* @param request
* @throws IllegalArgumentException if the request is null
*/
public MyHttpServletRequestWapper(HttpServletRequest request) {
super(request);
// 把请求参数添加到我们自己的map当中
this.params.putAll(request.getParameterMap());
}
/**
* 添加参数到map中
* @param name
* @param value
*/
public void setParameter(String name, Object value) {
if (value != null) {
if (value instanceof String[]) {
params.put(name, (String[]) value);
} else if (value instanceof String) {
params.put(name, new String[]{(String) value});
} else {
params.put(name, new String[]{String.valueOf(value)});
}
}
}
/**
* 重写getParameter,代表参数从当前类中的map获取
* @param name
* @return
*/
@Override
public String getParameter(String name) {
String[]values = params.get(name);
if(values == null || values.length == 0) {
return null;
}
return values[0];
}
/**
* 重写getParameterValues方法,从当前类的 map中取值
* @param name
* @return
*/
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
}
/**
*
* 不合法参数过滤器
*/
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class InvalidParamFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(InvalidParamFilter.class)
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
/**
* 参数预处理
* @param request
* @param response
* @param chain
* @throws IOException
* @throws ServletException
*/
@SuppressWarnings("unchecked")
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//包装一下请求
MyHttpServletRequestWapper requestWrapper = new MyHttpServletRequestWapper(
(HttpServletRequest) request);
//获取原始请求参数
Map<String, String[]> paramterMap = requestWrapper.getParameterMap();
//预处理原始请求参数
for(Map.Entry<String, String[]> entry : paramterMap.entrySet()){
String[] values = entry.getValue();
//1、只处理单个参数
if(values.length !=1){
continue;
}
if(Objects.isNull(values[0]) || StringUtils.isBlank(values[0]) || values[0].equals("undefined")) {
//2、把处理后的参数放回去, null、""、undefined等输入参数值统一转换为字符串"0"
requestWrapper.setParameter(entry.getKey(), "0");
}
}
// 3、放行,把我们的requestWrapper放到方法当中
chain.doFilter(requestWrapper, response);
}
@Override
public void destroy() {}
}
网友评论