主要流程思路【粗略讲处理思路,若遇到具体问题可留言交流】:

1.android的打包命令

2.ios的打包命令

3.jenkins的参数化构建

4.七牛的上传命令等

5.处理ipa的下载操作及ipa过期的监控

6.下载页面h5页面(css,js,html)

7.打包等数据存入数据库

8.分层封装

代码目录结构:

一、pkg_common:一些基础的操作都封装在这个目录

(1)安卓的打包命令、apk处理

(2)ios的打包命令

(3)命令运行封装

(4)ipa的监控

(5)jengkins的参数处理

(6)通知处理

(7)七牛上传处理

(8)二维码处理

比如文件处理:

拷贝文件,获取文件信息(获取包的名字,版本信息,环境信息,图标信息等)、生成下载html页面,创建下载plist文件等等

android的打包上传下载比较简单,重点讲一下ios的打包:

1. ios打包分为三步:清理,编译,导出ipa

(1)清理项目:xcodebuild clean -workspace %s -scheme %s -configuration %s

(2)编译:xcodebuild archive -workspace %s -scheme %s -configuration %s -archivePath %s

(3)导出包:xcodebuild -exportArchive -archivePath %s -exportOptionsPlist %s -exportPath %s

贴一个导出包的代码:

 1 from datetime import datetime
2 from pkg_common.cmd import common_run_cmd as cmd
3 from pkg_common.handle_file import find_file as fd
4
5
6 def export_ipa(xch, plist, ext_path, log, wp):
7
8 """
9 :param xch: xcarchive文件及路径
10 :param plist: ExportOptions.plist 文件及路径
11 :param ext_path: 导出ipa包的路径
12 :param log: 日志文件
13 :param wp: 执行cmd的目录
14 :return:
15 """
16
17 """
18 xcodebuild -exportArchive -archivePath /Users/Work/iOS/exrmle/AppStore/20190929171231/covermedia.xcarchive -exportOptionsPlist /Users/Work/iO
19 S/exrmle/AppStore/ExportOptions.plist -exportPath /Users/Work/iOS/exrmle/AppStore/20190929171231/ > /Users/Work/iOS/exrmle/log/03export.log
20 """
21 cmd_export = "xcodebuild -exportArchive -archivePath %s -exportOptionsPlist %s -allowProvisioningUpdates -exportPath %s > %s" % (xch, plist, ext_path, log)
22 print(datetime.now(), '** Export Begin **')
23 cmd.run_cmd(cmd_export, wp).read()
24 with open(log, 'r', encoding='utf-8') as f:
25 for i in f.readlines():
26 if 'EXPORT SUCCEEDED' in i:
27 print(datetime.now(), '** Export Succeed **')
28 break
29 else:
30 error_list = fd.find_log_error(log)
31 for el in error_list:
32 print(el)
33 raise AssertionError('** Export Error **')
ExportOptions.plist文件内容:
分methon的不同有4中类型:ad-hoc、app-store、development、enterprise。
不知道怎么构造的化,用xcode直接导出包后就生成了,compileBitcode最好设置为false,不然容易出错不说,导出时候还很慢。
 1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 <plist version="1.0">
4 <dict>
5 <key>compileBitcode</key>
6 <false/>
7 <key>method</key>
8 <string>ad-hoc</string>
9 <key>signingStyle</key>
10 <string>automatic</string>
11 <key>stripSwiftSymbols</key>
12 <true/>
13 <key>teamID</key>
14 <string>SWM****5PP</string>
15 <key>thinning</key>
16 <string>&lt;none&gt;</string>
17 </dict>
18 </plist>

包导出后,可以上传到第三方如蒲公英、fir下载,最好还是自己搭建下载页面,如果有七牛云的话,更简单,注意:ipa下载需要是https的。

ipa不像apk一样直接上传后获取下载地址就可下载,需要生成下载plist文件才可以下载到ipa的包。

下载plist文件样式:

