在实际的开发过程中,经常会使用String
类型的参数,而用户提交给后端的字符串可以说五花八门:""," “,” 123456","123456 “,” 123456 " 等等。如果不对这些空格进行处理,不仅会浪费存储空间,还会引起一些不必要的麻烦。
接收String
类型的参数通常两种方式:
1、使用url
或者form
表单的形式
对于这种情况,我们在参数绑定时注册下面的类即可:
@RestControllerAdvice public class GlobalHandler { private static final Logger LOGGER = LoggerFactory.getLogger(GlobalHandler.class); /** * url和form表单中的参数trim */ @InitBinder public void initBinder(WebDataBinder binder) { // 构造方法中 boolean 参数含义为如果是空白字符串,是否转换为 null // 即如果为 true,那么 " " 会被转换为 null,否者为"" binder.registerCustomEditor(String.class, new StringTrimmerEditor(false)); } }
2、接收Request Body
中JSON
或XML
对象参数
Spring MVC
默认使用 Jackson
对参数进行反序列化,所以对Jackson加入如下自定义转换器即可:
@Configuration public class ApplicationConfig { /** * Request Body中JSON或XML对象参数trim */ @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()); } }); }; } }
3、优化
对于这种所有项目都需要的通用配置,我们应该抽取一个公共模块,然后通过引入依赖来实现自动配置
在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