springBoot过滤器去除请求参数前后空格
在一个阳光明媚的早晨,客服小姐姐甜美的声音照常的响起:”昨天客户平台数千条用户充值失败,钱打到客户手中了,但是订单生成失败“
啊这…这……阳光逐渐暗淡,温馨的画面变成了黑白,甜美的声音也逐渐变的刺耳。脑子中出现了四个字【重大事故】
细细思索一番,昨天
?? 近一周都没有了新版本上线,怎么昨天出现问题???? 带着满脑子问号冲向工位
迅速走过以下操作
不信任原则
迅速验证消息的真实性(消息属实)- 查错误数据,查看数据范围,评定事故等级(还好:51条失败订单)
- 回复客服以及上级,说明事情已经开始处理
- 根据上面出错数据查询日志,定位问题
- 经过比对用户更改了微信参数【前面多打一个空格】
- 微信回调参数与数据库中保存进行比对【多一个空格必定比对不成功】
- 结局就是,回调失败,订单生成失败
- 立刻联系客户修复错误参数(保证不再扩大事故范围)
- 立即着手修复错误数据,保证平台运行
- 随后进行程序优化【即增加过滤器去除请求参数前后空格】
是时候站起来喝杯茶,客户很好说话,没有问责,没有争吵。看看窗外的天,乌云散去,阳光逐渐洒满大地,依旧是温馨和谐的日常~
随后,附上代码
每个SpringBoot项目增加过滤器(对外提供API的模块,web网站模块,微信小程序模块。。。)
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
/**
* 去除参数头尾空格过滤器
*
* @return
*/
@Bean
public FilterRegistrationBean trimFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new TrimFilter());
registration.addUrlPatterns("/*");
registration.setName("TrimFilter");
registration.setOrder(Integer.MAX_VALUE - 1);
return registration;
}
}
common(公共组件)中增加过滤器
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class TrimFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(new TrimHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
}
@Override
public void destroy() {
}
}
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class TrimHttpServletRequestWrapper extends javax.servlet.http.HttpServletRequestWrapper {
private Map<String , String[]> params = new HashMap<>();
public TrimHttpServletRequestWrapper(HttpServletRequest request) {
// 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似
super(request);
//将参数表,赋予给当前的Map以便于持有request中的参数
this.params.putAll(request.getParameterMap());
this.modifyParameterValues();
}
/**
* 重写getInputStream方法 post类型的请求参数必须通过流才能获取到值
*/
@Override
public ServletInputStream getInputStream() throws IOException {
//非json类型,直接返回
if(!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)){
return super.getInputStream();
}
//为空,直接返回
String json = IOUtils.toString(super.getInputStream(), "utf-8");
if (!StringUtils.hasLength(json)) {
return super.getInputStream();
}
ByteArrayInputStream bis = new ByteArrayInputStream(JsonTrimUtils.jsonTrim(json).getBytes("utf-8"));
return new MyServletInputStream(bis);
}
/**
* 将parameter的值去除空格后重写回去
*/
public void modifyParameterValues(){
Set<String> set =params.keySet();
Iterator<String> it=set.iterator();
while(it.hasNext()){
String key= it.next();
String[] values = params.get(key);
for (int i = 0; i < values.length; i++) {
values[i] = values[i].trim();
}
params.put(key, values);
}
}
/**
* 重写getParameter 参数从当前类中的map获取
*/
@Override
public String getParameter(String name) {
String[]values = params.get(name);
if(values == null || values.length == 0) {
return null;
}
return values[0];
}
/**
* 重写getParameterValues
*/
@Override
public String[] getParameterValues(String name) {//同上
return params.get(name);
}
class MyServletInputStream extends ServletInputStream{
private ByteArrayInputStream bis;
public MyServletInputStream(ByteArrayInputStream bis){
this.bis=bis;
}
@Override
public boolean isFinished() {
return true;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener listener) {
}
@Override
public int read() {
return bis.read();
}
}
}
工具类,去除JSON中值前后空格
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONValidator;
import java.util.Iterator;
import java.util.Map;
/**
* json工具类
* @Version 1.0
*/
public final class JsonTrimUtils {
/**
* 构造器
*/
private JsonTrimUtils() {
}
/**
* 去除json值前后空格
* @param jsonStr jsonStr
* @return
*/
public static JSON jsonTrim(String jsonStr) throws Exception {
if (JSONValidator.from(jsonStr).getType() == JSONValidator.Type.Object) {
return jsonTrim(JSONObject.parseObject(jsonStr));
} else if (JSONValidator.from(jsonStr).getType() == JSONValidator.Type.Array) {
JSONArray array = JSONArray.parseArray(jsonStr);
jsonTrimArray(array);
return array;
}
//前后端联调传值类型不同,及早的暴露问题,避免隐藏问题。
throw new Exception("非JSON参数");
}
/**
* 去除json值前后空格
* @param json jsonStr
* @return
*/
public static JSON jsonTrim(JSON json) throws Exception {
if (json instanceof JSONObject) {
return jsonTrim(json);
} else if (json instanceof JSONArray) {
jsonTrimArray((JSONArray) json);
return json;
}
throw new Exception("非JSON参数");
}
/**
* 去除value的空格
*
* @param jsonObject jsonObject
* @return
*/
public static JSONObject jsonTrim(JSONObject jsonObject) {
Iterator<Map.Entry<String, Object>> iterator = jsonObject.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> next = iterator.next();
Object value = next.getValue();
if (value != null) {
if (value instanceof String) {
//清空值前后空格
jsonObject.put(next.getKey(), ((String) value).trim());
} else if (value instanceof JSONObject) {
jsonTrim((JSONObject) value);
} else if (value instanceof JSONArray) {
jsonTrimArray((JSONArray) value);
}
}
}
return jsonObject;
}
/**
* 清空JSONArray 值前后空格
* @param array
*/
private static void jsonTrimArray(JSONArray array) {
if (array.size() > 0) {
for (int i = 0; i < array.size(); i++) {
Object object = array.get(i);
if (object != null) {
if (object instanceof String) {
array.set(i, ((String) object).trim());
} else if (object instanceof JSONObject) {
jsonTrim((JSONObject) object);
} else if (object instanceof JSONArray) {
jsonTrimArray((JSONArray) object);
}
}
}
}
}
}
JSON 的支持使用的JAR
<!-- Json解析 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.69_sec11</version>
</dependency>