<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<!-- ipa下载地址 -->
<string>https://pkgcdn.***r.cn/pkg/cover/ipa/rm_cg_iOS/7.0.0/***.ipa</string>
</dict>
<dict>
<key>kind</key>
<!-- 512 x 512 像素的 PNG 图像 -->
<string>full-size-image</string>
<key>needs-shine</key>
<false/>
<key>url</key>
<string> </string>
</dict>
<dict>
<key>kind</key>
<!-- 57 x 57 像素的 PNG 图像,在下载和安装过程中显示 -->
<string>display-image</string>
<key>needs-shine</key>
<false/>
<key>url</key>
<string> </string>
</dict>
</array>
<key>metadata</key>
<dict>
<!-- bundle ID -->
<key>bundle-identifier</key>
<string>com.C***anCha</string>
<!-- APP 版本号 -->
<key>bundle-version</key>
<string>7.0.0</string>
<key>kind</key>
<string>software</string>
<key>subtitle</key>
<string>7.0.0</string>
<!--下载和安装过程中显示的应用的名称 -->
<key>title</key>
<string>rm_cg_iOS</string>
</dict>
</dict>
</array>
</dict>
</plist>

需要维护ipa下载地址、bundle ID、版本信息等即可

然后把这个plist文件上传的服务器,下载地址生成:

“itms-services://?action=download-manifest&url=”加上plist的下载地址,如:

itms-services://?action=download-manifest&url=https://pk**n.thecover.cn/pkg/cover/plist/rm_cg_iOS/7.0.0/rm**7.plist

好了,iOS的打包全流程就这样~搞明白了还是很简单的。

当然,ipa到此还没有结束,ipa还需要上传到苹果市场,也可以通过命令解决。

(1)上传appstore验证:xcrun altool --validate-app -f %s -t ios --apiKey %s --apiIssuer %s --verbose

(2)上传appstore:xcrun altool --upload-app -f %s -t ios --apiKey %s --apiIssuer %s --verbose

这两个命令前提是需要到app store connect 用户-密钥去配置:

apiKey:密钥ID

apiIssuer:issuer ID

配具体步骤:

登录iTunesConnect --->用户与访问--->密钥,至此,生成相应身份的密钥,再将私钥下载下来

下载后需要放到一个固定目录下,'./private_keys'或者'~/private_keys' 或者'~/.private_keys'

或者'~/.appstoreconnect/private_keys'目录下

到此,ipa的包才算处理完成

与iOS相比,Android的打包就简单得多:

1.清理项目:./gradlew clean

2.编译:./gradlew assemble%s%s

3上传:普通上传,不需特殊处理

4.下载:上传后得到的下载地址即可

二、pkg_controller

(1)android的打包流程

(2)ios的打包流程

贴一个ios的打包流程,当然,还可以进一步封装,后续再优化优化。

  1 # coding = utf-8
