余生所遇之人,都是好人

愿你三冬暖,愿你春不寒。
愿你天黑有灯,下雨有伞。
愿你一路上,有良人相伴 。
愿时光能缓,愿故人不散。
愿你所有快乐,无需假装。
愿你此生尽兴,赤诚善良。
愿你惦念的人能和你道晚安,
愿你独闯的日子里不觉得孤单。
愿你余生所遇之人,都是好人。

人的这一生

26岁,你看着身边的人都结了婚
婚礼的份子钱逐年递增
春节回家,父母从带你串亲戚
变成了带你去见相亲对象
见了十几个姑娘
你每次都觉得和那个她比
差了一点
28岁那年,你遇到了一个和你遭遇差不多的姑娘
你们有一搭没一搭的聊着
她说:你还不错
你喝了一口可乐说:你也是
你还不确定喜不喜欢她
双方家长就已经摆好了订婚宴
结婚的前一周,你和朋友出去喝酒
你说,不想结婚
朋友说,你啊,就是想太多。谁不是这么过来的?
29岁,你们终于结了婚
婚礼办的不大不小,朋友来的不多不少
攒了几年想要去实现理想的钱
搭在了这一场百人的私人庙会上

婚礼进行到中间
司仪带着标准的商业化微笑
对着台下的亲朋喊道
要不要让他们亲一个!
台下那些人跟着一起起哄
不知道为什么
你简简单单的亲了一口
俩人恢复到了一开始的站位
你小声说了一句:我爱你
那个昨天还看不惯你倒腾模型的新娘
愣了一下说:我也爱你
你不确定她是不是对你说的
就像你不确定是不是对她说的一样
婚礼结束后,并没有你想象的浪漫
你听着外屋的新娘一笔一笔的算着份子钱
想着不过才两年,怎么就变成这样了
想着想着,洞房夜就睡着了
30岁,她怀孕了
辞掉了工作,在家养胎
你在公司逐渐有了点地位
手里管着十来个人
独立负责一个项目
结婚前陪嫁的那辆20万左右的车
也变成了你一个人的独享
但你依然不敢放松
每次加班
电话那头都是抱怨与委屈
但你不能争辩什么
谁让她怀了你的孩子
在这一刻
不论是她的父母还是你的父母
都无条件的站在这一边
31岁,孩子落地了
前前后后连孕检带住院费花了10万块钱
不过无所谓
你看着你的孩子,怎么看怎么喜欢
高兴的仿佛这是你的新生
32岁,这是人生最不愿意重复的一年
平均睡眠3小时
孩子每一个小时都要闹腾一次
第二天拖着睡不醒的眼睛去上班
老板说你上班不干活
回家媳妇说你不干活
你想了半天不明白,那谁干活呢?
那辆开了3年的车
成为了你真正的家
你不在抱怨路上拥堵的交通
你甚至开始希望
再多堵一会
回到家,你关了发动机
在车上点了一根烟
这是你每天最幸福的十分钟
车前是功名利禄,车尾是柴米油盐
35岁,你因为身体越来越差
加班越来越少
晋升的速度也越来越缓慢
那天下班,媳妇告诉你
孩子要上幼儿园了
双语的一个月3000
你皱了皱眉头,那边就已经不耐烦了
“四单元的老王家孩子,一个月6000”
“你已经这样了,你想让孩子也输?”
你没说话,回屋给媳妇转了6000块钱
这笔钱,你原本打算给自己过个生日,买个新电脑
38岁,孩子上了一年级
老师说一年级最关键,打好基础很重要
你笑着说,是是是,老师您多照顾
新生接待的老师看着你不明事理的脸
给你指了一条明路
“课外辅导班,一个月2200”
40岁的时候,孩子上了三年级
老师说,三年级,最关键,承上启下很重要
你笑着说:是是是,正打算再报个补习班
44岁,孩子上了初中
有一天回到家,她对你说
爸爸,我想学钢琴
你没什么犹豫的
你以为这些年,你已经习惯了
但那句“爸爸现在买不起”你始终说不出口
好在孩子比较懂事
她说:爸爸没事,要不我先学陶笛也可以
你看着这么懂事的孩子,却开心不起来
46岁,孩子上了一个不好不差的高中
有一天你在开会,接到了老师的电话
电话里说你的孩子在学校打架了
叫你去一趟
你唯唯诺诺的
和那个比你还小5岁的领导请了个假
到学校又被老师训了一通
无非台词就是那一句
你们做家长的就知道工作,能不能陪陪孩子
你看着这个老师,有点可笑
好像当时说:
家长在外辛苦点
多赚点钱让孩子多补补课的和他不是一个人
50岁,孩子上了大学
很争气,是一个一本
他学的专业你有点看不懂
你只知道工作不一定好找
而且学费还死贵
你和他深夜想聊聊
准备了半斤白酒,一碟花生米
你说着那些曾经你最讨厌的话
还是要为以后工作着想
挑个热门的专业
活着比热爱重要
你们从交流变成了争吵
你发现,你老了
老到可能都打不过这个18岁的孩子
你说不过他,只能说一句:我是你爸爸!
孩子看着你,知道再怎么争辩都没用
这场确立你最后威严的酒局不欢而散
你听的不真切
在孩子回自己屋的路上好像叨叨了一句
“我不想活的像你一样”
怎么就哭了呢?50岁的人了
一定是酒太辣了,对不对
一定是酒太辣了
55岁,孩子工作了,似乎有一点理解你了
但你却反了过来,你说不要妥协
56岁,孩子也结婚了
你问他喜欢那个姑娘么
他愣了愣说:喜欢吧
60岁,辛苦了一辈子,想出去走走
身边的那个人过了30年
你依旧分不清到底喜不喜欢
你们开始规划旅游路线
这么多年了
你们还是存在分歧,还是在争吵
某个瞬间,你觉得
这样可能也挺好
一切都准备好了
儿子说:爸妈,我工作太忙了
可以帮我照顾一下孩子么
你们退了机票,又回到了30年前

70岁,孩子的孩子也长大了,不用天天操心了
你下定决心说:一定要去玩一趟
可是手边的拐杖
只能支持你走到楼下的花园
75岁,你在医院的病床上
身边聚满了人,你迷迷糊糊的看见医生摇了摇头
周围那些人神情肃穆
你明白了,你要死掉了
你没有感到一丝害怕
你突然问自己,我到底是什么时候死掉的呢?
你想起来30岁的那场婚礼
原来,那时候,你就死掉了吧
依照惯例
死前的3秒,你的大脑要走马灯
倒叙你这75个年头的一生
画面一张一张的过
1秒
2秒
两秒过去了
你面无表情的看着这两秒内的回忆
第3秒
突然你笑了
原来已经回到了15岁的那一年
你看见一个男孩
他叼着一袋牛奶,背着书包
从另一个女孩家的阳台下跑过
那个男孩朝窗户里看了看
那是15岁的你暗恋的那个女孩子
你想不起来她长什么样子了
最后一秒你努力的回忆着
然后终于笑了出来
3秒过去了
身边的人突然间开始嚎啕大哭
你可能听不清了
你最后听到的嘈杂的声音
是一群十五六的少年,起着哄说的
答应他
答应他
答应他

