首页 > 其他分享 >项目中统一处理请求中的字符串参数的空格

项目中统一处理请求中的字符串参数的空格

时间:2024-04-14 13:22:05浏览次数:21  
标签:Map return String value 空格 字符串 new public 请求

测试controller

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {

    @GetMapping("/testStringParamTrim")
    public TestObjectInfo testStringParamTrim(@RequestParam String goodsId, String goodsName) {
        return new TestObjectInfo().setGoodsId(goodsId).setGoodsName(goodsName);
    }

    @GetMapping("/testObjectTrim")
    public TestObjectInfo testObjectTrim(TestObjectInfo objectInfo) {
        return objectInfo;
    }

    @PostMapping("/testBodyObjectTrim")
    public TestObjectInfo testBodyObjectTrim(@RequestBody TestObjectInfo objectInfo) {
        return objectInfo;
    }

    @Data
    @Accessors(chain = true)
    public static class TestObjectInfo {
        private String goodsId;
        private String goodsName;
    }
}

测试去除 GET请求参数 和 POST请求体 的属性值的前后空格。

处理请求参数

@Configuration
public class WebConfig {

    @Autowired
    public void setWebBindingInitializer(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
        WebBindingInitializer webBindingInitializer = requestMappingHandlerAdapter.getWebBindingInitializer();
        if (webBindingInitializer instanceof ConfigurableWebBindingInitializer) {
            //添加属性编辑器注册器,注册String类型的属性编辑器
            PropertyEditorRegistrar[] propertyEditorRegistrars = ((ConfigurableWebBindingInitializer) webBindingInitializer).getPropertyEditorRegistrars();
            if (Objects.isNull(propertyEditorRegistrars)) {
                propertyEditorRegistrars = new PropertyEditorRegistrar[0];
            }
            int originalLen = propertyEditorRegistrars.length;
            propertyEditorRegistrars = Arrays.copyOf(propertyEditorRegistrars, originalLen + 1);
            propertyEditorRegistrars[originalLen] = new CustomPropertyEditorRegistrar();
            ((ConfigurableWebBindingInitializer) webBindingInitializer).setPropertyEditorRegistrars(propertyEditorRegistrars);
        }
    }

    public static class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {

        @Override
        public void registerCustomEditors(PropertyEditorRegistry registry) {
            registry.registerCustomEditor(String.class, new StringTrimmerEditor(false));
        }
    }

}

通过扩展 SpringMVC 中的 PropertyEditorRegistrar 来实现,这种方式可以实现将请求参数中的字符串参数都去除前后空格,但有一定的隐患,不确定是否会影响项目中 Spring 的其他使用场景。

处理请求体

@Component
public class CustomerJackson2ObjectMapperBuilderCustomizer implements Jackson2ObjectMapperBuilderCustomizer {
    @Override
    public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        jacksonObjectMapperBuilder.deserializerByType(String.class, new JsonDeserializer<String>() {
            @Override
            public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                String value = jsonParser.getValueAsString();
                if (Objects.nonNull(value)) {
                    return value.trim();
                }
                return value;
            }
        });
    }
}

这种方式通过 自定义 jackson 反序列化字符串时的逻辑,来去除前后空格,但限制了 jackson,不支持 fastjson 或者其他 json 框架且影响项目中其他的序列化场景。

更好的方式

@Configuration
public class WebConfig {

    @Bean
    public FilterRegistrationBean<ParamsFilter> paramsFilter() {
        FilterRegistrationBean<ParamsFilter> registration = new FilterRegistrationBean();
        registration.setFilter(new ParamsFilter());
        registration.addUrlPatterns("/*");
        registration.setName("paramsFilter");
        return registration;
    }

