SpringBoot去除字符串类型参数的前后空格

在实际的开发过程中,经常会使用String类型的参数,而用户提交给后端的字符串可以说五花八门:""," “,” 123456","123456 “,”  123456 " 等等。如果不对这些空格进行处理,不仅会浪费存储空间,还会引起一些不必要的麻烦。

接收String类型的参数通常两种方式:

①.使用url或者form表单的形式
对于这种情况,我们在参数绑定时注册下面的类即可:

@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));
    }
}

②.接收Request BodyJSONXML对象参数
Spring MVC默认使用 Jackson 对参数进行反序列化,所以对Jackson加入如下自定义转换器即可:

@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());
                }
            });
        };
    }
}
优化

对于这种所有项目都需要的通用配置,我们应该抽取一个公共模块,然后通过引入依赖来实现自动配置

common模块下创建自动配置类 WebMvcStringTrimAutoConfiguration

package com.zzs.common.autoconfigure;

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;

@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 {
                        return StringUtils.trimWhitespace(jsonParser.getValueAsString());
                    }
                });
    }
}

然后在 resurces 创建 META-INF/spring.factories 文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.zzs.common.autoconfigure.WebMvcStringTrimAutoConfiguration
<think> 我们正在讨论Spring Boot的YAML配置文件,特别是当参数值包含空格时的处理方法。 在YAML中,字符串值通常不需要引号,但如果字符串包含特殊字符(如空格、冒号等),则可能需要引号来避免歧义。 对于带空格参数值,我们可以使用单引号或双引号将其括起来。 注意:单引号会转义特殊字符(即不会解析转义序列),而双引号则允许使用转义序列。 例如,在application.yml中: 不带空格的情况:example: value 带空格的情况: example1: 'Hello World' # 使用单引号 example2: "Hello World" # 使用双引号 另外,如果字符串中包含单引号或双引号,则需要注意: 使用单引号包裹时,字符串内的单引号需要转义(用两个单引号表示),而双引号则不需要转义。 使用双引号包裹时,字符串内的双引号需要用反斜杠转义,而单引号不需要。 但是,在Spring Boot中,我们通常使用@Value或@ConfigurationProperties来注入这些值。 在注入时,Spring Boot自动处理这些引号,所以我们只需要在配置文件中正确书写即可。 让我们通过一个例子来说明: 在application.yml中: my: message: 'Hello, Spring Boot!' 在Java类中,我们可以这样注入: @Value("${my.message}") private String message; 或者使用@ConfigurationProperties。 需要注意的是,如果使用双引号,那么字符串中的转义序列会被解析。例如: message: "Hello\nWorld" # 会解析为一个换行符 而单引号则不会: message: 'Hello\nWorld' # 会原样输出字符串"Hello\nWorld" 因此,根据是否需要转义序列来选择单引号或双引号。 另外,还有一种情况是参数值以空格开头或结尾,此时必须使用引号,否则空格会被忽略(因为YAML会去除字符串两端的空格)。 例如: withoutQuote: This has leading space? # 实际上,YAML会去除两端空格,所以值将是"This has leading space?"(没有两端空格) withQuote: ' This has leading space? ' # 保留两端空格 所以,处理带空格参数值,关键是正确使用引号。 总结: 1. 如果参数值包含空格或特殊字符,使用引号(单引号或双引号)包裹。 2. 根据是否需要转义序列选择引号类型。 3. 如果参数值需要保留开头或结尾的空格,必须使用引号。 生成相关问题: 1. 在Spring Boot的YAML配置中,如何包含特殊字符(如冒号)? 2. 使用@Value注入配置时,如果配置项不存在,如何设置默认值? 3. YAML配置中的多行字符串如何书写? 注意:我们引用的部分来源于Spring Boot官方文档关于YAML配置的说明[^1]。 </think>在 Spring Boot 的 YAML 配置文件中处理带空格参数值,需遵循以下规则: ### 1. **必须使用引号包裹** YAML 会将未加引号的空格视为分隔符,因此带空格参数值**必须用引号包裹**: ```yaml # ✅ 正确写法 app: greeting: "Hello World" # 双引号 description: 'This is a description' # 单引号 # ❌ 错误写法(值被截断) app: greeting: Hello World # 实际值会变成 "Hello" ``` ### 2. **引号类型选择** - **双引号 `"`**:支持转义字符(如 `\n` 换行) ```yaml message: "Line1\nLine2" # 解析为两行文本 ``` - **单引号 `'`**:禁用转义,内容原样输出 ```yaml message: 'Line1\nLine2' # 解析为 "Line1\\nLine2" ``` ### 3. **值首尾空格保留** 若需保留值开头/结尾的空格,必须用引号: ```yaml spaced: " value " # 值为 " value "(保留空格) trimmed: value # 值为 "value"(空格自动修剪) ``` ### 4. **代码中读取值** 通过 `@Value` 或 `@ConfigurationProperties` 注入时,Spring Boot自动处理引号: ```java // 方式1:@Value 注入 @Value("${app.greeting}") private String greeting; // "Hello World" // 方式2:@ConfigurationProperties 绑定 @ConfigurationProperties(prefix = "app") public class AppConfig { private String greeting; // 自动匹配值 } ``` ### 常见问题解决 #### ❌ 报错:`Could not resolve placeholder` **原因**:未加引号导致值被截断 **修复**: ```yaml # 错误配置 error: value with space # 修正后 correct: "value with space" ``` #### ❌ 特殊字符冲突(如 `:`) ```yaml # 错误(冒号被解析为符号) url: http://example.com?param=value # 正确 url: "http://example.com?param=value" ``` > 参考:Spring Boot 官方文档中关于 [YAML 配置语法](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.yaml) 的说明[^1]
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值