空字符串转为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. spring使用之旅(一) ---- bean的装配

           基础配置 启用组件扫描配置                     Java类配置文件方式 package com.springapp.mvc.application;   import ...

  2. 【CSS3 transform属性和过渡属性详解】

    CSS3transform属性详解 transform字面上就是变形,改变的意思. 在CSS3中transform主要包括以下几种:旋转rotate.扭曲skew.缩放scale和移动translat ...

  3. BZOJ 1597: [Usaco2008 Mar]土地购买【斜率优化+凸包维护】

    1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4989  Solved: 1847[Submit] ...

  4. HDU--1212大数取模

    大数取模问题.题目传送门:HDU1212 #include <iostream> using namespace std; char a[1010]; int main() { int b ...

  5. 启动redis

    方法一:默认是前端启动       默认端口:6379 cd  /usr/local/redis/bin/redis-server 方法二:后端启动 方法二:后端启动 然后进入 指定配置文件 [roo ...

  6. JavaScript八张思维导图—编程风格

    JS基本概念 JS操作符 JS基本语句 JS数组用法 Date用法 JS字符串用法 JS编程风格 JS编程实践 不知不觉做前端已经五年多了,无论是从最初的jQuery还是现在火热的Angular,Vu ...

  7. 从零开始学习前端开发 — 9、标签嵌套规则及CSS常用样式覆盖

    1. 块级元素可以包含内联元素或某些块级元素,但内联元素却不能包含块级元素,它只能包含其它的内联元素: <div><h1></h1><p></p& ...

  8. WIN2016安装织梦没写入权限怎么办听语音

    配置好了WINSERVER2016环境,一切看起来都弄得差不多了,可是安装织梦的时候提示我没有写入权限,不能继续安装,于是我很郁闷,开始寻求解决办法. 工具/原料 WINSERVER2016 织梦5. ...

  9. 邓_thinkphp口试

    描述php框架开发 通过提供一个开发Web程序的基本架构,PHP开发框架把PHPWeb程序开发摆到了流水线上.换句话说,PHP开发框架有助于促进快速软件开发(RAD),这节约了你的时间,有助于创建更为 ...

  10. Asp.net mvc 中Action 方法的执行(二)

    [toc] 前面介绍了 Action 执行过程中的几个基本的组件,这里介绍 Action 方法的参数绑定. 数据来源 为 Action 方法提供参数绑定的原始数据来源于当前的 Http 请求,可能包含 ...