对待孤独

​ 一个人看电影、学习、生活感觉特别孤独、寂寞,如何排解。孤独是一种常态,一生中没有人能陪你一辈子,包括你的父母、孩子,有些朋友只是你人生某个时段的陪伴,人生大多数时候都是一个人在孤独中度过。有很多人我们认识了、离开了,也许杳无音信,再不相见。如果你不能很好地做到自己跟自己相处,那么做很多事情时都会出现障碍。你要清楚地知道孤单不是一种错,也不代表心理有问题,这只是一种常态,你要学会跟自己相处,学会跟自己的内心独处。

操作jar包内文件以及jar包内jar包里文件的方法

#操作jar包内文件以及jar包内jar包里文件的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
package com.supcon.supfusion.framework.cloud.i18n.resource.utils;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JarUtil {


// public static void main(String args[]) {
//
// JarUtil f = new JarUtil();
// f.instal();
// }

/**
* 安装jar包
*/
private void instal() {
System.out.println("Start Installing Portal......");
System.out.println("Start Extracting File......");

String jarFileName = "portal.jar";
Date d = new Date();
String outputPath = "portal" + d;
try {
//执行解压
decompress(jarFileName, outputPath);
System.out.println("Extracting OK!");
} catch (IOException e) {
e.printStackTrace();
System.out.println("Extracting File Failed!");
dealError(outputPath);
System.out.println("Installing Portal Failed");
return;
}

String systemName = System.getProperty("os.name");
System.out.println("System is " + systemName);
//如果是unix系列操作系统则赋予用户可执行权限
if (!systemName.toLowerCase().contains("windows")) {
System.out.println("Start Granting User Excecute Rights......");
try {
Process p1 = Runtime.getRuntime().exec("chmod +x portal.sh");
p1.waitFor();
Process p2 = Runtime.getRuntime().exec("portal.sh");
p2.waitFor();
System.out.println("Granting User Excecute Rights OK!");
} catch (Exception e) {
e.printStackTrace();
System.out.println("Granting User Excecute Rights Failed!");
dealError(outputPath);
System.out.println("Installing Portal Failed");
return;
}
}
}


/**
* 解压缩JAR包
*
* @param fileName 文件名
* @param outputPath 解压输出路径
* @throws IOException IO异常
*/
private void decompress(String fileName, String outputPath) throws IOException {

if (!outputPath.endsWith(File.separator)) {
outputPath += File.separator;

}
JarFile jf = new JarFile(fileName);
for (Enumeration e = jf.entries(); e.hasMoreElements(); ) {
JarEntry je = (JarEntry) e.nextElement();
String outFileName = outputPath + je.getName();
File f = new File(outFileName);
System.out.println(f.getAbsolutePath());

//创建该路径的目录和所有父目录
makeSupDir(outFileName);

//如果是目录,则直接进入下一个循环
if (f.isDirectory()) {
continue;
}

InputStream in = null;
OutputStream out = null;

try {
in = jf.getInputStream(je);
out = new BufferedOutputStream(new FileOutputStream(f));
byte[] buffer = new byte[2048];
int nBytes = 0;
while ((nBytes = in.read(buffer)) > 0) {
out.write(buffer, 0, nBytes);
}
} catch (IOException ioe) {
throw ioe;
} finally {
try {
if (null != out) {
out.flush();
out.close();
}
} catch (IOException ioe) {
throw ioe;
} finally {
if (null != in) {
in.close();
}
}
}
}
}

/**
* 循环创建父目录
*
* @param outFileName
*/
private void makeSupDir(String outFileName) {
//匹配分隔符
Pattern p = Pattern.compile("[" + File.separator + "]");
Matcher m = p.matcher(outFileName);
//每找到一个匹配的分隔符,则创建一个该分隔符以前的目录
while (m.find()) {
int index = m.start();
String subDir = outFileName.substring(0, index);
File subDirFile = new File(subDir);
if (!subDirFile.exists())
subDirFile.mkdir();
}
}

/**
* 递归删除目录及子目录
*
* @param path
*/
private void clean(String path) throws IOException {
File file = new File(path);
//如果该路径不存在
if (!file.exists()) {
System.out.println(path + " Not Exist!");
} else {
//如果是目录,则递归删除
if (file.isDirectory()) {
String[] fileNames = file.list();

if (null == fileNames) {
throw new IOException("IO ERROR While Deleting Files");
}
//如果是空目录则直接删除
else if (fileNames.length == 0) {
file.delete();
} else {
for (String fileName : fileNames) {
File subFile = new File(fileName);
clean(path + File.separator + subFile);
}
System.out.println(file.getAbsolutePath());
//最后删除父目录
file.delete();

}
}
//如果是文件,则直接删除
else {
System.out.println(file.getAbsolutePath());
file.delete();
}
}
}

/**
* 处理安装错误的异常,调用清洗过程
*
* @param outputPath 输出路径
* @throws IOException IO异常
*/
private void dealError(String outputPath) {
//删除已解压的文件
System.out.println("Start Deleting Files......");
try {
clean(outputPath);
System.out.println("Deleting Files OK!");
} catch (IOException e) {
e.printStackTrace();
System.out.println("Deleting Files Failed!");
}
}
package com.supcon.supfusion.framework.cloud.i18n.resource.utils;


import com.supcon.supfusion.framework.cloud.common.util.StringExUtil;
import com.supcon.supfusion.framework.cloud.i18n.constants.ResourcesConstant;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
* i18n资源处理操作
* <ul>
* 进程拉起时处理流程 -> process
* <li>读取资源目录</li>
* <li>资源转储临时目录 -> temp</li>
* <li>压缩临时目录 -> compress</li>
* <li>上传至服务器 -> upload</li>
* <li>删除临时目录 -> deleteAnyone</li>
* </ul>
*/
@Slf4j
public class MessageFileUtil {

/********************************************* Process Method ******************************************/

/**
* 上传结束后删除临时目录
* 本地流程的最后一步操作
*
* @param tempDir
* @return
*/
public static Boolean delete(String tempDir) {
try {
tempDir = addFileSeperator(tempDir);
deleteAnyone(tempDir);
} catch (Exception e) {
log.error("delete temp dir fail! ", e);
}
return true;
}

/**
* 处理本地国际化资源目录
*
* @param messageDir
* @param tempDir
* @param modules
* @return
*/
public static String compressBundleMessage(String messageDir, String tempDir, String[] modules) {
URL url = locateUrl(messageDir);
if (null != url) {
String s = url.toString();
if (s.startsWith(ResourcesConstant.JAR_FILE_PREFIX)) {
MessageFileUtil.jarCreateTransform(messageDir, tempDir, modules, url);
} else if (s.startsWith(ResourcesConstant.FILE_PREFIX)) {
MessageFileUtil.fileCreateTransform(tempDir, modules, url);
}
} else {
url = locateUrl("");
//TODO 扫描 指定文件 路径获取资源压缩 若为空 遍历寻找对应jar包,找到对应jar包获取资源压缩
MessageFileUtil.jarsCreateTransform(messageDir, tempDir, modules, url);
}
return tempDir;
}


/**
* 多个模块 遍历每一个 当前jar包内系统中对应文件夹下资源
*/
private static void jarCreateTransform(String messageDir, String tempDir, String[] modules, URL url) {
if (modules != null && modules.length > 0) {
ArrayList<String> localModules = new ArrayList<String>(Arrays.asList(modules));
//循环多个模块 以次压缩每个模块的资源 到临时目录
if (localModules != null && localModules.size() > 0) {
localModules.forEach(module -> {
jarCreate(messageDir, tempDir, module, url);
});
}
}
}

/**
* 多个模块 遍历每一个 文件系统中对应文件夹下资源
*/
private static void fileCreateTransform(String tempDir, String[] modules, URL url) {
if (modules != null && modules.length > 0) {
ArrayList<String> localModules = new ArrayList<String>(Arrays.asList(modules));
//循环多个模块 以次压缩每个模块的资源 到临时目录
if (localModules != null && localModules.size() > 0) {
localModules.forEach(module -> {
fileCreate(tempDir, module, url);
});
}
}
}

/**
* 多个模块 遍历每一个 jar包内的jar包资源
*/
private static void jarsCreateTransform(String messageDir, String tempDir, String[] modules, URL url) {
if (modules != null && modules.length > 0) {
ArrayList<String> localModules = new ArrayList<String>(Arrays.asList(modules));
//循环多个模块 以次压缩每个模块的资源 到临时目录
if (localModules != null && localModules.size() > 0) {
localModules.forEach(module -> {
tempJar(messageDir, tempDir, module, url);
});
}
}
}

/**
* 获取临时目录
*
* @param tempDir
* @return
*/
public static String systemTemp(String tempDir) {
//未设置临时目录,则取系统变量的临时目录
if (StringExUtil.isBlank(tempDir)) {
tempDir = System.getProperty(ResourcesConstant.SYSTEM_TEMP_DIR);
}
return tempDir;
}

/**
* 处理临时文件
*
* @param tempDir
* @return
*/
public static String messageTempPathResolve(String tempDir, String basename) {
//判断临时目录是否设置,未设置则取系统临时目录
tempDir = MessageFileUtil.systemTemp(tempDir);
//添加分隔符
tempDir = MessageFileUtil.addFileSeperator(tempDir);
//添加国际化目录
tempDir += StringExUtil.isNotBlank(basename) ? basename : ResourcesConstant.LOCALE_BASE_NAMES;
//添加系统分隔符,得到完整临时文件目录
tempDir = MessageFileUtil.addFileSeperator(tempDir);
return tempDir;
}

/********************************************* Private Step Method ******************************************/

/**
* 进程拉起时本地流程
*
* @param messageDir
* @param tempDir
* @return
*/
private static File jarCreate(String messageDir, String tempDir, String module, URL url) {
StringBuffer moduleDir = new StringBuffer(messageDir);
moduleDir.append(module);
File file = temp(moduleDir.toString(), tempDir, module, url);
File compressFile = compress(file, tempDir, module);
return compressFile;
}

/**
* 压缩国际化资源目录
*
* @param tempDir
* @param module
* @param url
* @return
*/
private static File fileCreate(String tempDir, String module, URL url) {
try {
File tempFile = new File(url.toURI());
MessageFileUtil.tempDir(tempDir);
String moduleDirPath = tempFile.getAbsolutePath();
StringBuffer moduleDir = new StringBuffer(moduleDirPath);
addFileSeperator(moduleDir);
moduleDir.append(module);
addFileSeperator(moduleDir);
File file = new File(moduleDir.toString());
File compressFile = compress(file, tempDir, module);
return compressFile;
} catch (URISyntaxException ex) {
log.error(ex.getMessage(), ex);
}
return null;
}

/**
* 读取i18n资源目录,写入临时文件目录
* 暂不支持jar包以外的打包方式
*
* @param messageDir
* @param tempDir
*/
private static File temp(String messageDir, String tempDir, String module, URL url) {
File file = null;
try {
tempDir = addFileSeperator(tempDir);
tempDir += module;
file = resolveTempFilesJar(messageDir, tempDir, url);
} catch (IOException e) {
log.error(e.getMessage());
}
return file;
}

/**
* 读取i18n资源目录,写入临时文件目录
* 暂不支持jar包以外的打包方式
*
* @param messageDir
* @param tempDir
* @return
*/
private static void tempJar(String messageDir, String tempDir, String module, URL url) {
try {
String jarPath = url.toString().substring(0, url.toString().indexOf(ResourcesConstant.JAR_FILE_SUFFIX) + ResourcesConstant.JAR_FILE_SUFFIX_LENGTH);
URL jarURL = new URL(jarPath);
JarURLConnection jarCon = (JarURLConnection) jarURL.openConnection();
JarFile jarFile = jarCon.getJarFile();
if (null != jarFile) {
File temp = tempDir(tempDir);
if (temp.exists()) {
Enumeration<JarEntry> jarEntrys = jarFile.entries();
while (jarEntrys.hasMoreElements()) {
JarEntry entry = jarEntrys.nextElement();
String name = entry.getName();
if (name.endsWith(ResourcesConstant.JAR_PACKAGE_SUFFIX) &&
name.contains(ResourcesConstant.LOCALE_BASE_JAR) &&
!entry.isDirectory()
&& name.contains(module)) {
resolveTempFilesJarNest(messageDir, tempDir, module, name);
}
}
}
}
} catch (IOException e) {
log.error(e.getMessage());
}
}

private static void resolveTempFilesJarNest(String messageDir, String tempDir, String module, String name) throws IOException {
writeAndClose(name, tempDir);
String jarName = (ResourcesConstant.JAR_FILE_PREFIX + ResourcesConstant.FILE_PREFIX + ResourcesConstant.LOCALE_URL_SUFFIX +
tempDir + name + ResourcesConstant.JAR_FILE_SUFFIX).replace(ResourcesConstant.LOCALE_URL_PREFIX, ResourcesConstant.LOCALE_URL_SUFFIX);
URL url = null;
try {
url = new URL(jarName);
} catch (MalformedURLException e) {
log.error(e.getMessage());
}
File file = resolveTempFilesJar(messageDir, tempDir, url);
compress(file, tempDir, module);
}

/**
* 压缩文件
*
* @param tempFile
* @return
*/
private static File compress(File tempFile, String tempDir, String module) {
if (tempFile.exists()) {
StringBuffer zipFilePath = new StringBuffer(tempDir);
addFileSeperator(zipFilePath);
zipFilePath.append(module).append(ResourcesConstant.ZIP_FILE_SUFFIX);
return CompressUtil.createZip(tempFile, zipFilePath.toString());
}
return null;
}

/**
* 读取jar包内的目录
* 输出到临时目录
*
* @param messageDir
* @param tempDir
* @param url
* @return
*/
private static File resolveTempFilesJar(String messageDir,
String tempDir,
URL url)
throws IOException {
String jarPath = url.toString().substring(0,
url.toString().indexOf(ResourcesConstant.JAR_FILE_SUFFIX)
+ ResourcesConstant.JAR_FILE_SUFFIX_LENGTH);
URL jarURL = new URL(jarPath);
JarURLConnection jarCon = (JarURLConnection) jarURL.openConnection();
JarFile jarFile = jarCon.getJarFile();
if (null != jarFile) {
File temp = tempDir(tempDir);
if (temp.exists()) {
Enumeration<JarEntry> jarEntrys = jarFile.entries();
while (jarEntrys.hasMoreElements()) {
JarEntry entry = jarEntrys.nextElement();
String name = entry.getName();
if (name.startsWith(messageDir) && !entry.isDirectory()) {
writeAndClose(name, tempDir);
}
}
return temp;
}
}
return null;
}

/**
* 创建临时目录
*
* @param tempDir
* @return
*/
private static File tempDir(String tempDir) {
File temp = new File(tempDir);
if (!temp.exists()) {
temp.mkdirs();
}
return temp;
}

/**
* 写入临时文件
*
* @param inputFileFullName
* @param tempDir
* @throws IOException
*/
private static void writeAndClose(String inputFileFullName, String tempDir) {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = locateStream(inputFileFullName);
outputStream = output(tempDir, inputFileFullName);
int read;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
for (int i = 0; i < read; i++) {
outputStream.write(bytes[i]);
}
}
} catch (IOException e) {
log.error("write temp file fail! ", e);
} finally {
try {
if (null != inputStream) {
inputStream.close();
}
if (null != outputStream) {
outputStream.close();
}
} catch (IOException e) {
log.error("close stream fail! ", e);
}

}
}

