SpringMVC接收參數後處理(前端空參數轉爲null)

SpringBoot版本:2.1.6.RELEASE
SpringMVC版本:5.1.8.RELEASE

當遇到前端沒有填寫的表單字段被作爲空字符串傳到後端時,在業務邏輯中處理顯得有點蹩腳,那正常的解法應該是擴展Spring,畢竟Spring擴展性很強,這是基本思路。
注:這些解決問題的辦法都是解決由Spring進行綁定的操作,比如自動創建一個類,將參數綁定上去。你自己通過HttpServletRequest.getParamenter("key")是需要自己封裝處理的的。

解決辦法:

  1. 自己擴展實現一個ConfigurableWebBindingInitializer,註冊爲Bean,需要設置爲較高優先級(不建議使用,因爲SpringBoot中預留的口子不明顯)
  2. @InitBinder+@ControllerAdvice實現。@ControllerAdvice標註的類中的方法被@InitBinder標註後,所有Controller可用。(解決request.getParameter(“key”)的問題,如果是@RequestBody則無效)
  3. @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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章