使用场景
- 需要对项目中的所有输入进行前后空格的过滤
- 替换一些特殊字符的输入
- 解密一些关键性字段
- 注入一些参数在请求方法的时候
- 返回参数统一处理,如果后台返回空,统一返回成功信息
- 身份证等特殊字符统一做 * 号处理等
code
主要就是用到了 RequestBodyAdvice
和 ResponseBodyAdvice
两个接口和一个注解@ControllerAdvice
- 请求参数去空格
package com.sanri.test.testmvc.config;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject;import com.alibaba.fastjson.serializer.SerializerFeature;import lombok.extern.slf4j.Slf4j;import org.apache.commons.io.IOUtils;import org.apache.commons.lang3.ObjectUtils;import org.apache.commons.lang3.StringUtils;import org.springframework.core.MethodParameter;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpInputMessage;import org.springframework.http.MediaType;import org.springframework.http.converter.HttpMessageConverter;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.Type;import java.util.Iterator;import java.util.Map;/** * 去掉前后空格和特殊字符 */@Slf4j@ControllerAdvicepublic class CustomRequestBodyAdvice implements RequestBodyAdvice { @Override public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) { return true; } @Override public Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) { return body; } @Override public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException { return new CustomHttpInputMessage(httpInputMessage); } @Override public Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) { return body; } class CustomHttpInputMessage implements HttpInputMessage{ private HttpInputMessage origin; public CustomHttpInputMessage(HttpInputMessage httpInputMessage) { this.origin = httpInputMessage; } @Override public InputStream getBody() throws IOException { HttpHeaders headers = origin.getHeaders(); InputStream body = origin.getBody(); // 空参,get 请求,流为空,非 application/json 请求,不处理参数 MediaType contentType = headers.getContentType(); if(contentType == null){return body;} if(!contentType.isCompatibleWith(MediaType.APPLICATION_JSON)){return body;} if(body == null){return body;} String params = IOUtils.toString(body, "utf-8"); if(StringUtils.isBlank(params)){return body;} // 正式过滤 json 参数 Object parse = JSON.parse(params); if (parse instanceof JSONArray) { JSONArray jsonArray = (JSONArray) parse; trimJsonArray(jsonArray); } else if (parse instanceof JSONObject) { trimJsonObject((JSONObject) parse); } else { log.error("参数不支持去空格:" + parse+ " contentType:"+contentType); } return IOUtils.toInputStream(JSON.toJSONString(parse, SerializerFeature.WriteMapNullValue), "UTF-8"); } private void trimJsonObject(JSONObject jsonObject) { Iterator<Map.Entry<String, Object>> iterator = jsonObject.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Object> next = iterator.next(); String key = next.getKey(); Object value = next.getValue(); if (value instanceof JSONArray) { trimJsonArray((JSONArray) value); }else if(value instanceof JSONObject){ trimJsonObject((JSONObject) value); }else if(value instanceof String){ String trimValue = StringUtils.trim(ObjectUtils.toString(value)); next.setValue(filterDangerString(trimValue)); } } } private void trimJsonArray(JSONArray jsonArray) { for (int i = 0; i < jsonArray.size(); i++) { Object object = jsonArray.get(i); if(object instanceof JSONObject){ JSONObject jsonObject = jsonArray.getJSONObject(i); trimJsonObject(jsonObject); }else if(object instanceof String){ String trimValue = StringUtils.trim(ObjectUtils.toString(object)); jsonArray.set(i,trimValue); } } } @Override public HttpHeaders getHeaders() { return origin.getHeaders(); } private String filterDangerString(String value) { if(StringUtils.isBlank(value))return value; value = value.replaceAll(";", ";"); value = value.replaceAll("'", "‘"); value = value.replaceAll("<", "《"); value = value.replaceAll(">", "》"); value = value.replaceAll("\\(", "("); value = value.replaceAll("\\)", ")"); value = value.replaceAll("\\?", "?"); return value; } }}
- 使用 ResponseBodyAdvice 处理返回空返回
package com.sanri.test.testmvc.config;import com.alibaba.fastjson.JSONObject;import org.springframework.core.MethodParameter;import org.springframework.http.MediaType;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServerHttpResponse;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.RestControllerAdvice;import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;import java.lang.reflect.AnnotatedType;import java.lang.reflect.Executable;import java.lang.reflect.Type;/** * 可以定义空返回的时候返回正确的信息,如成功信息 */@RestControllerAdvicepublic class CustomResponseBodyAdvice implements ResponseBodyAdvice { @Override public boolean supports(MethodParameter returnType, Class converterType) { return true; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { Executable executable = returnType.getExecutable(); AnnotatedType annotatedReturnType = executable.getAnnotatedReturnType(); Type type = annotatedReturnType.getType(); return JSONObject.parseObject("{\"result\":0}"); }}
项目代码
我弄了一个例子代码,关于 java 中每个工具的使用,如 rabbitmq
,mysql
,mybatis
,springboot
,springmvc
可以方便初学者,更方便我自己随时取用,github 地址
https://gitee.com/sanri/example
sanri-tools 工具
推广下我的小工具,很实用的解决项目中的一些麻烦的事情,欢迎来 github 点星,fork
https://gitee.com/sanri/sanri-tools-maven