2 # ***iOS打包
3
4
5 import sys
6 sys.path.append('..')
7 from datetime import datetime
8 from PIL import Image
9 from pkg_dao import deal_sql_data as ds
10 from pkg_common.qiniu import common_qiniu as qn
11 from pkg_common.notice import common_notice as notice
12 from pkg_common.qr_code import common_qr_code as qr_code
13 from pkg_common.jenkins import get_jenkins_parameter as get_jenkins
14 from pkg_common.ios import ios_modify_file as mf
15 from pkg_common.ios import ios_build_ipa as build
16 from pkg_common.ios import ios_export_ipa as export
17 from pkg_common.ios import ios_clean_workspace as clean
18 from pkg_common.ios import ios_pod_update as pod
19 from pkg_common.handle_file import zntopy as pin
20 from pkg_common.handle_file import deal_file as df
21 from pkg_common.handle_file import find_file as find
22 from pkg_common.handle_file import common_pkg_info as pkg
23 from pkg_common.handle_file import common_upload as upload
24 from pkg_common.handle_file import create_plist as ipa_plist
25 from pkg_common.ipa_monitor import copy_ipa_monitor as monnitor
26 from pkg_common.handle_file import create_download_html as down_html
27
28
29 # 需要重jenkins获取的参数
30 jks = [
31 'WORKSPACE', # jenkins工作路径
32 'build_environment', # 打包环境 test/product
33 'build_configuration', # 打包模式 Release/Debug
34 'export_environment', # 导出包的模式AdHoc/AppStore/Development/Enterprise
35 'upload_app_store', # 上传app store
36 'BUILD_NUMBER', # 打包次数
37 'is_direct_export' # 是否跳过编译直接导出
38 ]
39
40 dic_jks = get_jenkins.get_jenkins(jks)
41 wk = dic_jks['WORKSPACE']
42 be = dic_jks['build_environment']
43 ee = dic_jks['export_environment']
44 ua = dic_jks['upload_app_store']
45 cfg = dic_jks['build_configuration']
46 ie = dic_jks['is_direct_export']
47 bid = dic_jks['BUILD_NUMBER']
48
49
50 # wk = "/Users/drew/.jenkins/workspace/iOS**"
51 # be = 'product'
52 # ee = 'appstore'
53 # ua = 'T'
54 # cfg = 'Release'
55 # ie = 'T'
56 # bid = '115'
57
58
59 class AppPackaging:
60
61 """
62 iOS打包类
63 """
64
65 def __init__(self, ex_path, con_fig, key_word):
66
67 """
68 变量自定义方法
69 :param ex_path: 输出输入的目录
70 """
71
72 # 日志目录
73 self.lc = ex_path + 'log/01_clean.log'
74 self.lp = ex_path + 'log/02_uppod.log'
75 self.lb = ex_path + 'log/03_build.log'
76 self.le = ex_path + 'log/04_export.log'
77 self.lv = ex_path + 'log/05_validate.log'
78 self.lu = ex_path + 'log/06_upstore.log'
79 self.lx = ex_path + 'log/07_xcarchive.log'
80
81 # 输出文件子目录【存放.plist文件和每次编译后的文件】
82 ex_c = ''
83 if ee.upper() == 'ADHOC':
84 ex_c = ex_path + 'AdHoc/'
85 if ee.upper() == 'APPSTORE':
86 ex_c = ex_path + 'AppStore/'
87 if ee.upper() == 'DEVELOPMENT':
88 ex_c = ex_path + 'Development/'
89 if ee.upper() == 'ENTERPRISE':
90 ex_c = ex_path + 'Enterprise/'
91
92 # 输出孙目录【存放.xcarchive,ipa文件】
93 self.ex_g = ex_c + datetime.now().strftime('%Y%m%d%H%M%S') + '/'
94 # plist文件及路径
95 self.plist = ex_c + 'ExportOptions.plist'
96
97 # 查找当前目录下需要修改环境的配置文件
98 self.f, self.f_p = find.find_file(con_fig, wk)
99 # 定位关键词:指定关键词以定位修改文件的地方
100 self.key_word = key_word
101 # workspace名称
102 self.ws = find.find_file('*.xcworkspace', wk)[0][0]
103
104 def ios_pra(self):
105 """
106 定义iOS打包参数
107 :return:
108 """
109
110 # workspace文件
111 wsn = self.ws + '.xcworkspace'
112 # scheme名称
113 schn = self.ws
114 # 编译后生成的xcarchive文件
115 xch = self.ex_g + self.ws + '.xcarchive'
116 # 需要上传的ipa文件
117 ipa_path = self.ex_g + self.ws + '.ipa'
118 return wsn, schn, xch, ipa_path
119
120 def packaging(self, dic, pod_sign=0, copy_sign=0):
121 """
122
123 :param dic:
124 :param pod_sign:
125 :param copy_sign:
126 :return:
127 """
128
129 desc = ''
130 push_file = ''
131 if be.upper() == 'TEST':
132 desc = '内网测试环境'
133 push_file = wk + dic['str_test']
134 if be.upper() == 'PRODUCT':
135 desc = '外网正式环境'
136 push_file = wk + dic['str_product']
137 if ee.upper() == 'APPSTORE':
138 desc = '外部发布上线【非安装版本】'
139 push_file = wk + dic['str_product']
140 push_file_to = wk + dic['str_to']
141
142 if ie == "F":
143 # 删除xcode缓存文件
144 clean.del_file(self.ws + '*')
145 # 清理项目
146 clean.clean_xcworkspace(dic['wsn'], dic['schn'], cfg, self.lc, wk)
147 # 修改配置文件
148 mf.modify_file(be, self.key_word, self.f_p[0])
149 # 配置阿里推送文件目录
150 if dic['push_sign'] == 1:
151 # 拷贝配置
152 mf.copy_file(push_file, push_file_to)
153 if pod_sign == 1:
154 pod.update_pod(self.lp, wk)
155 # 编译
156 build.build_ipa(dic['wsn'], dic['schn'], cfg, dic['xch'], self.lb, wk)
157 # 编译成功后把.xcarchive文件路径写入log文件
158 df.write_file(self.lx, dic['xch'])
159 # 导出ipa
160 export.export_ipa(dic['xch'], self.plist, self.ex_g, self.le, wk)
161 else:
162 # 读取上次编译的.xcarchive文件目录
163 xch = df.read_file(self.lx)
164 # 导出ipa
165 export.export_ipa(xch, self.plist, self.ex_g, self.le, wk)
166
167 # --------------------------------参数定义-----------------------------
168
169 # ipa名称
170 ipa_name = self.ws + bid + '.ipa'
171 # plist 名称
172 plist_name = dic['project_name'] + bid + '.plist'
173 # plist文件路径
174 file_plist_path = dic['path_plist'] + plist_name
175 # icon 名称
176 img_name = dic['project_name'] + bid + 'ios_icon.png'
177 # 当前包二维码名称
178 qr_name = dic['project_name'] + bid + 'ios'
179 # 当前包二维码上传七牛key名称
180 qn_qr_name = qr_name + '.png'
181 # --------------------------------参数定义-----------------------------
182
183 # -------------------------上传七牛生成二维码及下载页面--------------------
184
185 # 获取APP版本等信息
186 app_image, app_bundle_id, app_version, app_name = pkg.get_ipa_info(dic['app_icon'], wk)
187
188 # --------------------------------参数定义-----------------------------
189 # 通用下载html名称
190 html_name = pin.zn_to_py(app_name) + "_gdh.html"
191 # html文件路径+
192 file_html_path = dic['path_html'] + html_name
193 adg = pin.zn_to_py(app_name) + bid + "ios_adg.html"
194 app_dg_html_path = dic['path_html'] + adg
195 # 通用html生成二维码名称
196 qr_name_html = dic['project_name'] + '_html' + bid + 'ios'
197 # 通用html二维码上传七牛key名称
198 qn_qr_name_html = qr_name_html + '.png'
199 # --------------------------------参数定义-----------------------------
200 # 上传icon图标
201 img_key, img_download_url = qn.qiniu_upload(app_image, dic['project_name'], app_version, img_name, 'img')
202 # 上传ipa文件
203 ipa_key, ipa_download_url = qn.qiniu_upload(dic['ipa_path'], dic['project_name'], app_version, ipa_name, 'ipa')
204 # 生成plist文件
205 ipa_plist.create_plist(ipa_download_url, app_bundle_id, app_version, dic['project_name'], file_plist_path)
206 # 上传plist
207 plist_key, plist_download_url = qn.qiniu_upload(file_plist_path, dic['project_name'], app_version, plist_name, 'plist')
208 # 生成ipa下载地址
209 ios_download_path = 'itms-services://?action=download-manifest&url=%s' % plist_download_url
210
211 # 查询数据库
212 sql_where = {
213 'app_name': app_name,
214 'app_type': 'iOS'
215 }
216 sql1, sql2, sql_a_q, sql_a_o, sql_i_t, sql_i_p = ds.rs(sql_where)
217 app_related = ds.read_sql(sql1)
218 pkg_path = ds.read_sql(sql2)
219 if len(app_related) == 0:
220 app_related = '0'
221 else:
222 app_related = app_related[0][0]
223 if len(pkg_path) == 0:
224 pkg_path = ''
225 else:
226 pkg_path = pkg_path[0][0]
227
228 saq = ds.read_sql(sql_a_q)
229 sao = ds.read_sql(sql_a_o)
230 sit = ds.read_sql(sql_i_t)
231 sip = ds.read_sql(sql_i_p)
232 saq_html = down_html.create_table(saq)
233 sao_html = down_html.create_table(sao)
234 sit_html = down_html.create_table(sit)
235 sip_html = down_html.create_table(sip)
236
237 adg_img = Image.open(app_image)
238 adg_img = adg_img.resize((120, 120), Image.ANTIALIAS)
239 qr_adg_name = pin.zn_to_py(app_name) + bid + 'ios.png'
240 save_file = dic['path_qr_code'] + qr_adg_name
241 adg_img.save(save_file, quality=100)
242 qr_adg_key, qr_adg_download_url = qn.qiniu_upload(save_file, dic['project_name'], app_version, qr_adg_name, 'img')
243 app_dg = {
244 'type': 'ios',
245 'cfg': cfg,
246 'app_version': app_version,
247 'bid': bid,
248 'desc': desc,
249 'dg_url': ios_download_path,
250 'app_dg_html_path': app_dg_html_path,
251 'app_name': app_name,
252 'icon_url': qr_adg_download_url
253 }
254 # 生成app单次下载html
255 down_html.create_html_app_dg(app_dg)
256 # 上传html
257 a_key, adg_url = qn.qiniu_upload(app_dg_html_path, dic['project_name'], app_version, adg, 'html')
258 # 生成二维码
259 qr_save_img = qr_code.create_qr_code(adg_url, app_image, qr_name, dic['path_qr_code'])
260 # 上传二维码图片
261 qr_code_key, qr_code_download_url = qn.qiniu_upload(qr_save_img, dic['project_name'], app_version, qn_qr_name, 'img')
262 # 替换https为http(钉钉不支持https)
263 qr_code_download_url = qr_code_download_url.replace('https', 'http')
264
265 qr_dic = {
266 'qr_code_download_url': qr_code_download_url,
267 'ipa_download_url': ios_download_path,
268 'apk_download_url': pkg_path,
269 'file_html_path': file_html_path,
270 'app_name': app_name,
271 'app_version': app_version,
272 'bid': bid,
273 'v_code': '0',
274 'type': 'iOS',
275 'cfg': cfg,
276 'desc': desc,
277 'saq_html': saq_html,
278 'sao_html': sao_html,
279 'sit_html': sit_html,
280 'sip_html': sip_html
281 }
282
283 # 生成通用下载html
284 down_html.create_html(qr_dic)
285 # 上传html
286 html_code_key, html_code_download_url = qn.qiniu_upload(file_html_path, dic['project_name'], app_version, html_name, 'html', 1)
287 # 通用html生成二维码图片
288 save_html_img = qr_code.create_qr_code(html_code_download_url, app_image, qr_name_html, dic['path_qr_code'])
289 # 上传二维码图片
290 qr_code_key_html, qr_code_download_url_html = qn.qiniu_upload(save_html_img, dic['project_name'], app_version, qn_qr_name_html, 'img')
291 qr_code_download_url_html = qr_code_download_url_html.replace('https', 'http')
292
293 # ------------------------上传七牛生成二维码及下载页面-----------------------
294
295 # 生成钉钉数据
296 app_info = {
297 'buildName': app_name,
298 'buildVersion': app_version,
299 'buildBuildVersion': bid,
300 'buildUpdated': datetime.now(),
301 'buildUpdateDescription': desc,
302 'buildShortcutUrl': html_code_download_url,
303 'buildQRCodeURL': qr_code_download_url_html
304 }
305
306 # 通知钉钉
307 notice.ding_talk(app_info, 'iOS', cfg)
308
309 # 插入数据库
310 sql_dic = {
311 'app_name': app_name,
312 'app_type': 'iOS',
313 'bundle_id': app_bundle_id,
314 'build_num': bid,
315 'version_id': 0,
316 'version': app_version,
317 'icon_path': img_download_url,
318 'qr_path': qr_code_download_url,
319 'pkg_path': ios_download_path,
320 'build_env': be,
321 'build_type': cfg,
322 'export_env': ee,
323 'app_related': app_related,
324 'html_download1': html_code_download_url,
325 'html_download2': adg_url
326 }
327 ds.write_sql(ds.ws(sql_dic))
328 ds.close_mysql()
329
330 # 上传AppStore
331 if ua == 'T':
332 # 验证
333 upload.up_validate(dic['ipa_path'], dic['ios_key'], dic['ios_issuer'], self.lv)
334 # 上传
335 upload.up_app_store(dic['ipa_path'], dic['ios_key'], dic['ios_issuer'], self.lu)
336
337 if copy_sign == 1:
338 # 拷贝ipa文件
339 monnitor.copy_ipa(dic['ipa_path'], app_name)

