Spring中多线程事务处理

SpringMVC中绑定复杂数据

SpringMVC中可以实现将前端传过来的数据封装好。在此之前一直都是对一个实体的封装,但在青芒项目里,遇到两个关于SpringMVC数据绑定的问题

  1. SpringMVC一个请求绑定多个不同实体
  2. SpringMVC绑定实体里复杂的数据结构

SpringMVC一个请求绑定多个不同实体

场景:

接口中要保存活动信息,活动报名表,活动展示,活动的问答,其中活动的问答传过来是一串数组,而活动报名表里有一些复杂的数据结构

接口里的实体

解决办法:

对于一串数组,平日里传的话,就直接传,然后就会绑定到参数里了,就如同下面一样

1
2
@PostMapping(value = "/publish)
public void test(List<String> testString) {}

但是在多实体的情况下这样就不管用了,多实体的话,SpringMVC不知道这是数组啊,所以要使用@InitBinder去绑定

这里使用@InitBinder主要就是用以区分前端传过来的数据,使用WebDataBinder.setFieldDefaultPrefix()设置前缀用以区分,这里要特别留意一下:@InitBinder后面跟着的是某个类的类名的驼峰命名,如:Activity,@InitBinder(“activity”);ActivityRegister,@InitBinder(“activityRegister”)等等,而在webDataBinder.setFieldDefaultPrefix()中的字符串参数则是自己定义的,前端传数据过来带上这个前缀就知道哪个是哪个了,如下图

SpringMVC绑定实体里复杂的数据结构

场景:

同上,上面还有几个问题没有解决,就是活动QA就是以一串数组传过来的嘛,然后上面解决了如何区分多个实体,但却没有解决如何封装这些数组,以及一些复杂的数据结构

解决办法:

SpringMVC在多实体的情况下,貌似不能直接以List去封装的:

1
2
3
// 貌似在SpringMVC里这样是不可以的,数据绑定不到qaList上
@PostMapping(value = "/publish)
public void test(Activity activity, List<ActivityQA> qaList, ActivityShow show) {}

这样不行,我们换个法子,用一个实体来封装这些数据结构,这个实体应该叫VO吧,用来封装前端传过来的数据

QAListVO

这里也有个注意的地方就是前端传的时候,如果不加任何别名的话,应该是这样的

QAList

前缀 + 属性名[index] + QA里的属性名

如上 前缀 -> “activityQA.”,而ActivityQAListModel里的List属性名 activityQAList,所以以 activityQA.activityQAList[index] 去封装数据,index为索引

这样就解决了SpringMVC在多实体情况下绑定实体数组

但是这里的实例是List,List倒是明白了,Java里面有List,Map等数据结构,那又怎么办?同样还是一样的招数,只不过传的时候形式有点变化。

如下ActivityRegister, ActivityRegisterFormList,ActivityRegisterForm所示

ActivityRegister:

ActivityRegister

ActivityRegisterFormList:

ActivityRegisterFormList

ActivityRegisterForm:

ActivityRegisterForm

可以看到ActivityRegister中Map包含了ActivityRegisterFormList,List里用ActivityRegisterForm做元素,所展示出来大概就如下面一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
form: {
person: {
formList: [
{
title: 姓名,
type: 0,
ifNecessary: true,
ifChoice: false,
choice: null
},
{...},
{...}
]
}
}

这时Map中有List,对于List的数据绑定,前面已经介绍过了,直接 formList[0].title = 姓名,formList[0].type = 0,formList[0].ifNecessary = true这样,那么Map又如何?

Map的话,由于其是key-value结构,而List是索引-value结构,那么这样对比一下,List中的索引相对于Map的key,应该是有共通之处,所以,数据绑定的时候,招数是一样的,形式不同而已

ActivityRegister

直接以指定的字符串作为内容,后面接着List的格式,代表value就是一个List,那么整理一下格式就可以概括为:

map[key].list[index].属性名

拓展

上面介绍了List,Map<String, List>的情况,那么如果是List<Map<String, List>>这样的呢

像List<Map<String, List>>这样的,同理

list[index].map[key].list[index]这样

注意一点!!!就是Map<String, Map<String, String>>或者Map<String, Map<String, List>>这样的,直接套用上面的方法是不行的,这时建议审视数据结构,重新规划一下,因为本人就是一开始使用Map<String, Map<String, List>>这样的,发现无论怎样都不能比较方便直接地转换过来,这时重新审查自己的数据结构,结合业务,然后洗个澡,就把这个问题给解决了,重新建立了数据模型,在不影响业务需求的情况下,更好地进行访问,也不用再恶心地使用什么json字段,设置application/json这样的请求类型,传入不好校验,极其不安全的参数。

总结

  • 在多实体数据绑定情况下,使用@InitBinder + webdataBinder.setFieldDefaultPerfix()设置前缀去区分
  • List数据结构在多实体数据绑定情况下,使用一个VO去包装这个List,前端传过来,在不加别名的情况下,按照List的属性名传
  • List,Map数据结构的组合,基本掌握 List的数据传输格式为 list[index],Map的数据传输格式为 map[key] 这两种基本就可以了,同时注意Map中Map数据结构本人暂时没有办法解决,若有晓得的,可以告知我一下

##

-------------本文结束感谢您的阅读-------------