/**
* 创建输出流
*
* @param tempDir
* @param fileName
* @return
* @throws IOException
*/
private static OutputStream output(String tempDir, String fileName) throws IOException {
OutputStream outputStream;
StringBuffer sb = new StringBuffer(tempDir);
addFileSeperator(sb);
sb.append(fileName);
File file = new File(sb.toString());
File parent = file.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
if (!file.exists()) {
file.createNewFile();
}
outputStream = new FileOutputStream(file);
return outputStream;
}

/**
* 补目录分隔符
*
* @param dir
* @return
*/
public static String addFileSeperator(String dir) {
if (!dir.endsWith(File.separator)) {
dir += File.separator;
}
return dir;
}

/**
* 补目录分隔符
*
* @param sb
* @return
*/
public static StringBuffer addFileSeperator(StringBuffer sb) {
if (!sb.toString().endsWith(File.separator)) {
sb.append(File.separator);
}
return sb;
}


/**
* 删除目录下的所有文件
*
* @param dirName
*/
private static void deleteAnyone(String dirName) {
File file = new File(dirName);
if (file.exists()) {
if (file.isFile()) {
deleteFile(dirName);
} else {
deleteDir(dirName);
}
}
}

/**
* 删除文件
*
* @param fileName
*/
private static void deleteFile(String fileName) {
File file = new File(fileName);
if (file.exists() && file.isFile()) {
file.delete();
}
}