流程根据自己需要处理,这里的代码涉及数据库交互,数据相关交互还可以进一步封装处理,这样代码可读性更好一点。

三、pkg_dao

主要处理数据交互与数据库配置信息等

不详细描述

四、pkg_view

android打包实现页面

ios打包实现页面

五、resource

资源模块

(1)配置文件

(2)css文件

(3)html文件

(4)plist文件

(5)其他

六、jenkins的配置

主要用的是自由模式的参数化构建

jenkins再加上邮件监控,打包失败自动发布邮件,网上有各种邮件模版:

七、打包成功后通知钉钉

网上有很多例子,这不讲了

败邮件通知:

效果:

(1)钉钉通知:

(2)下载页面

(3)分类下载页面:

包管理平台:

Android、iOS、jenkins全自动化打包的更多相关文章

  1. iOS使用fastlane自动化打包到fir(最全最详细流程)

    # iOS使用fastlane自动化打包到fir(最全最详细流程)1. **首先确认是否安装了ruby,终端查看下ruby版本**> ruby -v终端输出:ruby 2.4.1p111 (20 ...

  2. iOS如何实现自动化打包

    iOS如何实现自动化打包 前言 在我们的日常开发工作中,避免不了会出现这样的场景:需求迭代开发完成之后,需要提供ipa包给QA同学进行测试,一般会执行如下流程:1.执行Git Pull命令,拉最新的代 ...

  3. ios实现fastlane自动化打包

    终于抽出时间来学习自动化打包了,app在测试阶段一天总会经历好几次的打包,每次打包真是身心疲惫,刚打完的包说不定就被测试妹子反应还要微调什么地方,我就真的有气没法出,打一次包怎么也得浪费十几分钟,还不 ...

  4. 【最新】Android使用jenkins全自动构建打包-Windows版本(Android,Jenkins,360加固,Email,QRcode,参数构建,蒲公英)

    Android打包喝咖啡系列(Windows版) 这篇博客主要讲述的内容: 1.windows上部署Jenkins https://jenkins.io 2.基于SVN或Git https://git ...

  5. Jenkins实现Android自动化打包

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/77102359 本文出自[赵彦军的博客] 1.Tomcat 进入 https://t ...

  6. iOS Jenkins 自动化打包构建

    前言 在测试app项目过程中,通常都是需要开发打测试包给到测试,但是无论是iOS还是Android的打包过程都是相当漫长的,频繁的回归测试需要频繁的打包,对于开发同学影响还是蛮大的.因此在这种情况下, ...

  7. Android Jenkins 自动化打包构建

    前言 在测试app项目过程中,通常都是需要开发打测试包给到测试,但是无论是iOS还是Android的打包过程都是相当漫长的,频繁的回归测试需要频繁的打包,对于开发同学影响还是蛮大的.因此在这种情况下, ...

  8. Mac Jenkins+fastlane 简单几步实现iOS自动化打包发布 + jenkins节点设置

    最近在使用jenkins 实现ios自动化打包发布蒲公英过程实践遇到了一些坑,特意记录下来方便有需要的人. 进入正题: 一.安装Jenkins 1.Mac上安装Jenkins 遇到到坑 因为 Jenk ...

  9. Jenkins+ Xcode+ 蒲公英 实现IOS自动化打包和分发

    Jenkins+ Xcode+ 蒲公英 实现IOS自动化打包和分发 直接入正题: Screen Shot 2015-09-18 at 16.56.20.png Mac上安装Jekins jekins下 ...

  10. Jenkins 持续集成实现 Android 自动化打包

    打 debug 包流程: git pull 分支最新代码 Android Studio:Build - Generate Signed APK 从 IDE 里可以看到,实际上该操作是执行了 assem ...

