Git多人协作
每次项目都是使用的git,整理下多人协作时git的流程。以一个在Gitlab上的TestProject作为例子
首先创建远程库
在对应的Git代码管理平台上创建一个项目,比如Gitlab,就new出一个项目
久仰Jenkins大名,特前来做个Demo以此来学习Jenkins自动化部署
使用Jenkins + Git + Maven 在Ubuntu下自动化部署SpringBoot项目,将SpringBoot项目上传至Git的master分支上,然后Jenkins就将Git上的分支拉过来,使用Maven构建,并在服务器上运行
在官网上(https://jenkins.io/) 点击Download 之后,选择所要部署的服务器发行版,我的服务器用的阿里云(Ubuntu 16.0.4)所以选择 Ubuntu/Debian系列。进入之后按照官方提示操作
前面用自己的服务器搭了个Jenkins + Github + Maven部署SpringBoot项目,上面所有都在一台机子上完成。但是很快,由于工作室的需要,因此这种全部集成在一台机子上的部署是行不通的,因此考虑使用远程连接服务器部署
之前描述的是Jenkins + Github + Maven在一台机子上部署SpringBoot项目,也就是说Jenkins在A服务器上,Maven在A服务器上,从Github拉取的源码在A服务器上,打包好的Jar包也在A服务器上,这种是最基础的自动化部署,同时也是不用怎么进行网络传输的部署方式。但是你想,如果一个初创企业,服务器只够买几台云服务器,而一些云服务器空间不大,大概也就是一台机部署一个项目的这样子,那要是按照上面说的单机部署,服务器肯定吃不消,而且一个企业内部商业项目也不太可能放到Github上,一般企业都是搭建自己的Gitlab服务器的,所以从安全性,可扩展性,以及内存争用问题上看,应该选择 Jenkins + Gitlab + Maven 自动化远程部署SpringBoot项目
因为工作室原来的Gitlab挂了,服务器不再续费,所以重新部署Gitlab并且汉化
首先先看下官方文档,里面记录了一些主要步骤,但是由于环境因素,所以有些步骤不太适用
1 | sudo apt-get update |
安装Postfix以发送通知电子邮件
1 | sudo apt-get install -y postfix |
安装postfix过程中,选择“Internet Site”并按Enter键。使用服务器的外部DNS作为“邮件名称”,然后按Enter键。如果出现其他屏幕,请继续按Enter键接受默认值。(官网上的描述,照抄)
SpringMVC中可以实现将前端传过来的数据封装好。在此之前一直都是对一个实体的封装,但在青芒项目里,遇到两个关于SpringMVC数据绑定的问题
- SpringMVC一个请求绑定多个不同实体
- SpringMVC绑定实体里复杂的数据结构
场景:
接口中要保存活动信息,活动报名表,活动展示,活动的问答,其中活动的问答传过来是一串数组,而活动报名表里有一些复杂的数据结构
解决办法:
对于一串数组,平日里传的话,就直接传,然后就会绑定到参数里了,就如同下面一样
1 | @PostMapping(value = "/publish) |
但是在多实体的情况下这样就不管用了,多实体的话,SpringMVC不知道这是数组啊,所以要使用@InitBinder去绑定
这里使用@InitBinder主要就是用以区分前端传过来的数据,使用WebDataBinder.setFieldDefaultPrefix()设置前缀用以区分,这里要特别留意一下:@InitBinder后面跟着的是某个类的类名的驼峰命名,如:Activity,@InitBinder(“activity”);ActivityRegister,@InitBinder(“activityRegister”)等等,而在webDataBinder.setFieldDefaultPrefix()中的字符串参数则是自己定义的,前端传数据过来带上这个前缀就知道哪个是哪个了,如下图
场景:
同上,上面还有几个问题没有解决,就是活动QA就是以一串数组传过来的嘛,然后上面解决了如何区分多个实体,但却没有解决如何封装这些数组,以及一些复杂的数据结构
解决办法:
SpringMVC在多实体的情况下,貌似不能直接以List去封装的:
1 | // 貌似在SpringMVC里这样是不可以的,数据绑定不到qaList上 |
这样不行,我们换个法子,用一个实体来封装这些数据结构,这个实体应该叫VO吧,用来封装前端传过来的数据
这里也有个注意的地方就是前端传的时候,如果不加任何别名的话,应该是这样的
前缀 + 属性名[index] + QA里的属性名
如上 前缀 -> “activityQA.”,而ActivityQAListModel里的List属性名 activityQAList,所以以 activityQA.activityQAList[index] 去封装数据,index为索引
这样就解决了SpringMVC在多实体情况下绑定实体数组
但是这里的实例是List,List倒是明白了,Java里面有List,Map等数据结构,那又怎么办?同样还是一样的招数,只不过传的时候形式有点变化。
如下ActivityRegister, ActivityRegisterFormList,ActivityRegisterForm所示
ActivityRegister:
ActivityRegisterFormList:
ActivityRegisterForm:
可以看到ActivityRegister中Map包含了ActivityRegisterFormList,List里用ActivityRegisterForm做元素,所展示出来大概就如下面一样
1 | form: { |
这时Map中有List,对于List的数据绑定,前面已经介绍过了,直接 formList[0].title = 姓名,formList[0].type = 0,formList[0].ifNecessary = true这样,那么Map又如何?
Map的话,由于其是key-value结构,而List是索引-value结构,那么这样对比一下,List中的索引相对于Map的key,应该是有共通之处,所以,数据绑定的时候,招数是一样的,形式不同而已
直接以指定的字符串作为内容,后面接着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这样的请求类型,传入不好校验,极其不安全的参数。
##
在青芒第三次迭代时,一个活动模块需要同时处理多个实体的业务,而彼此业务间没有关联,但存在事务性,考虑再三,决定尝试使用多线程处理多个业务
在了解了Spring事务处理之后,使用 编程式事务处理 更为灵活,由于有多个线程,而每个线程对应一个数据库连接,所以在多线程环境中,事务不止一个,同理事务状态也不止一个,因此这里的解决办法就是 将所有线程的事务状态保存到一个同步集合(多线程环境下使用同步集合,保证线程安全),若某个线程出现错误,遍历所有线程的事务状态,循环回滚
看到一个比较有意思的东西–私有构造器捕获模式。
下面代码可以看到在testA处有个编译错误:Cannot reference ‘PrivateConstructor.testA’ before supertype constructor has been called。此处是说不能在超类构造器调用之前引用testA
尝试解释一下,由于PrivateConstructor这个类继承自Parent,然后在构造的时候,先从Parent构造起来,由于PrivateConstructor构造器指明调用父类的带参数构造器,调用Parent的一个带参数的构造器。但是因为在PrivateConstructor构造器中,调用了还没被初始化的testA,所以报出了编译错误。
Linux下配置ssr,对于刚从Window转过来的小白用户实在是折腾,还好是看了同事的博客,教小白如何傻瓜式操作ssr配置,才慢慢懂得。Linux的知识实在是太欠缺了,去拜读一下鸟哥先。
1 | wget http://www.texfox.com/ssr |
1 | sudo mv ssr /usr/local/bin |
1 | sudo chmod 766 /usr/local/bin/ssr |
1 | ssr install |
1 | ssr config |
这个操作会调起一个gedit的文本编辑器,将节点json信息配置到里面去就ok
1 | ssr start |
讲完服务端的配置,接下来就要说下客户端配置,例子将会在google上进行配置
首先设置情景模式为 proxy,如上图的第一个箭头,然后将 https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt这个url复制粘贴到规则列表地址上,这是被墙的url列表。当代理检测到你要访问里面的url时,认定你将要翻墙。最后点击立即更新情景模式
这里配置的是proxy项,代理服务器填127.0.0.1,代理端口是1080,当然代理端口看运营方给你的端口设置。
到这里基本配置是完了,接下来的可能因每个人的Linux发行版不同而有所差别,笔者用的是 稍微有点低级的deepin(小白用户专用),所以接下来配置跟主流Linux发行版不太一样。
其他Linux发行版中 /etc下是应该有rc.local文件的,直接在rc.local文件上配置就行了,但是deepin呢就比较奇葩,他在最新版本没有rc.local,因此得另找门路
不过,根据官网的wiki deepin自启动程序里面介绍到,直接在/etc下创建个rc.local文件,然后配上以下代码
1 | #!/bin/bash |
然后修改下文件权限 sudo chmod +x /etc/rc.local ,然后重启,就会发现可以了。
1 | sudo touch /usr/lib/systemd/system/rc-local.service |
1 | [Unit] |
1 | systemctl enable rc-local.service |
1 | sudo touch rc.local |
1 | #!/bin/bash |
1 | sudo chmod +x /etc/rc.local |
1 | systemctl enable rc-local.service |
由于在deepin下过渡的时间够长了,也基本适应了win转Linux了,所以打算考完试换下系统,特地记录一下一些必要的操作
1 | sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak |
1 | sudo gedit /etc/apt/sources.list |