SpringMVC接收参数后处理(前端空参数转为null)

11 篇文章 0 订阅
7 篇文章 0 订阅

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值