随机推荐

  1. mybatis缓存源码解析

    为什么使用缓存 减少和数据库交互次数,提高执行效率 mybatis的缓存 mybatis一级缓存,也就是局部的sqlSession级别的缓存,默认是开启的 每一个 session 会话都会有各自的缓存 ...

  2. Spring配置xml自定义事务管理器

    上一篇博客讲解了Spring配置xml事务,使用的是Spring框架提供的事务管理器. 在本篇博文当中,来讲解一下使用自定义的事务管理方式. 把上一篇博文当中的这个配置 <bean id=&qu ...

  3. InputNumber 不能输入点 viewDesign 需求是 只能是整数

    <InputNumber ref="xxxRef" v-model="xxx" :disabled="xxx" style=" ...

  4. C#实现一个简单的日志类

    目录 自定义日志类 NLog版本的日志类 Serilog版本的日志类 上个月换工作,新项目又要重新搭建基础框架,把日志实现部分单独记录下来方便以后参考. 自定义日志类 代码大部分使用ChatGPT生成 ...

  5. Ubuntu 22.04 源码安装ST-Link V2过程详解

    一 首先安装依赖工具: A 安装预编译库: sudo apt-get install git make cmake libusb-1.0-0-dev B 安装gcc库: sudo apt-get in ...

  6. KETTLE实战视频教程--免费白嫖(本贴持续更新)

    KETTLE实战视频教程 欢迎关注笔者的公众号: java大师, 每日推送java.kettle运维等领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!!个人网站: http://w ...

  7. View事件机制源码分析

    目录介绍 01.Android中事件分发顺序 02.Activity的事件分发机制 2.1 源码分析 2.2 点击事件调用顺序 2.3 得出结论 03.ViewGroup事件的分发机制 3.1 看一下 ...

  8. HDFS Balancer负载均衡器

    目录 1.背景 2.什么是平衡 2.1 每个DataNode的利用率计算 2.2 集群的利用率 2.3 平衡 3.hdfs balancer语法 4.运行一个简单的balance案例 4.1 设置平衡 ...

  9. Dockerfile 时区设置(MacOs有效)

    # 设置时区RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtimeRUN echo 'Asia/Shanghai' >/etc/t ...

  10. 英语文档阅读学习系列之Zynq-7000 EPP Software Developers Guide

    阅读ug821-zynq-7000-swdev记录 1.略看目录Table 依旧采用总说加解释的模式,这种方式易于查找,是可靠的框架.目录词条依次为: Introduction Software Ap ...