空字符串转为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. Erlang内存吃紧之解决思路

    首先使用erlang:memory()确定是哪个部分内存吃紧,根据输出的内容,比对内存占用大小,有针对性地进行分析.在erlang系统里内存的单位为word,通过erlang:system_info( ...

  2. Django----->一周后的重温

    Django   一 什么是web框架? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来 ...

  3. Windows下Java环境变量配置

    新建: JAVA_HOMEC:\Program Files\Java\jdk1.8.0_25 新建或添加到开头: PATH %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin; C ...

  4. 给“file”类型的input框赋值的问题

    开发"新闻编辑"功能时,会遇到给"file"类型的input框赋值的问题,用来展示之前上传的文件,但由于file类型的input框受到安全限制,所以不能被赋值, ...

  5. Video Target Tracking Based on Online Learning—TLD多目标跟踪算法

    TLD算法回顾 TLD(Tracking-Learning-Detection)是英国萨里大学的一个捷克籍博士生Zdenek Kalal在其攻读博士学位期间提出的一种新的单目标长时间(long ter ...

  6. c++(递归和堆栈)

    看过我前面博客的朋友都清楚,函数调用主要依靠ebp和esp的堆栈互动来实现的.那么递归呢,最主要的特色就是函数自己调用自己.如果一个函数调用的是自己本身,那么这个函数就是递归函数. 我们可以看一下普通 ...

  7. CLR 简介

    (一)CLR介绍 CLR是一个可以由多编程语言使用的运行时,CLR的核心功能:内存管理,程序集加载,安全性,异常处理,线程同步等等.可以被很多属于微软系列的开发语言使用. 事实上,在运行时,CLR根本 ...

  8. 关于layer的坑

    真是自己给自己挖坑,坑死人不偿命啊. 在用layui开发时,遇到这种情况,点击按钮出现一个弹出层,然而我不是用button按钮去实现的,而是用a标签做的,本来a标签也是可以实现的,在这里我无形中给自己 ...

  9. 织梦DedeCms获取当前页面URL地址的调用方法

    织梦内容页如何调用当前页面url?相信很多对织梦感兴趣的朋友都会去考虑这个问题:在文章内容中加入本文链接,除了 保护自己版权外还可以增加网站的外链收录.网上这方面的帖子一搜一大堆,但多数都只能调用相对 ...

  10. VisualSVN Server启动错误(0x8007042a)

    SVN Server启动错误(0x8007042a)   原因是SVN Server端口被占用 打开VisualSVN Server, 菜单->操作->Properties->Net ...