/**
* 删除目录
*
* @param dirName
*/
private static void deleteDir(String dirName) {
dirName = addFileSeperator(dirName);
File file = new File(dirName);
if (file.exists() && file.isDirectory()) {
if (file.listFiles() != null && file.listFiles().length > 0) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
deleteAnyone(files[i].getAbsolutePath());
}
}
file.delete();
}
}

/**
* 加载资源目录
*
* @param resourcesPath
* @return
*/
private static URL locateUrl(String resourcesPath) {
URL url = null;
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (null != loader) {
url = loader.getResource(resourcesPath);
}
if (null == url) {
url = ClassLoader.getSystemResource(resourcesPath);
}
return url;
}

/**
* 创建输入流
*
* @param fileName
* @return
*/
private static InputStream locateStream(String fileName) {
InputStream inputStream = null;
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (null != loader) {
inputStream = loader.getResourceAsStream(fileName);
}
if (null == inputStream) {
inputStream = ClassLoader.getSystemResourceAsStream(fileName);
}
return inputStream;
}

}

}

jvm2类加载器子系统与SPI

类加载器子系统分两节课讲解:类加载、类加载器

上节课已经深入讲解了类加载,这节课开始讲解类加载器

类加载器子系统 = 三层类加载器 + 双亲委派

类加载器

JVM中有两种类型的类加载器,由C++编写的及由Java编写的。除了启动类加载器(Bootstrap Class Loader)是由C++编写的,其他都是由Java编写的。由Java编写的类加载器都继承自类java.lang.ClassLoader。

JVM还支持自定义类加载器。后面会将。

各种类加载器之间存在着逻辑上的父子关系,但不是真正意义上的父子关系,因为它们直接没有从属关系。

0000056666

启动类加载器

因为启动类加载器是由C++编写的,通过Java程序去查看显示的是null

因此,启动类加载器无法被Java程序调用

启动类加载器不像其他类加载器有实体,它是没有实体的,JVM将C++处理类加载的一套逻辑定义为启动类加载器


查看启动类加载器的加载路径

1
2
3
4
URL[] urLs = Launcher.getBootstrapClassPath().getURLs();
for (URL urL : urLs) {
System.out.println(urL);
}

也可以通过-Xbootclasspath指定


从openjdk源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
int JNICALL
JavaMain(void * _args)
{
……
mainClass = LoadMainClass(env, mode, what);
……
}

static jclass
LoadMainClass(JNIEnv *env, int mode, char *name)
{
jmethodID mid;
jstring str;
jobject result;
jlong start, end;
jclass cls = GetLauncherHelperClass(env);
NULL_CHECK0(cls);
if (JLI_IsTraceLauncher()) {
start = CounterGet();
}
NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls,
"checkAndLoadMain",
"(ZILjava/lang/String;)Ljava/lang/Class;"));

str = NewPlatformString(env, name);
CHECK_JNI_RETURN_0(
result = (*env)->CallStaticObjectMethod(
env, cls, mid, USE_STDERR, mode, str));

if (JLI_IsTraceLauncher()) {
end = CounterGet();
printf("%ld micro seconds to load main class\n",
(long)(jint)Counter2Micros(end-start));
printf("----%s----\n", JLDEBUG_ENV_ENTRY);
}

return (jclass)result;
}

jclass
GetLauncherHelperClass(JNIEnv *env)
{
if (helperClass == NULL) {
NULL_CHECK0(helperClass = FindBootStrapClass(env,
"sun/launcher/LauncherHelper"));
}
return helperClass;
}

