封装的DynamicCRM平台中最实用的JS工具类
包含了一个遮罩层的使用对象和一个通用的CRM平台JS操作对象。
使用示例:
function toDo(callback) {
console.log('开始审批(BPM)')
if (!callback) {
Xrm.Utility.confirmDialog("您将做一个耗时操作,是否确认?", function () {
overflowLayer.open("操作执行中,请勿进行其他操作...", toDoM);
return;
})
}
else{
//执行操作
overflowLayer.close();
}
}
通用commonUtil工具JS
1 var isFirstDefineOverflowLayer = false;
2 /**
3 * 遮罩层的使用
4 */
5 var overflowLayer = overflowLayer || (function () {
6 if (window == window.top) {
7 return {
8 open: function (msg) { },
9 close: function () { },
10 appendShadowCls: function () { },
11 appendShadowDiv: function () { }
12 };
13 }
14 isFirstDefineOverflowLayer = true;
15 return {
16 layerId: 'layer_shadow_in_top_window',
17 /**
18 * 打开遮罩层
19 * @param {any} msg 遮罩层提示的信息
20 */
21 open: function (msg, callback) {
22 $('#' + this.layerId + '_div', window.top.document).css('display', 'block');
23 $('#' + this.layerId + '_msgDiv', window.top.document).css('display', 'block');
24 $('#' + this.layerId + '_msg', window.top.document).text(msg);
25 if (typeof callback === 'function') {
26 setTimeout(function () { callback(true); }, 100);// 中断JS线程让界面及时渲染
27 }
28 },
29 /**
30 * 关闭遮罩层
31 */
32 close: function () {
33 $('#' + this.layerId + '_div', window.top.document).css('display', 'none');
34 $('#' + this.layerId + '_msgDiv', window.top.document).css('display', 'none');
35 },
36 /**
37 * 添加遮罩层样式至顶层页面
38 */
39 appendShadowCls: function () {
40 var doc = window.top.document;
41 var shadowCssId = this.layerId + '_css';
42 var shadowCss = doc.getElementById(shadowCssId);
43 if (shadowCss) {
44 return;
45 }
46 var shadowDode = '.msgbox-shadow {position: fixed;left: 0;top: 0;right: 0;bottom: 0;background-color: #FFF;opacity: 0.8;z-index: 10000;}';
47 var modalCode = '.msgbox-modal {position: fixed;top: 50%;left: 50%;opacity: 1;transform: translate(-50%, -50%);z-index: 10001;}';
48 var style = doc.createElement('style');
49 style.id = shadowCssId
50 style.type = 'text/css';
51 style.rel = 'stylesheet';
52 //for Chrome Firefox Opera Safari
53 style.appendChild(doc.createTextNode(shadowDode));
54 style.appendChild(doc.createTextNode(modalCode));
55 //for IE
56 if (this.isIE()) {
57 style.styleSheet.cssText = shadowDode;
58 style.styleSheet.cssText = modalCode;
59 }
60 var head = doc.getElementsByTagName('head')[0];
61 head.appendChild(style);
62 },
63 appendShadowDiv: function () {
64 var doc = window.top.document;
65 var shadowDivId = this.layerId + '_div';
66 var shadowDiv = doc.getElementById(shadowDivId);
67 if (shadowDiv) {
68 return;
69 }
70
71 var body = doc.getElementsByTagName('body')[0];
72 var layerDiv = doc.createElement('div');
73 body.appendChild(layerDiv);
74 layerDiv.id = shadowDivId;
75 layerDiv.classList.add('msgbox-shadow');
76 var msgDiv = doc.createElement('div');
77 msgDiv.id = this.layerId + '_msgDiv';
78 body.appendChild(msgDiv);
79 msgDiv.classList.add('msgbox-modal');
80
81 msgDiv.style.textAlign = 'center';
82 var img = doc.createElement('img');
83 img.src = "/_imgs/processing_loader.gif";
84 img.classList.add('ms-crm-inline-processing');
85 msgDiv.appendChild(img);
86 msgDiv.appendChild(document.createElement('br'));
87 var msgText = doc.createElement('span');
88 msgText.id = this.layerId + '_msg';
89 msgText.style.fontSize = '20px';
90 msgText.style.margin = '0px';
91 msgText.style.padding = '0px';
92 msgDiv.appendChild(msgText);
93
94 layerDiv.style.display = 'none';
95 msgDiv.style.display = 'none';
96 },
97 isIE: function () {
98 var userAgent = navigator.userAgent;
99 var isOpera = userAgent.indexOf("Opera") > -1; //判断是否Opera浏览器
100 return userAgent.indexOf("compatible") > -1
101 && userAgent.indexOf("MSIE") > -1 && !isOpera; //判断是否IE浏览器
102 }
103 };
104 })();
105
106 if (isFirstDefineOverflowLayer) {
107 overflowLayer.appendShadowCls(); // 添加CSS样式到document
108 overflowLayer.appendShadowDiv(); // 添加遮罩层到顶层document
109 }
110
111 /**
112 * 封装常用CRM操作工具类
113 */
114 var commonUtil = (function () {
115 const BASE_URL = Xrm.Page.context.getClientUrl() + "/api/data/v8.2";
116 //是否本地
117 const IS_LOCAL = true;
118 /**
119 * 获取当前运行环境
120 */
121 const getEnvironment = function () {
122 if (Xrm.Page.context.getClientUrl().indexOf("Testf") >= 0)
123 return "1";//测试环境
124 else if (Xrm.Page.context.getClientUrl().indexOf("hwdms") >= 0)
125 return "2";//正式环境
126 }
127 /**
128 * 打开弹窗
129 */
130 const openDialog = function (page, params, cbfun, level, width, height, top) {
131 if (level == null || level == "")
132 level = 0;
133 if (width == null || width == "")
134 width = 1000;
135 if (height == null || height == "")
136 height = 550;
137 if (top == null || top == "")
138 top = -300;
139 var Clienturl = Xrm.Page.context.getClientUrl();
140 var URL = Clienturl + "/WebResources/" + page;
141 var DialogOption = new Xrm.DialogOptions;
142 DialogOption.width = width;
143 DialogOption.height = height;
144 DialogOption.top = top;
145 switch (level) {
146 case 0://0级子页面,即当前页面打开弹窗
147 Xrm.Internal.openDialog(URL + "?Type=&data=" + params, DialogOption, null, null, cbfun);
148 break;
149 case 1://1级子页面打开弹窗
150 parent.Xrm.Internal.openDialog(URL + "?Type=&data=" + params, DialogOption, null, null, cbfun);
151 break;
152 }
153 }
154 /**
155 * 根据查询URL执行查询操作
156 * @param {any} queryUrl 查询URL
157 * @param {any} callback 结果回调方法
158 * @param {any} async 是否异步查询,默认为true
159 * @param {int} maxRows 获取记录的最大条数,默认为空
160 */
161 const queryWithUrl = function (queryUrl, callback, async, maxRows) {
162 if (!queryUrl) {
163 callback && callback({ success: false, message: '参数queryUrl不可为空' })
164 return
165 }
166 var req = new XMLHttpRequest();
167 req.open("GET", BASE_URL + queryUrl, async !== false);
168 req.setRequestHeader("OData-MaxVersion", "4.0");
169 req.setRequestHeader("OData-Version", "4.0");
170 req.setRequestHeader("Accept", "application/json");
171 req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
172 req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"" + (maxRows ? (",odata.maxpagesize=" + maxRows) : ""));
173 req.onreadystatechange = function () {
174 if (this.readyState === 4) {
175 req.onreadystatechange = null;
176 let result = { success: false, message: this.statusText }
177 if (this.status === 200) {
178 result.success = true
179 let data = JSON.parse(this.response)
180 result.data = data.value || data
181 } else {
182 console.error(this.response)
183 }
184 callback && callback(result)
185 }
186 };
187 req.send();
188 }
189
190 const createEntity = function (entitySetName, entityData, callback, async) {
191 if (!entitySetName) {
192 callback && callback({ success: false, message: '参数entitySetName不可为空' })
193 return
194 }
195 var req = new XMLHttpRequest();
196 req.open("POST", `${BASE_URL}/${entitySetName}`, async !== false);
197 req.setRequestHeader("OData-MaxVersion", "4.0");
198 req.setRequestHeader("OData-Version", "4.0");
199 req.setRequestHeader("Accept", "application/json");
200 req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
201 req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");
202 req.onreadystatechange = function () {
203 let result = { success: false, message: this.responseText }
204 if (this.readyState === 4) {
205 req.onreadystatechange = null;
206 if (this.status === 204) {
207 var uri = this.getResponseHeader("OData-EntityId");
208 var regExp = /\(([^)]+)\)/;
209 var matches = regExp.exec(uri);
210 result.success = true
211 result.data = { id: matches[1] }
212 } else {
213 console.error('----' + this.responseText)
214 }
215 } else {
216 console.error('==== ' + this.responseText)
217 }
218 callback && callback(result)
219 };
220 req.send(JSON.stringify(entityData));
221 }
222
223 const updateEntity = function (entitySetName, entityId, entityData, callback, async) {
224 if (!entitySetName) {
225 callback && callback({ success: false, message: '参数entitySetName不可为空' })
226 return
227 }
228 var req = new XMLHttpRequest();
229 req.open("PATCH", `${BASE_URL}/${entitySetName}(${entityId})`, async !== false);
230 req.setRequestHeader("OData-MaxVersion", "4.0");
231 req.setRequestHeader("OData-Version", "4.0");
232 req.setRequestHeader("Accept", "application/json");
233 req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
234 req.onreadystatechange = function () {
235 let result = { success: false, message: this.statusText }
236 if (this.readyState === 4) {
237 req.onreadystatechange = null;
238 if (this.status === 204) {
239 result.success = true
240 result.data = { id: entityId }
241 } else {
242 console.error('----' + this.statusText)
243 }
244 } else {
245 console.error('==== ' + this.statusText)
246 }
247 callback && callback(result)
248 };
249 req.send(JSON.stringify(entityData));
250 }
251
252 /**
253 * 根据业务实体集合名称及业务实体ID删除指定的记录
254 * @param {any} entitySetName 【必须】业务实体集合名称
255 * @param {any} entityId 【必须】业务实体ID
256 * @param {any} callback 【可选】回调方法,参数为:{success:true/false,message:null/具体错误信息}
257 * @param {any} async 【可选】是否异步操作,默认为true,传入false时则同步执行,否则按异常执行
258 */
259 const deleteEntity = function (entitySetName, entityId, callback, async) {
260 var req = new XMLHttpRequest();
261 req.open("DELETE", `${BASE_URL}/${entitySetName}(${entityId})`, async !== false);
262 req.setRequestHeader("Accept", "application/json");
263 req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
264 req.setRequestHeader("OData-MaxVersion", "4.0");
265 req.setRequestHeader("OData-Version", "4.0");
266 req.onreadystatechange = function () {
267 if (this.readyState === 4) {
268 req.onreadystatechange = null;
269 callback && callback({
270 success: this.status === 204 || this.status === 1223,
271 message: this.statusText
272 })
273 if (this.status !== 204 && this.status !== 1223) {
274 console.error(this.response)
275 }
276 }
277 };
278 req.send();
279 }
280 /**
281 * 通过实体id取得数据
282 */
283 const getEntityData = function (entity, id) {
284 var resultData = null;
285 var queryUrl = "/" + entity + "(" + commonUtil.delBrackets(id) + ")";
286 commonUtil.queryWithUrl(queryUrl,
287 (result) => {
288 console.log("getEntityData", result)
289 if (result != null && result.data != null)
290 resultData = result.data;
291 }, false, 1);
292
293 return resultData;
294 }
295 /**
296 * 通过查询url取得数据
297 */
298 const getEntityDatas = function (queryUrl) {
299 var resultData = null;
300 commonUtil.queryWithUrl(queryUrl, (result) => {
301 if (result && result.data && result.data.length) {
302 resultData = result.data;
303 }
304 }, false);
305
306 return resultData;
307 }
308 /**
309 * 在URL中解析ID
310 */
311 const getIdFromUrl = function () {
312 let objData = parseParams()
313 return objData['?_CreateFromId'] && decodeURIComponent(objData['?_CreateFromId'])
314 }
315 /**
316 * 解析URL传入的参数
317 */
318 const parseParams = function () {
319 var objData = {};
320 var vals = decodeURIComponent(getParameter("extraqs")).split("&");
321 for (var i = 0; i < vals.length; i++) {
322 var pr = vals[i].replace(/\+/g, " ").split("=");
323 if (pr.length != 2) {
324 continue;
325 }
326 objData[pr[0]] = pr[1];
327 }
328 return objData;
329 }
330 /**
331 * 获取参数信息
332 * @param {any} param url参数
333 */
334 const getParameter = function (param) {
335 var query = window.top.location.search;
336 var iLen = param.length;
337 var iStart = query.indexOf(param);
338 if (iStart == -1)
339 return "";
340 iStart += iLen + 1;
341 var iEnd = query.indexOf("&", iStart);
342 if (iEnd == -1)
343 return query.substring(iStart);
344 return query.substring(iStart, iEnd);
345 }
398 /**
399 * 判断页面元素是否字段控件类型
400 * @param {any} control 控件对象
401 */
402 const controlIsAttribute = function (control) {
403 var controlType = control.getControlType();
404 return controlType != "iframe" && controlType != "webresource" && controlType != "subgrid";
405 }
406
407 return {
408 /**
409 * 根据查询URL执行查询操作
410 * @param {any} queryUrl 查询URL
411 * @param {any} callback 结果回调方法
412 * @param {any} async 是否异步查询,默认为true
413 * @param {int} maxRows 获取记录的最大条数,默认为空
414 */
415 queryWithUrl: queryWithUrl,
416 /**
417 * 根据业务实体集合名称及业务实体ID删除指定的记录
418 * @param {any} entitySetName 【必须】业务实体集合名称
419 * @param {any} entityId 【必须】业务实体ID
420 * @param {any} callback 【可选】回调方法,参数为:{success:true/false,message:null/具体错误信息}
421 * @param {any} async 【可选】是否异步操作,默认为true,传入false时则同步执行,否则按异常执行
422 */
423 deleteEntity: deleteEntity,
424 /**
425 * 根据业务实体集合名称及业务实体数据创建新的记录
426 * @param {any} entitySetName 【必须】业务实体集合名称
427 * @param {any} entityData 【必须】业务实体数据
428 * @param {any} callback 【可选】回调方法,参数为:{success:true/false,message:null/具体错误信息}
429 * @param {any} async 【可选】是否异步操作,默认为true,传入false时则同步执行,否则按异常执行
430 */
431 createEntity: createEntity,
432 /**
433 * 根据业务实体集合名称及业务实体数据创建新的记录
434 * @param {any} entitySetName 【必须】业务实体集合名称
435 * @param {any} entityId 【必须】业务实体ID
436 * @param {any} entityData 【必须】业务实体数据
437 * @param {any} callback 【可选】回调方法,参数为:{success:true/false,message:null/具体错误信息}
438 * @param {any} async 【可选】是否异步操作,默认为true,传入false时则同步执行,否则按异常执行
439 */
440 updateEntity: updateEntity,
441 /**
442 * 将传入的数值保留两位小数后返回
443 */
444 keep2DecimalPlace: (decimalValue) => {
445 if (!decimalValue || isNaN(decimalValue)) {
446 return decimalValue
447 }
448 return Math.round(decimalValue * 100) / 100
449 },
450 /**
451 * 读取服务器时间
452 */
453 getServerTime: () => {
454 var xhr = null;
455 if (window.XMLHttpRequest) {
456 xhr = new window.XMLHttpRequest();
457 } else { // ie
458 xhr = new ActiveObject("Microsoft")
459 }
460 xhr.open("GET", "/", false)//false不可变
461 xhr.send(null);
462 return new Date(xhr.getResponseHeader("Date"))
463 },
464 /**
465 * 判断当前窗体是不是新建窗口
466 */
467 isCreateForm: () => { return Xrm.Page.ui.getFormType() === 1 },
468 /**
469 * 判断当前窗体是不是编辑窗口
470 */
471 isUpdateForm: () => { return Xrm.Page.ui.getFormType() === 2 },
472 /**
473 * 判断对象是否为字符串
474 */
475 isString: (obj) => { return Object.prototype.toString.call(obj) === "[object String]" },
476 /**
477 * 读取查询类型属性的id
478 */
479 getLookupId: (fieldName) => {
480 let attribute = Xrm.Page.getAttribute(fieldName)
481 if (!attribute) {
482 Xrm.Utility.alertDialog(`不存在的属性【${fieldName}】,请传入正确的属性名`)
483 return;
484 }
485 let fieldType = attribute.getAttributeType()
486 if (fieldType !== 'lookup') {
487 Xrm.Utility.alertDialog(`属性【${fieldName}】不是查找类型的字段,不可使用getLookupId方法`)
488 return
489 }
490 let lookupValue = attribute.getValue()
491 return lookupValue ? lookupValue[0].id : null
492 },
493 /**
494 * 读取查询类型属性的name
495 */
496 getLookupName: (fieldName) => {
497 let attribute = Xrm.Page.getAttribute(fieldName)
498 if (!attribute) {
499 Xrm.Utility.alertDialog(`不存在的属性【${fieldName}】,请传入正确的属性名`)
500 return;
501 }
502 let fieldType = attribute.getAttributeType()
503 if (fieldType !== 'lookup') {
504 Xrm.Utility.alertDialog(`属性【${fieldName}】不是查找类型的字段,不可使用getLookupName方法`)
505 return
506 }
507
508 let lookupValue = attribute.getValue()
509 return lookupValue ? lookupValue[0].name : null
510 },
511 /**
512 * 设置Lookup类型的值
513 * @param {any} LookupAttribute lookup控件字段名
514 * @param {any} Type 实体类型
515 * @param {any} Id 设置值的Guid
516 * @param {any} Name 值 显示名称
517 */
518 setLookupValue: (LookupAttribute, Type, Id, Name) => {
519 var lookupReference = [];
520 lookupReference[0] = {};
521 lookupReference[0].id = Id;
522 lookupReference[0].entityType = Type;
523 lookupReference[0].name = Name;
524 Xrm.Page.getAttribute(LookupAttribute).setValue(lookupReference);
525 },
526 /**
527 * 取得登录角户角色
528 */
529 GetRoleNames: () => {
530 let roleNames = [];
531 let userId = Xrm.Page.context.getUserId();
532 let queryUrl = `/systemusers(${commonUtil.delBrackets(userId)})?$select=fullname&$expand=systemuserroles_association($select=name)`
533 commonUtil.queryWithUrl(queryUrl, (result) => {
534 if (result.success) {
535 result.data.systemuserroles_association.forEach(r => {
536 roleNames.push(r.name);
537 })
538 }
539 }, false)
540 return roleNames;
541 },
542 /**
543 * 设置表单所有控件不可编辑
544 */
545 DisableALLControls: () => {
546 Xrm.Page.ui.controls.forEach(function (control, index) {
547 if (controlIsAttribute(control)) {
548 control.setDisabled(true);
549 }
550 })
551 },
552 /**
553 * 删除传入字符串首尾的{}
554 */
555 delBrackets: (str) => {
556 if (!str) {
557 return str;
558 }
559 return str.replace(/^\{|\}$/g, "").toUpperCase();
560 },
561 distinctArr: (arr, distinctKey) => {
562 const result = []
563 if (!arr || !arr.length) {
564 return result
565 }
566 const obj = {} // 标识是否存在相同的唯一标识
567 for (item of arr) {
568 if (!obj[distinctKey ? item[distinctKey] : item]) {
569 result.push(item)
570 obj[distinctKey ? item[distinctKey] : item] = true
571 }
572 }
573
574 return result
575 },
576 /**
577 * 获取实体ObjectTypeCode
578 */
579 getObjectTypeCode: ()=> {
580 var url = $("#crmContentPanel", window.top.document).attr("src");
581 var index = url.indexOf("etc=");
582 var objectTypeCode = url.substring(index + 4, index + 9);
583 return objectTypeCode
584 },
585 /**
586 * 获取数据Id
587 * @param {any} type 当前页面:0主页面 1子页面 2关联视图
588 */
589 getId: (type) =>{
590 var id = "";
591 switch ((type == null || type == "") ? 0 : type) {
592 case 0://主页面获取
593 id = Xrm.Page.data.entity.getId();
594 break;
595 case 1://从子页面获取
596 id = Xrm.Page.context.getQueryStringParameters()._CreateFromId;
597 break;
598 case 2://从关联视图页面获取
599 id = Xrm.Page.context.getQueryStringParameters().id;
600 break;
601 }
602 return commonUtil.delBrackets(id);
603 },
604 /**
605 * 通过实体id获取实体数据
606 */
607 getEntityData: getEntityData,
608 /**
609 * 通过查询url获取相关实体数据
610 */
611 getEntityDatas: getEntityDatas,
612 /**
613 * 在URL中解析ID
614 */
615 getIdFromUrl: getIdFromUrl,
616 /*
617 * 解析URL传入的参数
618 * (自定义页面可用)
619 */
620 parseParams: parseParams,
621 /*
622 * 打开弹窗(自定义页面)
623 */
624 openDialog: openDialog,
625 /*
626 * 获取当前环境
627 */
628 getEnvironment: getEnvironment,
629 /**
630 * 激活按钮隐藏
631 */
632 isDisplayActivate: () => {
633 return false;
634 },
635 /**
636 * 停用按钮隐藏
637 */
638 isDisplayDeactivate: () => {
639 return false;
640 }, 669 /**
670 * 获取用户Id
671 */
672 GetUserId: () => {
673 var id = Xrm.Page.context.getUserId();
674 id = id.toString().replace("{", "").replace("}", "");
675
676 return id;
677 }
678 }
679 })()
封装的DynamicCRM平台中最实用的JS工具类的更多相关文章
- 封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil
封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil,代码比较简单,主要是把MongoTarget的配置.FileTarget的配置集成到类中,同时利用缓存依赖来判断是否需要重新创 ...
- 封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil,nloglogutil
封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil,代码比较简单,主要是把MongoTarget的配置.FileTarget的配置集成到类中,同时利用缓存依赖来判断是否需要重新创 ...
- Go/Python/Erlang编程语言对比分析及示例 基于RabbitMQ.Client组件实现RabbitMQ可复用的 ConnectionPool(连接池) 封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil 分享基于MemoryCache(内存缓存)的缓存工具类,C# B/S 、C/S项目均可以使用!
Go/Python/Erlang编程语言对比分析及示例 本文主要是介绍Go,从语言对比分析的角度切入.之所以选择与Python.Erlang对比,是因为做为高级语言,它们语言特性上有较大的相似性, ...
- 超级实用的 Java 工具类
超级实用的 Java 工具类 在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类.以下工具类.方法按使用流行度排名,参考数据来源于Github上随机选取 ...
- Android实用的Toast工具类封装
Toast这个提示框大家都晓得,显示一段时间后自动消失,不能获得焦点.但是在使用中有些问题: 1)需要弹出一个新的Toast时,上一个Toast还没有显示完2)可能重复弹出相同的信息3)Toast具体 ...
- Nutz中那些好用的工具类
Nutz 是国产的精品开源框架,它全无依赖,只以1兆多的身材,就可以实现SSH全部功能的90%以上.内容主要涵盖了:Ioc.Aop.MVC.Dao.Json等WEB开发的方方面面. 它不仅轻巧,而且 ...
- 【深度精讲】JFinal中的Ret和Kv工具类的区别,你用对了吗?
在JFinal中有两个类Map的工具类,一个是有状态的Ret,一个是无状态的Kv,各种自己的应用场景,你用对了吗? 下面我们从多个方面来探究一下,JFinal针对这两个类的设计: 一.位置-com.j ...
- 封装一个简单好用的打印Log的工具类And快速开发系列 10个常用工具类
快速开发系列 10个常用工具类 http://blog.csdn.net/lmj623565791/article/details/38965311 ------------------------- ...
- Java中的4个并发工具类 CountDownLatch CyclicBarrier Semaphore Exchanger
在 java.util.concurrent 包中提供了 4 个有用的并发工具类 CountDownLatch 允许一个或多个线程等待其他线程完成操作,课题点 Thread 类的 join() 方法 ...
- Java中的AES加解密工具类:AESUtils
本人手写已测试,大家可以参考使用 package com.mirana.frame.utils.encrypt; import com.mirana.frame.constants.SysConsta ...
随机推荐
- HTML5+CSS3+JavaScript网页实战
1. HTML5基础 HTML5,作为构建和呈现网页内容的标准标记语言,带来了许多革命性的变化.它不仅提供了更加语义化的标签,使得网页内容更具可读性和可访问性,还增加了对多媒体的原生支持,无需依赖第三 ...
- SSIS作业提示所请求的 OLE DB 访问接口 Microsoft.ACE.OLEDB.12.0 尚未注册
没有跨不过的坎,也没有解决不了的问题,那些曾经没有把我们打死的困难,最终都会让我们变得更加强大 最近在使用ETL获取Excel数据时,在本地运行没有任何问题,部署到服务器后,使用作业运行时便一直提示以 ...
- Python安装技术类库模块
方法1: 方法2: 用如下命令安装即可(注意都得是英文字符): # 简单粗暴,但是可能安装到了不同的环境 pip install some-package # 复杂但是精准还快速 C:\Python3 ...
- Nuxt.js 应用中的 listen 事件钩子详解
title: Nuxt.js 应用中的 listen 事件钩子详解 date: 2024/11/9 updated: 2024/11/9 author: cmdragon excerpt: 它为开发者 ...
- OSG开发笔记(三十三):同时观察物体不同角度的多视图从相机技术
前言 前面的相机hud可以单独显示图形,继续深入研究相机hud,技术就是子视图了,实现该功能的直接技术是从相机技术. 本篇描述osg从相机技术 Demo 相机视口的关键调用 ...
- ArcGIS填补面图层的细小空白并删除主体部分外的零散部分
本文介绍在ArcMap软件中,基于消除面部件("Eliminate Polygon Part")工具,对矢量面要素的零碎.空洞区域加以删除,同时将游离于要素主体之外的部分剔除的 ...
- (Python基础教程之十一)Python找到最大的N个(前N个)或最小的N个项目
Python基础教程 在SublimeEditor中配置Python环境 Python代码中添加注释 Python中的变量的使用 Python中的数据类型 Python中的关键字 Python字符串操 ...
- Spring MVC 3.2 技术预览(一):Servlet 3介绍,异步支持
原文地址:http://blog.springsource.org/2012/05/06/spring-mvc-3-2-preview-introducing-servlet-3-async-supp ...
- Linux之查看开放端口
在网络技术中,端口(Port)包括逻辑端口和物理端口两种类型.物理端口指的是物理存在的端口,如ADSL Modem.集线器.交换机.路由器上用 于连接其他网络设备的接口,如RJ-45端口.SC端口等等 ...
- 4-CSRF漏洞渗透与防御
1.什么是CSRF漏洞 Cross-Site Request Forgery 跨站请求伪造 从一个第三方的网站,利用其他网站生效的cookie,直接请求服务器的某一个接口,导致攻击发生! 2.CSRF ...