天天看點

SpringMVC空字元串轉為null

空字元串轉為null

現在我遇到這樣一個需求,那就是我想要吧前端傳過來的值變為空,因為所謂前端的校驗,其實都不是校驗,如果前端傳給背景一個表單,可是表單未填入值,我們背景進行判斷的時候 既需要判斷null,同時需要判斷是否為

""

, 并且如果你不希望資料庫插入的是空字元串,而是

null

,那麼轉換和插入的就很麻煩

if (manager.getUsername().equals("") || manager.getUsername() == null) {
            throw new ErrorException("使用者名未填寫");
        }
        if (manager.getPassword().equals("") || manager.getPassword() == null) {
            throw new ErrorException("密碼未填寫");
        }
           

可是如果你在SpringMVC進行參數指派處理之前就能把

""

轉換為

null

,那麼你就隻需要進行如下判斷,并且插入資料庫的一直是空值

if (manager.getUsername() == null) {
            throw new ErrorException("使用者名未填寫");
        }
        if (manager.getPassword() == null) {
            throw new ErrorException("密碼未填寫");
        }
           

實作方式

  1. 可以使用過濾器/攔截器把空字元串設定成null(未嘗試)
  2. 注冊一個SpringMVC

    HandlerAdapter

    來進行處理

使用SpringMVC時,所有的請求都是最先經過DispatcherServlet的,然後由DispatcherServlet選擇合适的HandlerMapping和HandlerAdapter來處理請求,HandlerMapping的作用就是找到請求所對應的方法,而HandlerAdapter則來處理和請求相關的的各種事情。我們這裡要講的請求參數綁定也是HandlerAdapter來做的。

參數處理器

我們需要寫一個自定義的請求參數處理器,然後把這個處理器放到HandlerAdapter中,這樣我們的處理器就可以被拿來處理請求了。

public class EmptyStringToNullModelAttributeMethodProcessor extends ServletModelAttributeMethodProcessor implements ApplicationContextAware {

    ApplicationContext applicationContext;

    public EmptyStringToNullModelAttributeMethodProcessor(boolean annotationNotRequired) {
        super(annotationNotRequired);
    }

    @Override
    protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) {
        EmptyStringToNullRequestDataBinder toNullRequestDataBinderBinder = new EmptyStringToNullRequestDataBinder(binder.getTarget(), binder.getObjectName());
        RequestMappingHandlerAdapter requestMappingHandlerAdapter = applicationContext.getBean(RequestMappingHandlerAdapter.class);
        requestMappingHandlerAdapter.getWebBindingInitializer().initBinder(toNullRequestDataBinderBinder, request);
        toNullRequestDataBinderBinder.bind(request.getNativeRequest(ServletRequest.class));
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

           

DataBinder

繼承自

ExtendedServletRequestDataBinder

,主要用來自定義資料綁定處理

public class EmptyStringToNullRequestDataBinder extends ExtendedServletRequestDataBinder {
    public EmptyStringToNullRequestDataBinder(Object target, String objectName) {
        super(target, objectName);
    }

    protected void addBindValues(MutablePropertyValues mpvs, ServletRequest request) {
        super.addBindValues(mpvs, request);
        for (PropertyValue propertyValue : mpvs.getPropertyValueList()) {
            if (propertyValue.getValue().equals(""))
                propertyValue.setConvertedValue(null);
        }
    }
}
           

注冊器

話要從HandlerAdapter裡系統自帶的處理器說起。我這邊系統預設帶了24個處理器,其中有兩個ServletModelAttributeMethodProcessor,也就是我們自定義處理器繼承的系統處理器。SpringMVC處理請求參數是輪詢每一個處理器,看是否支援,也就是supportsParameter方法, 如果傳回true,就交給你出來,并不會問下面的處理器。這就導緻了如果我們簡單的把我們的自定義處理器加到HandlerAdapter的Resolver列中是不行的,需要加到第一個去。
public class EmptyStringToNullProcessorRegistry implements ApplicationContextAware, BeanFactoryPostProcessor {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        RequestMappingHandlerAdapter requestMappingHandlerAdapter = applicationContext.getBean(RequestMappingHandlerAdapter.class);

        List<HandlerMethodArgumentResolver> resolvers = requestMappingHandlerAdapter.getArgumentResolvers();


        List<HandlerMethodArgumentResolver> newResolvers = new ArrayList<HandlerMethodArgumentResolver>();

        for (HandlerMethodArgumentResolver resolver : resolvers) {
            newResolvers.add(resolver);
        }
        EmptyStringToNullModelAttributeMethodProcessor processor = new EmptyStringToNullModelAttributeMethodProcessor(true);
        processor.setApplicationContext(applicationContext);
        newResolvers.add(0, processor);
        requestMappingHandlerAdapter.setArgumentResolvers(Collections.unmodifiableList(newResolvers));
    }
}
           

XML配置

<mvc:annotation-driven>
        <mvc:argument-resolvers>
            <bean class="studio.geek.databind.EmptyStringToNullModelAttributeMethodProcessor">
                <constructor-arg name="annotationNotRequired" value="true"/>
            </bean>
        </mvc:argument-resolvers>
    </mvc:annotation-driven>
           

最後就可以完成将空字元串轉為

null

參考文檔

  1. SpringMVC對象綁定時自定義名稱對應關系
  2. SpringMVC源碼分析和一些常用最佳實踐