jclass
FindBootStrapClass(JNIEnv *env, const char* classname)
{
if (findBootClass == NULL) {
findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT,
"JVM_FindClassFromBootLoader");
if (findBootClass == NULL) {
JLI_ReportErrorMessage(DLL_ERROR4,
"JVM_FindClassFromBootLoader");
return NULL;
}
}
return findBootClass(env, classname);
}

JVM_ENTRY(jclass, JVM_FindClassFromBootLoader(JNIEnv* env,
const char* name))
JVMWrapper2("JVM_FindClassFromBootLoader %s", name);

// Java libraries should ensure that name is never null...
if (name == NULL || (int)strlen(name) > Symbol::max_length()) {
// It's impossible to create this class; the name cannot fit
// into the constant pool.
return NULL;
}

TempNewSymbol h_name = SymbolTable::new_symbol(name, CHECK_NULL);
Klass* k = SystemDictionary::resolve_or_null(h_name, CHECK_NULL);
if (k == NULL) {
return NULL;
}

if (TraceClassResolution) {
trace_class_resolution(k);
}
return (jclass) JNIHandles::make_local(env, k->java_mirror());
JVM_END

这套逻辑做的事情就是通过启动类加载器加载类sun.launcher.LauncherHelper,执行该类的方法checkAndLoadMain,加载main函数所在的类,启动扩展类加载器、应用类加载器也是在这个时候完成的

扩展类加载器

查看类加载器加载的路径

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
ClassLoader classLoader = ClassLoader.getSystemClassLoader().getParent();

URLClassLoader urlClassLoader = (URLClassLoader) classLoader;

URL[] urls = urlClassLoader.getURLs();
for (URL url : urls) {
System.out.println(url);
}
}

可以通过java.ext.dirs指定

应用类加载器

默认加载用户程序的类加载器

查看类加载器加载的路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
String[] urls = System.getProperty("java.class.path").split(":");

for (String url : urls) {
System.out.println(url);
}

System.out.println("================================");

URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();

URL[] urls1 = classLoader.getURLs();
for (URL url : urls1) {
System.out.println(url);
}
}

可以通过java.class.path指定

自定义类加载器

继承类java.lang.ClassLoader

具体细节见课堂上操作实战

线程上下文类加载器

类加载器创建链

上面已经讲了启动类加载器没有实体,只是将一段加载逻辑命名成启动类加载器。启动类加载器做的事情是:加载类sun.launcher.LauncherHelper,执行该类的方法checkAndLoadMain……启动类、扩展类、应用类加载器逻辑上的父子关系就是在这个方法的调用链中生成的?

1、\openjdk\jdk\src\share\classes\sun\launcher\LauncherHelper.java

核心代码:ClassLoader.getSystemClassLoader();

