空字符串转为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源码分析和一些常用最佳实践

SpringMVC空字符串转为null的更多相关文章

  1. Java空字符串与null的区别和判断字符串是否为空的方法

    Java空字符串与null的区别: 1.类型null表示的是一个对象的值,而并不是一个字符串.例如声明一个对象的引用,String a = null ;""表示的是一个空字符串,也 ...

  2. Oracle坑之-空字符串与NULL

    空字符串与NULL 首先有如下代码 SELECT * FROM Pdc_DataDomain DD INNER JOIN Pdc_DD_Table DDT ON DD.DataDomainID = D ...

  3. Java进阶(二十一)java 空字符串与null区别

    java 空字符串与null区别 1.类型 null表示的是一个对象的值,而并不是一个字符串.例如声明一个对象的引用,String a = null ; ""表示的是一个空字符串, ...

  4. Access空字符串和Null值

    什么是空字符串和Null值: Microsoft Access可以区分两种类型的空值.因为在某些情况下,字段为空,可能是因为信息目前无法获得,或者字段不适用于某一特定的记录.例如,表中有一个“电话号码 ...

  5. postgresql与Oracle:空字符串与null

    空字符串:两个单引号,中间无空格等任何内容 在postgresql中,空字符串与null是不同的:而oracle中,空字符串与null等同.测试如下: postgresql中: postgres=# ...

  6. 3-java中String值为空字符串与null的判断方法

    java中String值为空字符串与null的判断方法 2018年01月21日 14:53:45 阅读数:1189 Java空字符串与null的区别 1.类型 null表示的是一个对象的值,而不是一个 ...

  7. 解决CsvWriter:中文乱码、末尾行多一行空格(/r)、非第一列空字符串""显示null问题

    一:主要内容 解决CsvWriter存csv,csv文件打开后中文乱码问题 解决CsvWriter存csv,csv文件最后一行总是多一行空行的问题 解决CsvWriter存csv,csv文件不是第一列 ...

  8. 空字符串(“”)和null和空格字符串(" ")的区别

    1.类型 null表示的是一个对象的值,而并不是一个字符串.例如声明一个对象的引用,String a = null ;""表示的是一个空字符串,也就是说它的长度为0,但它是一个字符 ...

  9. vue 之 后端返回空字符串用 null 和 “”以及 undefind 判断不到的问题

    原文: <!-- <span v-if="scope.row.buyer_credit_score != '' || scope.row.buyer_credit_score ! ...

随机推荐

  1. Android 服务_笔记

    Service服务 服务(Service)是Android中的四大组件之一,适用于开发无界面.长时间运行的应用功能,服务是在后台运行,服务的创建与Activity类似,只需要继承Service和在An ...

  2. Uva - 12050 Palindrome Numbers【数论】

    题目链接:uva 12050 - Palindrome Numbers 题意:求第n个回文串 思路:首先可以知道的是长度为k的回文串个数有9*10^(k-1),那么依次计算,得出n是长度为多少的串,然 ...

  3. Vijos P1448 校门外的树【多解,线段树,树状数组,括号序列法+暴力优化】

    校门外的树 描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作: K=1,K= ...

  4. Vijos P1497 立体图【模拟】

    立体图 描述 小渊是个聪明的孩子,他经常会给周围的小朋友们讲些自己认为有趣的内容.最近,他准备给小朋友讲解立体图,请你帮他画出立体图. 小渊有一块面积为m*n的矩形区域,上面有m*n个边长为1的格子, ...

  5. Saving James Bond(dijk)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1245 Saving James Bond Time Limit: 6000/3000 MS (Java ...

  6. ASP.NET CORE MVC 2.0 项目中引用第三方DLL报错的解决办法 - InvalidOperationException: Cannot find compilation library location for package

    目前在学习ASP.NET CORE MVC中,今天看到微软在ASP.NET CORE MVC 2.0中又恢复了允许开发人员引用第三方DLL程序集的功能,感到甚是高兴!于是我急忙写了个Demo想试试,我 ...

  7. UE4 TSubclassOf VS Native Pointer

    最近看到了TSubclassOf ,所以想要弄清楚跟一般指针的区别~ NativePointer    VS     UClass*      VS     TSubclassOf AActor* p ...

  8. 我的flashfxp左右界面怎么变成这样了?

    如下图,flashfxp不是说左边是本地的文件夹,右边是服务器上的文件夹的吗?我不懂刚刚怎么搞了一下,变成两边都是服务器上的文件夹了,哪位大神,指点下,谢谢!!! 921050734 | 浏览 168 ...

  9. client和nginx简易交互过程

    # client和nginx简易交互过程- step1:client发起http请求- step2:dns服务器解析域名得到主机ip- step3:默认端口为80,通过ip+port建立tcp/ip链 ...

  10. DEDE中 field:rel 是什么意思,起一个什么样的作用效果

    DEDE中 field:rel 是什么意思,起一个什么样的作用效果 这是一段调用导航栏目的代码 {dede:channel type='top' row='10' } [field:typename/ ...