    public static class ParamsFilter extends OncePerRequestFilter {

        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            ParameterRequestWrapper paramRequest = new ParameterRequestWrapper(request);
            filterChain.doFilter(paramRequest, response);
        }
    }

    @Slf4j
    public static class ParameterRequestWrapper extends HttpServletRequestWrapper {

        private final Map<String, String[]> params = new HashMap<>();

        public ParameterRequestWrapper(HttpServletRequest request) {
            // 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似
            super(request);
            //将参数表,赋予给当前的Map以便于持有request中的参数
            Map<String, String[]> requestMap = request.getParameterMap();
            this.params.putAll(requestMap);
            log.info("转化前请求参数:{}", JSON.toJSONString(params));
            this.modifyParameterValues();
            log.info("转化后请求参数:{}", JSON.toJSONString(params));
        }

        /**
         * 重写getInputStream方法  post类型的请求参数必须通过流才能获取到值
         */
        @Override
        public ServletInputStream getInputStream() throws IOException {
            //非json类型,直接返回
            String contentType = super.getHeader(HttpHeaders.CONTENT_TYPE);
            if (StringUtils.isEmpty(contentType) || !contentType.startsWith(MediaType.APPLICATION_JSON_VALUE)) {
                return super.getInputStream();
            }
            String json = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8);
            log.info("转化前请求体:{}", json);
            Map<String, Object> map = StringJsonUtils.jsonStringToMap(json);
            log.info("转化后请求体:{}", JSON.toJSONString(map));
            ByteArrayInputStream bis = new ByteArrayInputStream(JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8));
            return new MyServletInputStream(bis);
        }

        /**
         * 将parameter的值去除空格后重写回去
         */
        private void modifyParameterValues() {
            Map<String, String[]> newParams = new HashMap<>();
            for (Map.Entry<String, String[]> entry : params.entrySet()) {
                String key = entry.getKey();
                String[] values = entry.getValue();
                if (Objects.nonNull(values) && values.length > 0) {
                    values[0] = values[0].trim();
                }
                newParams.put(key, values);
            }
            params.putAll(newParams);
        }

        /**
         * 重写getParameter 参数从当前类中的map获取
         */
        @Override
        public String getParameter(String name) {
            String[] values = params.get(name);
            if (Objects.nonNull(values) && values.length > 0) {
                return values[0];
            }
            return null;
        }

        /**
         * 重写getParameterValues
         */
        @Override
        public String[] getParameterValues(String name) {//同上
            return params.get(name);
        }

        public static 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() throws IOException {
                return bis.read();
            }
        }

    }
}
public class StringJsonUtils {

    /**
     * jsonstring 转换成map,并去除字符串值的前后空字符串--支持嵌套 k-v v=list
     *
     * @param jsonString 必须是 {}对象
     * @return
     */
    public static Map<String, Object> jsonStringToMap(String jsonString) {
        Map<String, Object> map = JSON.parseObject(jsonString);
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object value = entry.getValue();
            if (Objects.isNull(value)) {
                continue;
            }
            if (value instanceof String) {
                entry.setValue(((String) value).trim());
            } else if (value instanceof Map) {
                Map<String, Object> stringObjectMap = jsonStringToMap(JSON.toJSONString(value));
                entry.setValue(stringObjectMap);
            } else if (value instanceof List) {
                List<Object> stringObjects = stringListTrim(JSON.toJSONString(value));
                entry.setValue(stringObjects);
            }
        }
        return map;
    }

    /**
     * List中的字符串去除空格
     *
     * @param jsonString
     */
    private static List<Object> stringListTrim(String jsonString) {
        JSONArray objects = JSONArray.parseArray(jsonString);
        List<Object> newObjects = new ArrayList<>();
        for (Object object : objects) {
            if (Objects.isNull(object)) {
                continue;
            }
            if (object instanceof String) {
                newObjects.add(((String) object).trim());
            } else if (object instanceof Map) {
                Map<String, Object> stringObjectMap = jsonStringToMap(JSON.toJSONString(object));
                newObjects.add(stringObjectMap);
            } else if (object instanceof List) {
                List<Object> stringObjects = stringListTrim(JSON.toJSONString(object));
                newObjects.add(stringObjects);
            } else {
                newObjects.add(object);
            }
        }
        return newObjects;
    }

}

