SpringBoot版本:2.1.6.RELEASE
SpringMVC版本:5.1.8.RELEASE
當遇到前端沒有填寫的表單字段被作爲空字符串傳到後端時,在業務邏輯中處理顯得有點蹩腳,那正常的解法應該是擴展Spring,畢竟Spring擴展性很強,這是基本思路。
注:這些解決問題的辦法都是解決由Spring進行綁定的操作,比如自動創建一個類,將參數綁定上去。你自己通過HttpServletRequest.getParamenter("key")
是需要自己封裝處理的的。
解決辦法:
- 自己擴展實現一個ConfigurableWebBindingInitializer,註冊爲Bean,需要設置爲較高優先級(不建議使用,因爲SpringBoot中預留的口子不明顯)
@InitBinder
+@ControllerAdvice
實現。@ControllerAdvice
標註的類中的方法被@InitBinder
標註後,所有Controller可用。(解決request.getParameter(“key”)的問題,如果是@RequestBody則無效)- @RequestBody的處理在
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor#resolveArgument
,默認採用MappingJackson2HttpMessageConverter
進行解析,Jackson的配置是通過JacksonAutoConfiguration
,其中有Jackson2ObjectMapperBuilderCustomizer
可以配置jackson初始化時的ObjectMapper。
由於SpringBoot已經初始化了RequestMappingHandlerAdapter,因此不建議手動初始化覆蓋,建議採用方案2進行擴展。
https://docs.spring.io/spring/docs/4.3.24.RELEASE/spring-framework-reference/htmlsingle/#mvc-ann-webbindinginitializer
SpringMVC接收參數後處理(前端空參數轉爲null)
第一種:普通的參數
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.context.request.WebRequest;
import java.util.Locale;
/**
* 請求參數處理
*
* @author obiteaaron
* @since 2019/12/26
*/
@ControllerAdvice
public class WebMvcControllerAdvice {
@InitBinder
public void initBinder(WebDataBinder binder, WebRequest webRequest, Locale locale) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}
}
第二種:@RequestBody參數
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import java.io.IOException;
/**
* @author obiteaaron
* @since 2019/12/26
*/
@Configuration
public class JacksonConfiguration {
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.deserializerByType(String.class, new StringDeserializer() {
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String deserialize = super.deserialize(p, ctxt);
if (deserialize != null && deserialize.equals("")) {
return null;
}
return deserialize;
}
});
}
};
}
}
此處有坑:SpringMVC在默認情況下,會在org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#addDefaultHttpMessageConverters
加上new MappingJackson2HttpMessageConverter()
出來的對象,並不是HttpMessageConvertersAutoConfiguration
創建出來的對象,導致Jackson2ObjectMapperBuilderCustomizer
不生效,這是個大坑啊。
解決辦法:
第一種(推薦):通過org.springframework.web.servlet.config.annotation.WebMvcConfigurer#extendMessageConverters
擴展,剔除這個錯誤的,然後注入一個正確的。
或者直接通過org.springframework.web.servlet.config.annotation.WebMvcConfigurer#configureMessageConverters
注入正確的。
第二種:雖然new
的對象有問題,但是在Builder類中,設置了applicationContext,而org.springframework.http.converter.json.Jackson2ObjectMapperBuilder#configure
的最後一行,通過applicationContext設置了一個攔截器。這個攔截器是Jackson的攔截器,所以要自己實現,這裏不實現,有興趣可以自己看看。
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.removeIf(next -> next instanceof MappingJackson2HttpMessageConverter);
converters.add(mappingJackson2HttpMessageConverter);
}
}
重要的Spring類(自己去學習吧):
org.springframework.web.bind.support.WebBindingInitializer
org.springframework.web.bind.support.ConfigurableWebBindingInitializer#propertyEditorRegistrars
org.springframework.beans.PropertyEditorRegistrar
org.springframework.beans.propertyeditors.StringTrimmerEditor
org.springframework.format.support.DefaultFormattingConversionService
org.springframework.core.convert.support.GenericConversionService#converters
org.springframework.web.bind.annotation.InitBinder
org.springframework.web.bind.annotation.ControllerAdvice
參考:
https://chenzhihao.cc/2019/06/13/Springmvc%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0%E7%9A%84%E4%BC%98%E9%9B%85%E5%A4%84%E6%96%B9%E5%BC%8F/
https://blog.csdn.net/u012165930/article/details/78942938