1
2
3
4
5
6
7
8
9
10
public enum LauncherHelper {
……
private static final ClassLoader scloader = ClassLoader.getSystemClassLoader();
……
public static Class<?> checkAndLoadMain(boolean printToStderr,
int mode,
String what) {
……
mainClass = scloader.loadClass(cn);
……

2、\openjdk\jdk\src\share\classes\java\lang\ClassLoader.java

核心代码:sun.misc.Launcher.getLauncher();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
   public static ClassLoader getSystemClassLoader() {
initSystemClassLoader();
if (scl == null) {
return null;
}
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkClassLoaderPermission(scl, Reflection.getCallerClass());
}
return scl;
}

private static synchronized void initSystemClassLoader() {
if (!sclSet) {
if (scl != null)
throw new IllegalStateException("recursive invocation");
sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
……

3、\openjdk\jdk\src\share\classes\sun\misc\Launcher.java

核心代码:

  • private static Launcher launcher = new Launcher();

  • extcl = ExtClassLoader.getExtClassLoader();

  • loader = AppClassLoader.getAppClassLoader(extcl);

  • Thread.currentThread().setContextClassLoader(loader);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Launcher {
private static URLStreamHandlerFactory factory = new Factory();
private static Launcher launcher = new Launcher();
private static String bootClassPath =
System.getProperty("sun.boot.class.path");

public static Launcher getLauncher() {
return launcher;
}

private ClassLoader loader;

public Launcher() {
// Create the extension class loader
ClassLoader extcl;
try {
extcl = ExtClassLoader.getExtClassLoader();
} catch (IOException e) {
throw new InternalError(
"Could not create extension class loader", e);
}

// Now create the class loader to use to launch the application
try {
loader = AppClassLoader.getAppClassLoader(extcl);
} catch (IOException e) {
throw new InternalError(
"Could not create application class loader", e);
}

// Also set the context class loader for the primordial thread.
Thread.currentThread().setContextClassLoader(loader);
……

4、扩展类加载器的创建流程

1
2
3
4
5
6
7
8
9
10
11
12
public static ExtClassLoader getExtClassLoader() throws IOException
{
……
return new ExtClassLoader(dirs);
……

public ExtClassLoader(File[] dirs) throws IOException {
super(getExtURLs(dirs), null, factory);
}

URLClassLoader(URL[] urls, ClassLoader parent,
AccessControlContext acc) {

第二个参数传的是null,其实就是parent=null

5、应用类加载器的创建流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static ClassLoader getAppClassLoader(final ClassLoader extcl)
throws IOException {
final String s = System.getProperty("java.class.path");
final File[] path = (s == null) ? new File[0] : getClassPath(s);

// Note: on bugid 4256530
// Prior implementations of this doPrivileged() block supplied
// a rather restrictive ACC via a call to the private method
// AppClassLoader.getContext(). This proved overly restrictive
// when loading classes. Specifically it prevent
// accessClassInPackage.sun.* grants from being honored.
//
return AccessController.doPrivileged(
new PrivilegedAction<AppClassLoader>() {
public AppClassLoader run() {
URL[] urls =
(s == null) ? new URL[0] : pathToURLs(path);
return new AppClassLoader(urls, extcl);
}
});
}

AppClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent, factory);
}

应用类、扩展类加载器的父子关系就是这样建立的

类加载器加载的类如何存储

006b

双亲委派

如果一个类加载器收到了加载某个类的请求,则该类加载器并不会去加载该类,而是把这个请求委派给父类加载器,每一个层次的类加载器都是如此,因此所有的类加载请求最终都会传送到顶端的启动类加载器;只有当父类加载器在其搜索范围内无法找到所需的类,并将该结果反馈给子类加载器,子类加载器会尝试去自己加载。

每个类加载器的搜索范围上面已经讲过了

778

打破双亲委派

因为在某些情况下父类加载器需要委托子类加载器去加载class文件。受到加载范围的限制,父类加载器无法加载到需要的文件,以Driver接口为例,由于Driver接口定义在jdk当中的,而其实现由各个数据库的服务商来提供,比如mysql的就写了MySQL Connector,那么问题就来了,DriverManager(也由jdk提供)要加载各个实现了Driver接口的实现类,然后进行管理,但是DriverManager由启动类加载器加载,只能记载JAVA_HOME的lib下文件,而其实现是由服务商提供的,由系统类加载器加载,这个时候就需要启动类加载器来委托子类来加载Driver实现,从而破坏了双亲委派。

类似这样的情况就需要打破双亲委派。

打破双亲委派的意思其实就是不委派、向下委派

自定义类加载器

SPI

是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。这一机制为很多框架扩展提供了可能,比如在Dubbo、JDBC中都使用到了SPI机制

线程上下文类加载器

1、是什么

一种特殊的类加载器,可以通过Thread获取,基于此可实现逆向委托加载

2、为什么

为了解决双亲委派的缺陷而生

3、怎么做

1
2
3
4
5
//获取
Thread.currentThread().getContextClassLoader()

// 设置
Thread.currentThread().setContextClassLoader(new Classloader_4());

沙箱安全

跟Linux的权限机制有点像

1596186739409-9de7875f-b980-40cf-a392-e7218ee1a7d8


看openjdk源码会看到有这样的判断AccessController.doPrivileged

1596186486602-8ec36a19-d6c9-4914-967c-a223ba45aafb


随便搜了一下,35个文件有80处安全判断

1596186837719-26edf8c5-2f06-489d-89cf-80ac278e51f6


比如我定义了一个类名为String所在包为java.lang,因为这个类本来是属于jdk的,如果没有沙箱安全机制的话,这个类将会污染到我所有的String,但是由于沙箱安全机制,所以就委托顶层的bootstrap加载器查找这个类,如果没有的话就委托extsion,extsion没有就到aapclassloader,但是由于String就是jdk的源代码,所以在bootstrap那里就加载到了,先找到先使用,所以就使用bootstrap里面的String,后面的一概不能使用,这就保证了不被恶意代码污染

1596186237329-9d5d9073-ce88-4836-8a5c-f6c5be51aeef

jvm1带你探索JVM底层之类加载

类加载器子系统分两节课讲解:类加载、类加载器

本节课深入讲解类加载,分四PA来讲。

课堂上会有操作实战

klass模型

Java的每个类,在JVM中,都有一个对应的Klass类实例与之对应,存储类的元信息如:常量池、属性信息、方法信息……

看下klass模型类的继承结构

img

从继承关系上也能看出来,类的元信息是存储在原空间的

普通的Java类在JVM中对应的是instanceKlass类的实例,再来说下它的三个字类

  1. InstanceMirrorKlass:用于表示java.lang.Class,Java代码中获取到的Class对象,实际上就是这个C++类的实例,存储在堆区,学名镜像类

  2. InstanceRefKlass:用于表示java/lang/ref/Reference类的子类

  3. InstanceClassLoaderKlass:用于遍历某个加载器加载的类

Java中的数组不是静态数据类型,是动态数据类型,即是运行期生成的,Java数组的元信息用ArrayKlass的子类来表示:

  1. TypeArrayKlass:用于表示基本类型的数组
  2. ObjArrayKlass:用于表示引用类型的数组

类加载的过程

类加载由7个步骤完成,看图

img

加载

1、通过类的全限定名获取存储该类的class文件(没有指明必须从哪获取)

2、解析成运行时数据,即instanceKlass实例,存放在方法区

3、在堆区生成该类的Class对象,即instanceMirrorKlass实例

程序随便你怎么写,随便你用什么语言,只要能达到这个效果即可

就是说你可以改写openjdk源码,你写的程序能达到这三个效果即可


何时加载

主动使用时

1、new、getstatic、putstatic、invokestatic

2、反射

3、初始化一个类的子类会去加载其父类

4、启动类(main函数所在类)

5、当使用jdk1.7动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getstatic,REF_putstatic,REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先出触发其初始化

预加载:包装类、String、Thread


因为没有指明必须从哪获取class文件,脑洞大开的工程师们开发了这些

1、从压缩包中读取,如jar、war

2、从网络中获取,如Web Applet

3、动态生成,如动态代理、CGLIB

4、由其他文件生成,如JSP

5、从数据库读取

6、从加密文件中读取

验证

1、文件格式验证

2、元数据验证

3、字节码验证

4、符号引用验证

准备

为静态变量分配内存、赋初值

实例变量是在创建对象的时候完成赋值的,没有赋初值一说

img

如果被final修饰,在编译的时候会给属性添加ConstantValue属性,准备阶段直接完成赋值,即没有赋初值这一步

解析

将常量池中的符号引用转为直接引用

解析后的信息存储在ConstantPoolCache类实例中

1、类或接口的解析

2、字段解析

3、方法解析

4、接口方法解析


何时解析

思路:

1、加载阶段解析常量池时

2、用的时候

openjdk是第二种思路,在执行特定的字节码指令之前进行解析:

anewarray、checkcast、getfield、getstatic、instanceof、invokedynamic、invokeinterface、invokespecial、invokestatic、invokevirtual、ldc、ldc_w、ldc2_w、multianewarray、new、putfield

初始化

执行静态代码块,完成静态变量的赋值

静态字段、静态代码段,字节码层面会生成clinit方法

方法中语句的先后顺序与代码的编写顺序相关

20到30岁

锦帕图芹烟水浅,青丝书柳午梦棉。
回身顾盼覆侬影,此地忽生并蒂莲。
明月无情不约我,自许回旋可。
酒醒梅花吹画角,翻得一场寂寞。
四顾无人,君忆玄晖我忆君。
江山如此,博得青莲心肯死。[鄙视]

饶事不分白与黑,
了却心头是和非。
我有丹心向明月,
把酒问君可展眉?欲将心事付瑶琴,知音少,弦断有谁听

20到30岁这个阶段,是人生最艰苦的一段岁月,承担着渐长的责任,拿着与工作量不匹配的薪水,艰难地权衡事业和感情,不情愿地建立人脉,好像在这个不知所措的年纪一切都那么不尽人意……
但你总得撑下去,因为此时你的能力尚配不上自己的野心。不要只因一次挫败或任性,就迷失了远方,放弃了方向。

毕业后我们丢失的三件东西

骄傲 热情 梦想!

坚韧毅力

感恩包容

责任心 积极的态度

信任 沟通

学习创新

\1. 想要看清事实,必须要经历一些疼痛。

\2. 人,一简单就快乐,但快乐的人寥寥无几;一复杂就痛苦,可痛苦的人却熙熙攘攘。

\3. 生活中大半的麻烦是由于你Yes说得太快,No说得太慢。

\4. 一个人变强大的最好方式,就是拥有一个想要保护的人。

\5. 若不尝试着做些能力之外的事,你就永远不会成长。

\6. 不论你的生活如何卑微,你要面对它生活,不要躲避它,更别用恶言咒骂它。

\7. 如果要给美好人生一个定义,那就是惬意。如果要给惬意一个定义,那就是三五知己、谈笑风生。

\8. 成熟,就是某一个突如其来的时刻,把你的骄傲狠狠的踩到地上,任其开成花或者烂成泥。

\9. 生活不会向你许诺什么,尤其不会向你许诺成功。它只会给你挣扎、痛苦和煎熬的过程。所以要给自己一个梦想,之后朝着那个方向前进。如果没有梦想,生命也就毫无意义。

积极未必是好事,瞎积极还不如不积极,优先顺序:直接领导,次要领导,其他部门领导,其他同事。

1.找人谈问题,自己内部先统一,各搞各的问题,开会怎么搞,一团糟。

2.既然部门很细,那就确认好自己责任范围内的问题,自己做,不是自己责任范围内的问题,可以了解下问题具体情况,但不要去增加自己的工作量。

3.除了直接领导,不要谁让做什么事,就想都不想就去做,看自己工作情况。

4.所有群里发言,邮件信息不要乱发,不必要知会其他部门的不要使用公共交流软件。

4.被人屌可以,后面做的让他后悔。

5.学东西可以,不要像个傻逼一样从早到晚的一直干活,没有一点自己的思考。

6.与人沟通,优先考虑方式效率与可能的成效,不只别人很忙,你自己也累的像个狗一样,还TM拿到更少的工资,提升自己能力才是主要,要是没东西可学习,趁早辞。

被拒绝100次,我终于get到一个说话小窍门!

原创 2017-10-29 佳少 秋叶PPT

Hi,我是秋小叶~

说话是一件大有学问的事。上次我们提到交流是一个你问我答的过程,分为两种: 封闭式提问和开放式提问(点击回顾)。

其中,封闭式提问,简单来说就是只需要对方回答:是,或者否。比如:吃了吗?身体还好吧?这些天项目还算顺利吗?

于是,有读者朋友留言说这没什么了不起,感觉没有技术含量。其实,商务沟通想做到恰到好处,就得靠这一个个你可能瞧不起看不上的小细节小技巧。

我们来看一个故事:

一个基督徒问牧师:我祈祷的时候,可以抽烟吗?

牧师当然是拒绝:不行,这是对主的不敬,你怎么能有这种想法!

另一个信徒问:我在抽烟的时候,也可以祈祷吗?

牧师非常欣慰地回答:当然可以,你是主的好儿女!

这个故事告诉我们,只要换一种表达方式,你可以让对方回复你预想的结果。这也是沟通带来的魅力。

那么,想要有效沟通快速解决生活中的实际问题,达到我们的预期,可以采用什么样的沟通方法呢?

提问技巧——强迫式引导

比如,你妈妈早上问你中午想吃什么,她这么问:今天中午吃炒土豆丝,还是油淋茄子?

二选一,你甚至都没有意识到她今天不准备做其他菜了。

这就是「强迫式引导」的提问技巧。

听到这样的问题,我们的一般反应是做选择题,而不去想为什么不可以有其他选项。

而一旦换成其他问句,你的反应就不一定了。

比如:你今天想吃什么?想吃土豆丝吗?(建议吃土豆丝,但不强迫)

你今天想吃什么?(先听听你的意思,咱们好商量)

所以,聪明的妈妈才不会给机会你点满汉全席呢。

言归正传,今天聊这个小技巧,是因为强迫式引导在职场往来中非常好用,特别是商务往来,只有理解了这种提问方式,你才能有效地 get things done。

强迫式引导的运用

比如,你需要和商务对象约时间,用正常方式提问:

❶ 第一种场景

提问:太好了,王总,那明天你什么时候有空,我亲自去拜访您?

实际:对方很可能第一反应是没空,啥时候有空?没准…你的工作便悬而未决。

❷ 第二种场景

提问:好的,李总,我怎么样把资料给您呢?

实际:万一对方要求你打印好跑一趟给送过去,真的要跑腿?

❸ 第三种场景

提问:好的,陈女士你什么时间在家,我们派人到你们亲自检查一下门窗安全问题?

实际:对方可能晚上 22:00 以后在家,你也能派人去?

要知道答案是不能推动思维发展的,真正能推动思维发展的是问题!你觉得以上最普遍的提问方式能够快速解决实际问题吗?显然不能!

而用强迫式引导的提问方式,结果就会显而易见了,因为对方会不自觉给你一个正向的回复!例如这样提问:

❶ 第一种场景

提问:太好了,王总,那明天下午是两点钟,还是三点钟,亲自去拜访您好呢?

❷ 第二种场景

提问:好的,李总,我是通过传真方式,还是通过邮件方式,把具体资料发送给您呢?

❸ 第三种场景

提问:好的,陈女士你是今天白天抽时间,还是明天白天抽时间,我们好派人到你们亲自检查一下门窗安全问题?

总结来说,在提问前先预设几个合适的选项,让对方来做选择题,让他的决策基于你的引导。所以,我们职场人,在商务沟通时,必须要思考两个问题。

一是我说话的目的是什么,想得到什么样结果?有的放矢才不会浪费彼此的时间。

二是我采用什么样的方式进行沟通,也就是如何表达?不同的表达方式,得到结果可能会是截然相反的。

商务沟通想做到恰到好处,让结果得到满意答复,往往靠的是一个人的专业素质

小孟:

你入职也有将近一个月了。再次欢迎你加入公司,加入我们这个团队。

近期我都会出差,无法与你面谈,所以写邮件给你。

昨天的会议上,对你太凶,这是我的不对,我首先道歉。(这个领导还是很有气度的,而且放得下架子)但是,我想你也一定做了反思,包括老吴后来肯定也跟你沟通了,你做的事情,确实有很多欠缺的地方。

这封邮件里,我想跟你说说,一方面能够给你带来提高,另一方面,花出来的时间,也算是对昨天凶你的补偿。

按你们年轻人的话说,我要开始“吐槽”你了。不过请你明白,我花时间写给你,是根据我多年工作经验来判断。诚然你很聪明,有灵性,内心单纯,是个可塑之才,努力的话还有很大的希望转正。

但我不愿看到一个好苗子,因为缺少指点,而浑浑噩噩度过职业发展中刚开始这段最重要时间。

社会险恶,人心隔肚皮。不夸张的说,你可能不会遇到比我更坦诚的领导了,我要吐槽你的桩桩件件,都是你在今后的职场中很难听到的话。(这句是实话)

原因很简单,作为领导,讲出来,会显得很官僚,会影响你们这些心理承受力不够的年轻人的积极性。甚至90后95后,有的还跟你叛逆(想想就可笑,还以为自己是青春期呢?)。同时,你还在被考察期,考试结束前,考官为什么要提示你某题的答案?

所以我接下来说的话,请你认真的记住。我也只想说这一次,毕竟,我真的很忙,你看得到的。

第一

不要问我那么多为什么

你心中有困惑,有的你直接问我,有的你不说,但执行工作的时候,我能够通过工作产出,看到你的迷惑和不情愿。

当我交给你一件事的时候,我希望的是你出色的完成它,而不是过来挑战我的判断。我知道你有想法,但是你的判断无法超越我,经验、专业度,都太嫩了。你所要做的,就是不折不扣的执行,无论你是否清楚做这件事的目的。

如果我每件事都要跟你解释清楚为什么要做它,抱歉我没有这个义务,也没有这个必要。为什么?因为你作为新人,首先就是要出色的完成任务。

多年前,在我还是一个实习生的时候,我的总监告诉我,他看我们一线员工,和老总看他们总监,是一样的。他们需要最有执行力、最能够打仗的士兵。这些士兵用着踏实,如果每次都能够出色的完成任务,那么他们下一次所得到的任务,将会更加艰巨、也更加庞大。哪怕,新任务并不是他们擅长的,但新任务需要赢,也会交给他们。(经典)

所以,不要问那么多没有必要的为什么。我觉得我需要向你解释的时候,我会跟你说,其他情况下,我很忙,没有时间跟你一一解释。

第二

不要傲气,要谦虚

说句实在的,你有什么资本可傲气的?刚到职场,什么都不会,你甚至连自信的资本都没有。难道不是吗?你就是一张白纸,任凭你想法再多。所以,当同事、前辈、领导说话的时候,不要抢话、不要插话,因为你说不对,同时还打乱了对方的思路,还不够尊重人。

工作这么多年,谦虚,是一个人能否长久成长、不断结交朋友的最关键要素。(赞同)我想,你的谦虚,就从能不能读完我写给你的这篇告白开始吧。

第三

不要只是执行

你要学会动脑子,你要了解清楚我的关注点,了解清楚这件事的核心重点,并且用最精益的办法,达成它。如果连这些你都不清楚,你的产出一定不会满足要求,更别说超出预期了。

这个社会上,能做执行的人,一抓一大把,但是只有执行前、执行时,肯动脑子的人,才有机会成为佼佼者。(不动脑的人就是廉价劳动力)

此外,执行的时候,你要考虑风险、要考虑怎么能超出预期、要想到你所做的这件事涉及到的方方面面,同时,不要自作聪明,不要自以为是。

第四

不要提前下班

听起来像资本家?为了让你加班而加班?告诉你领导们真正想的是什么。

每天下班,你走的几乎都比我早,我有两点感受:第一,心里不爽,我还在为了团队而奋斗,你竟然撤了?第二,你一个实习生,远离家乡来到北京,离开了公司又能做些啥?你该学的,该研究的东西,不都在公司里吗?你回到家以后,十有八九就是舒适圈中,应该很难有更高的工作效率吧?还有,你一个穷学生,住的地方肯定不如公司环境好,回家那么早,到底为了什么呢?

你可能一时半会儿总结不出来,我给你我的答案——你对自己没有更高的要求。拼的凶的人我见过,不超额完成工作,他们不愿意下班,不是为了拖长时间,表现给领导看,而是希望对得起自己的每一天,能够更快速的成长,才能得到重用。(想当年,星彻大叔我也是这么走过来的)

所以,看你对自己的要求有多高。

第五

不要自己吃饭、独来独往

现在的年轻人是越来越独立,好坏参半。可是独立过了,就是独来独往,就是不合群,就是不能考虑到别人的感受。我这里举例要说的,是吃饭问题。

中午同事们一起吃饭,我经常看到你一个人去吃,然后在路上又遇到部门的其他同事。

无论是因为你太忙,还是因为你不喜欢吃他们吃的东西,还是别的什么理由。我给你一个忠告。白天在公司的时候,生活和工作分不开。也就是说,你要跟大家一起吃饭,最好每天都一起吃,就算你不是每次主动的那个人,也不要特立独行。

因为在工作中,只有中午饭是最能够放松消遣、交流感情的时候。这是同事之间增进感情,促进合作默契程度的最重要的一件事。彼此的了解、认可,很大程度都建立在吃饭这件事上。(工作过的人,尤其带团队的,肯定有感触)

所以,从今天过后,习惯跟同事一起吃饭吧。

第六

不要耍大小姐脾气

社会上,你不会是少爷。

你犯懒,耽误了事儿,公司就换人。你发脾气,无论你占不占道理,都会被打上一个“脾气不好”的标签。脾气不好的人,大多数人会避而远之,而你想短时间洗掉一个标签,是相当之困难的。

即便你需要遇到一个,极度挑战你底线的、大家都看在眼里的一件事,同时,将这件事处理得极度平顺柔和,才有可能逆转这个标签。而大家给到的评价,也不过是,“他脾气‘变’好了”而已。

不要耍大小姐脾气,你想有人惯着你,回家去。在职场里,所有人到公司都是希望做好自己的工作,拿到更好的薪水,得到更大的空间。你耽误了自己,也是公司的损失,你耽误了别人,就是损人不利己了。(现在90后、95后,以为这是自己的个性)

第七

不要死板、胆小

你是公司最年轻的,天然有义务给我们一些新的想法,带给公司老同事以新鲜感和热情。为什么很多公司在持续招新人,不仅仅是因为老员工的离开,或者业务的快速扩张,也因为新人也是公司的“新鲜血液”,新鲜血液能够带来更大的组织活力。

如果你死气沉沉,每天不开心,笑的也很少,你这个“新”人,除了能力不像老员工那么强,就没什么“新”的东西了。

上面说了这么多“不要”的,接下来我想简单告诉你:我,以及像我一样的管理者,想要的是什么的实习生和下属。

\1. 在我面对面跟你交代一件事的时候,你要梳理清楚做事的重点,然后说:明白了。要说得斩钉截铁,干脆利落。

\2. 在我用微信给你交代工作的时候,你要理解任务,并且第一时间回复:收到。我心里才会踏实。

\3. 在我或者其他前辈给你讲一件事的时候,不要急于表达自己的想法。你要先全部听完,等对方讲完了,再表达你的看法或者发问。

\4. 在开会和讨论的时候,你要记下相关事宜,记在本子上,因为你不可能靠脑子记住所有的细节和灵感。

\5. 在执行工作,尤其是需要其他人配合的时候,你要多思考、多询问,没有人会讨厌好学、努力的人,只要你够谦虚,你的“老师”就会很多。

\6. 在上交工作的时候,你要超出预期,不需要每次都以达成目标为上限,但是如果你不能超出预期,你的职业发展空间,也就这样了。

(上面这一段,全部超级赞)

其实我知道你想成功,但是你不知道怎么成功,不知道问题在哪儿,着急却没有办法。

我们既然有缘共事,我既然看好你,就花点时间告诉你这些事。

成功,或者说,做一个成功的职场人事,你要做到的、要规避的,其实还是那些烂大街的条条框框,所有人都知道,只是极少有人能够做到。

做到会很累,抵抗累的办法,是自己有目标、有梦想、有科学的工作理念和方法。(一点儿不错)

小孟,加油,我们看好你!

希望你能体会我的良苦用心,作为实习生可以提升的地方还有很多,我希望见到像你这样的更多的年轻人,在他们职业生涯开端的时候,能够多虚心,听前辈的建议,少走弯路。

老孙

2017年1月

今日有酒今日醉,明日愁来明日愁