通过一个 过滤器,来统一处理请求参数和请求体,且不耦合 Spring 及 具体的 json 框架。

标签:Map,return,String,value,空格,字符串,new,public,请求
From: https://www.cnblogs.com/strongmore/p/18050080

相关文章

  • 代码随想录算法训练营第8天 | 字符串 344.反转字符串 541. 反转字符串II 卡码网:54.
    leetcode344.反转字符串题目344.反转字符串编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用O(1)的额外空间解决这一问题。解题思路实现代码......
  • 代码随想录算法训练营第9天 | 字符串(KMP算法) 28. 找出字符串中第一个匹配项的下标
    leetcode28.找出字符串中第一个匹配项的下标题目28.找出字符串中第一个匹配项的下标给你两个字符串haystack和needle,请你在haystack字符串中找出needle字符串的第一个匹配项的下标(下标从0开始)。如果needle不是haystack的一部分,则返回-1。解题思路实现代......
  • 字符串基础
    字符串的常见函数:strlen()//计算字符串的长度,即字符串中字符的个数(不包括字符串末尾的空字符'\0'strcpy()//将一个字符串复制到另一个字符串中。目标字符串必须有足够的空间来容纳被复制的字符串。strcat()//将一个字符串追加到另一个字符串的末尾。目标字符......
  • Sql Server对等复制中将截断字符串或二进制数据。 (源: MSSQLServer,错误号: 8152)
    近期发现好好的复制突然出现了报错,导致备份库数据不一致的问题,如下 一直以为是发布数据库进行了DDL操作没有同步到这边来,导致数据同步时长度不够导致的,结果把表都检查了一遍也没发现啥不对劲最后只好去找相关资料,结果找到了官方资料(目前老项目用的14版本) 这边有几个......
  • 字符串
    1.基本命令集 Tcl将所有的变量值视作字符串,并将他们作为字符串来保存。下表列出了字符串操作的几个常用命令。 命令描述append将值追加到字符串尾binary二进制字符串操作format字符串格式化regexp正则表达式(用于字符串模式匹配)regsub用正则表......
  • 字符串占位符替换——StringSubstitutor
    1背景众所周知Java中的字符串占位符替换非常不友好,无论是String#format还是MessageFormat#format都只能说能用,但说不上好用,关于以上两种字符串格式化的用法请参考:JavaStringformat和MessageFormatformat,本文推荐org.apache.commons.text.StringSubstitutor,StrSubstitutor是......
  • 二维字符串数组的传参时与指针互转时的问题
    二维数组如何传参二维字符串数组,转char**会导致的问题,以及编译报错要想得到正确的结果,需要按如下方式去写传参:#include<stdio.h>#include<string.h>//intchar_arr_copy(char**dest)//这样定义传参类型将导致编译报错,在低版本的编译器下或者没有报错但是得不到正确......
  • JSON.parse() 方法中里面有函数,转化完成后是字符串问题
    要将JSON字符串中的函数还原回原来的函数对象,你可以使用JSON.parse()方法,并提供一个reviver函数来将字符串表示的函数重新转换为函数对象。以下是你可以使用的代码示例:varobj={"name":"Runoob","alexa":function(){return10000;},"site":"www.runoob.com"};//......
  • String类型转LPCTSTR -----理解C++中的字符串类型转换
    在看代码时,发现有时候会把string类型转换为LPCTSTR,刚开始不理解为什么要做这个转换,所以做了一些调查,现在记录如下是这样的,STRING是代表C++中的字符串string,而LPCTSTR代表的是Windows系统中的字符串类型。也就是说,这样转换的目的是为了把C++中的字符串string转换为Windows系......
  • C#长sql语句换行(长字符串换行且换行符不计入字符串中)
    示例:在红圈处敲回车vs会将其分段并拼接,这不是我想要的效果、不仅不美观还不好复制sql语句只需要在字符串前加一个@号就可以解决......