Spring 对请求参数的优雅处方式(重写序列化方法)

Spring 对请求参数的优雅处方式(重写序列化方法)

描述

在我们日常项目开发过程中,往往会遇到前端请求参数中有空格的情况,前端提交后后端的字符串什么形式的都有(例: " xxx ", " xxxxx ", "", "null" 等等),这样不对空格进行处理直接传参,不仅浪费空间,还会造成数据跟查询结果有出入的情况,引起很多不必要的麻烦。那么,怎么快速的去除前端传参中字符串类型参数的前后空格呢?

前端传参方式介绍

在开发过程中,后端接收前端的传参有两种方式:

  1. 使用 url 或者 form 表单进行传参,后端通过 @RequestParam 注解的方式,从 url 中获取参数。
  2. 使用 body 进行传参,后端通过 @RequestBody 注解进行参数的接收。

对于 url 或者 form 表单的方式,我们在参数绑定时注册下面的类即可对参数进行处理

java 复制代码
@RestControllerAdvice
public class GlobalHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalHandler.class);

    /**
     *  url和form表单中的参数trim
     * @param binder
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        // 构造方法中 boolean 参数含义为如果是空白字符串, 是否转换为 null
        // 即如果为 true, 那么 "" 会被转换为 null, 否者为""
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
    }
}

对于使用 body 中的 JSON 或者 XML 的传参方式,在 Spring 中,默认是使用的 Jackson 对参数进行序列化处理,所以对 Jackson 加入如下的自定义转换器即可实现:

java 复制代码
@Configuration
public class ApplicationConfig {

    /**
     * Request Body中JSON或XML对象参数trim
     *
     * @return
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return jacksonObjectMapperBuilder -> {
            // 时区问题
            jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());
            jacksonObjectMapperBuilder.deserializerByType(String.class, new StdScalarDeserializer<String>(String.class) {
                @Override
                public String deserialize(JsonParser jsonParser, DeserializationContext ctx)
                        throws IOException {
                    // 去除前后空格
                    return StringUtils.trimWhitespace(jsonParser.getValueAsString());
                }
            });
        };
    }
}

代码实现:

1、重写序列化方式代码

对于上述的两种传参方式,我们优化一下,将两个合并成一个统一的类来进行实现;

java 复制代码
package com.wblog.framework.config;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.Servlet;
import java.io.IOException;

/**
 * 序列化处理前端请求数据的前后空格
 * @author wangxk
 * @date 2023-12-27
 */
@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
public class WebMvcStringTrimAutoConfiguration {

    @ControllerAdvice
    public static class ControllerStringParamTrimConfig {
        /**
         * url和form表单中的参数trim
         */
        @InitBinder
        public void initBinder(WebDataBinder binder) {
            // 构造方法中 boolean 参数含义为如果是空白字符串,是否转换为null
            // 即如果为true,那么 " " 会被转换为 null,否者为 ""
            StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(false);
            binder.registerCustomEditor(String.class, stringTrimmerEditor);
        }
    }

    /**
     * Request Body中JSON或XML对象参数trim
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder
                .deserializerByType(String.class, new StdScalarDeserializer<String>(String.class) {
                    @Override
                    public String deserialize(JsonParser jsonParser, DeserializationContext ctx)
                            throws IOException {
                        System.out.println("Jackson2ObjectMapperBuilderCustomizer jsonParser.getValueAsString() = " + jsonParser.getValueAsString());
                        return StringUtils.trimWhitespace(jsonParser.getValueAsString());
                    }
                });
    }
}

2、设置类自动加载到 Spring 中

由于 Spring 启动时,是默认加载同级别目录下所有的 Bean,如果我们重写的 WebMvcStringTrimAutoConfiguration 类是在外部目录时,我们就需要手动去指定一下需要加载的类,在 resurces 下创建 META-INF/spring.factories 文件,将我们的类加到里面去:

powershell 复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.wblog.framework.config.WebMvcStringTrimAutoConfiguration

参考链接:

  1. SpringBoot去除字符串类型参数的前后空格
  2. Springmvc请求参数的优雅处方式
相关推荐
敲代码娶不了六花8 分钟前
jsp | servlet | spring forEach读取不了对象List
java·spring·servlet·tomcat·list·jsp
Yhame.9 分钟前
深入理解 Java 中的 ArrayList 和 List:泛型与动态数组
java·开发语言
是小崔啊2 小时前
开源轮子 - EasyExcel02(深入实践)
java·开源·excel
myNameGL2 小时前
linux安装idea
java·ide·intellij-idea
青春男大2 小时前
java栈--数据结构
java·开发语言·数据结构·学习·eclipse
HaiFan.3 小时前
SpringBoot 事务
java·数据库·spring boot·sql·mysql
我要学编程(ಥ_ಥ)3 小时前
一文详解“二叉树中的深搜“在算法中的应用
java·数据结构·算法·leetcode·深度优先
music0ant3 小时前
Idea 添加tomcat 并发布到tomcat
java·tomcat·intellij-idea
计算机徐师兄3 小时前
Java基于SSM框架的无中介租房系统小程序【附源码、文档】
java·微信小程序·小程序·无中介租房系统小程序·java无中介租房系统小程序·无中介租房微信小程序
源码哥_博纳软云3 小时前
JAVA智慧养老养老护理帮忙代办陪诊陪护小程序APP源码
java·开发语言·微信小程序·小程序·微信公众平台