0%

文章字数:2627,阅读全文大约需要10分钟

一、责任链模式(Chain of Responsibility Pattern)

意图:创建一个处理请求的对象链,对象发送者和对象接受者解耦。责任链上的对象如果不能处理请求,就会把请求发送给下一个责任链节点。

实现:

  1. 创建责任链节点的抽象类
  2. 使用抽象类生成若干处理节点
  3. 节点依次连接,保存下一个节点的地址
  4. 当请求进入时判断是否是自己处理的类型,不是传给下一个节点。
  5. 请求发送给责任链头节点即可

二、命令模式(Command Pattern)

意图:将请求(可以是调用方法的请求)封装成一个对象,再创建一个执行类,可以向执行类中添加请求对象,然后再统一执行。执行前可以任意添加和删除命令。过程有点类似建造者模式,添加添加然后统一执行。

实现:

  1. 创建一个命令的接口,声明一个execute()执行方法
  2. 创建一个请求类,里面有若干方法。这个方法原本是直接被调用的,现在要被外面包裹成命令,然后多个命令放到一个执行类中按顺序执行。
  3. 实现命令接口,每个命令类代表不同的操作。构造方法接收一个请求类,然后在execute()方法中对于具体执行操作封装。
  4. 创建一个命令调用类,类中包含一个列表存储放入的命令类。其中主要包含
  • 命令列表(list)
  • 添加命令的方法
  • 删除命令的方法
  • 循环调用命令列表中的命令的执行方法
  • 还可以有记录执行了那些命令的方法…(可以根据记录还原)
  • 还可以加上undo()方法,用于撤销执行的命令。具体实现要结合业务。
  1. 向命令盗用类中添加若干命令,然后调用执行方法统一执行所以的命令

三、解释器模式(Interpreter Pattern)

意图:将语言或者表达式解析成具体的操作,例如sql解析,数学公式计算(符号处理引擎)等

实现:

  1. 创建表达式接口Expression,声明一个解析方法interpret
  2. 创建终结符类(不能再分割的元素)比如 1 + 2中的12都是终结符
  3. 创建非终结符(还能再被分割)1 + 2中的++号左右都可以有元素,在语法树上就是父节点,拥有左右两个子节点。而终结符就是叶子节点。
  4. 终结符和非终结符都在解析里定义好自己的功能,
    1 + 1中的终结符就是构造函数接受字符串并转化成int类型保存。
    非终结符+就是构造函数中接收两个终结符,并调用其解析方法结果相加返回
  5. 将需要解释的字符串构建成语法树,即非终结符是父节点,终结符是叶子节点的树。然后深度遍历并解析。

四、迭代器模式(Iterator Pattern)

意图: 提供一个方便的遍历集合的方法,但是不用暴露内部结构。

例子: Java中的集合迭代器

实现:

  1. 创建一个迭代器接口,内部声明hasNext()next()方法
  2. 创建一个集合类,内部构件好存储的结构,并实现迭代器接口
  3. 内部使用一个游标存储当前访问位置,int index
  4. hasNext方法返回游标是否到了结尾
  5. next方法返回当前游标所在的元素,并且游标下移。

五、中介者模式(Mediator Pattern)

用于降低对象和类之间的通信复杂性。遵循迪米特原则,即最少知道原则。
将原来网状的通信方式转换成星型的结构,所有的类都通过一个中介类进行交流。

实现:

  1. 创建一个中介类,其中有发送信息的方法
  2. 创建沟通的类,其中的发送方法使用的就是中介类的方法进行发送

六、备忘录模式(Memento Pattern)

允许获取类的内部状态,并且可以设置状态以便回复到导出时的状态。
在不破坏封装的前提下可以完成类的备份还原,可以用作游戏存档、撤销操作、历史、事务等。

实现:

  1. 创建状态的类,其中的成员变量就是从需要还原的类中提取出来的变量。
  2. 创建用于存储和获取状态的类,其中用集合保存状态类。
  3. 需要还原的类中实现提取状态和通过状态类还原的操作,提取也就是把相应的变量赋值给状态类,还原就是把状态类的信息保存到相应变量。

七、观察者模式(Observer Pattern)

订阅/发布 的模式,发布消息后会通知所有订阅了这个主题topic的类。
和中介模式的区别是这个是很明显的主体和客体的结构,一个主体发送信息,多个客体接收。
中介模式是所有的类只关心自己和中介类之间的关系,沟通全部交给中介处理。

实现(mqtt的例子):

  1. 设备连接mqtt服务器时维持连接(tcp)
  2. 设备主动订阅主题,服务器根据主题保存相应设备信息(在集合里保存观察者的信息)
  3. 主题有新的发布后推送给订阅了此主题的设备

八、状态模式(State Pattern)

意图:
允许类的内部在状态发生改变时改变他的行为
代码中有很多改变对象状态的条件语句时,可以使用状态模式将部分条件语句隐藏在类中
把类的可能出现的状态都列举并封装了

缺点:
结构较为复杂
对于开闭原则的支持不是很好,增加状态一定要修改逻辑
类会变庞大

实现:
在类中声明一个状态的属性
进行操作之前判断一下状态,然后再执行相应的动作

九、策略模式(Strategy Pattern)

策略模式就是把操作逻辑封装成不同的类,通过选择不同的类实例化就是选择不同的策略。
这种模式可以减少if...else的判断次数,逻辑清晰。
算法自由切换,并且拓展性良好
缺点是会增加代码量
spring中可以直接把类注册为组件,然后再通过名字注入。很方便就能实现

实现:
创建策略的接口,内部有具体的操作方法
创建不同的策略实现类,例如+的策略,就是把传入值相加。-的策略就是把传入值相减。
实例化策略类,并使用接口操作,执行操作方法。
因为是使用接口操作,所以策略类可以更换成其它的策略也可以正常运行

十、模板模式(Template Pattern)

意图:在抽象类中写好其它几个抽象方法直接的调用关系,具体方法让子类实现。即搭建好累的框架,细节让子类自己实现。

实现:

  1. 创建一个游戏的抽象类,内部有初始游戏、开始游戏、结束游戏三个抽象方法
  2. 增加一个final play方法,按顺序调用初始、开始、结束三个抽象方法。以指明子类的执行顺序也是这样
  3. 创建子类,实现此抽象类。实现具体的抽象方法
  4. 通过父类执行play方法

十一、访问者模式(Visitor Pattern)

意图:当一个类的数据结构很稳固,但是操作容易改变。或者类中有很多和结构无关的操作,防止这些操作改变类的数据。所以采用访问者模式进行数据和操作的分离。
有良好的拓展性,符合单一职责原则,灵活

关键:数据类中实现一个接收访问的方法,并调用访问者的访问方法,传入自身
访问者根据传入的数据类进行操作

实现:

  1. 创建一个被访问接口,内部有一个被访问的方法,入参是访问者接口
  2. 访问者接口,内部有访问的方法,入参是被访问者接口
  3. 实现接口
  4. 访问者需要访问时就直接调用被访问者的被访问方法,并使用入参操作值。

其它设计模式

空对象模式(Null Object Pattern)

意图:用一个代表空的对象代替null,空对象相对于null可以拥有默认的行为。

实现:
创建一个对象接口,有isNil和相应操作的方法
创建一个空对象,并实现isNil方法,用于判断当前方法是否为空。并赋予默认方法,例如输出当前为空
创建非空对象,实现isNil方法,并实现操作方法,如输出非空
然后就可以使用了,比如从集合中取出非空元素并执行。
-》 遍历集合,判断是否为空,并执行默认方法


文章字数:2483,阅读全文大约需要9分钟

selenium是一款Headless Browser无头浏览器。没有图形化用户界面,通常使用编程或者命令行的方式进行控制。整理自原文

环境

  1. ChromeDriver: chrome浏览器驱动,下载和浏览器对应的驱动并放到Google\Chrome\Application\目录下。
    或者

    1
    System.setProperty("webdriver.chrome.driver", "/Applications/Google Chrome.app/Contents/MacOS/chromedriver");
  2. 依赖

    1
    2
    3
    4
    5
    <dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>...</version>
    </dependency>
  3. 配置环境变量

使用

  1. 前置设置

    1
    2
    3
    4
     //设置google浏览器选项
    ChromeOptions chromeOptions = new ChromeOptions();
    //指定浏览器全屏
    chromeOptions.addArguments("--start-fullscreen");
  2. 操作封装

    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
    import com.sun.jna.platform.FileUtils;
    import org.openqa.selenium.*;
    import org.openqa.selenium.chrome.ChromeDriver;
    import org.openqa.selenium.interactions.Actions;
    import org.openqa.selenium.support.ui.ExpectedCondition;
    import org.openqa.selenium.support.ui.Select;
    import org.openqa.selenium.support.ui.WebDriverWait;

    import javax.swing.*;
    import java.io.File;
    import java.io.IOException;
    import java.util.List;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;

    /**
    * Created by moooke on 2017/8/21.
    */
    public class HelloSelenium {
    public static void main(String[] args) throws InterruptedException {
    WebDriver driver = new ChromeDriver();
    driver.get("http://www.baidu.com/");

    String title = driver.getTitle();
    System.out.println(title);

    // System.out.println("改变浏览器窗口大小");
    // Borwser(driver);

    // System.out.println("浏览器前进后退");
    // BrowserGo(driver);

    // System.out.println("浏览器元素操作");
    // BrowserOperation(driver);

    // System.out.println("模拟鼠标操作");
    // MouseOperation(driver);

    // System.out.println("模拟键盘操作");
    // KeyBoardOperation(driver);

    // System.out.println("获取断言信息");
    // Assert(driver);

    // System.out.println("设置元素等待");
    // ElementWait(driver);

    // System.out.println("定位一组元素");
    // ElementsPositioning(driver);

    // System.out.println("多表单切换");
    // SwitchTable(driver);

    // System.out.println("多窗口切换");
    // WindowsSwitch(driver);

    // System.out.println("下拉框选择");
    // SelectWindow(driver);

    // System.out.println("警告框处理");
    // AlertDemo(driver);

    // System.out.println("文件上传");
    // FileUpload(driver);

    // System.out.println("浏览器Cookie操作");
    // BorwserCookie(driver);

    // System.out.println("执行JavaScript代码");
    // JavaScript(driver);

    System.out.println("获取窗口截图");
    ScreenShot(driver);

    }


    //改变窗口大小
    private static void Borwser(WebDriver driver) throws InterruptedException {

    WebDriver driver1;
    driver1 = driver;

    driver1.manage().window().maximize();
    Thread.sleep(2000);

    // driver1.get("https://m.baidu.cn");
    driver1.manage().window().setSize(new Dimension(1200,720));
    Thread.sleep(2000);

    driver1.quit();

    }


    //前进后退
    private static void BrowserGo(WebDriver driver) throws InterruptedException{

    WebDriver driver2;
    driver2 = driver;

    //看看链接地址
    System.out.printf("now accesss %s \n", driver.getCurrentUrl());
    Thread.sleep(2000);

    //点击新闻链接
    driver2.findElement(By.linkText("新闻")).click();
    System.out.printf("now accesss %s \n", driver.getCurrentUrl());
    Thread.sleep(1000);

    //试试浏览器后退
    driver2.navigate().back();
    System.out.printf("back to %s \n", driver2.getCurrentUrl());
    Thread.sleep(1000);

    //试试浏览器往前
    driver2.navigate().forward();
    System.out.printf("forward to %s \n", driver2.getCurrentUrl());
    Thread.sleep(1000);

    //试试浏览器刷新
    driver2.navigate().refresh();
    System.out.printf("refresh broswer", driver2.getCurrentUrl());
    Thread.sleep(1000);

    driver2.quit();

    }


    //浏览器元素操作
    private static void BrowserOperation(WebDriver driver) throws InterruptedException{

    WebDriver driver3;
    driver3 = driver;

    WebElement search_text = driver3.findElement(By.id("kw"));
    WebElement search_button = driver3.findElement(By.id("su"));

    // clear() 清除文本 | sendKeys(*value) 模拟按键输入
    search_text.sendKeys("试一下输入");
    Thread.sleep(1000);
    search_text.clear();
    Thread.sleep(1000);
    search_text.sendKeys("Selenium");
    Thread.sleep(1000);
    search_button.click();
    Thread.sleep(1000);
    //sendKeys()方法模拟键盘向输入框里输入内容。我们还可以用它发送键盘按键,甚至用它来指定上传的文件。

    driver3.navigate().back();
    Thread.sleep(1000);

    //搜索到内容以后我回到百度首页,这时候要重新定位元素,不然会报错
    WebElement search_text2 = driver3.findElement(By.id("kw"));
    WebElement search_button2 = driver3.findElement(By.id("su"));

    search_text2.sendKeys("Java");
    search_text2.submit();
    Thread.sleep(1000);
    search_text2.submit();
    Thread.sleep(1000);
    //submit()方法用于提交表单。例如,在搜索框输入关键字之后的“回车” 操作,就可以通过 submit()方法模拟.

    //getSize()
    //getText()
    //getAttribute(name) 获取属性值
    //isDisplayed() 设置元素是否用户可见
    System.out.println("输入框尺寸:" + search_text2.getSize());
    System.out.println("提交按钮尺寸:" + search_button2.getSize());
    System.out.println("提交按钮文本:" + search_button2.getText());
    System.out.println("输入框id:" + search_text2.getAttribute("id") +
    " 输入框Type:" + search_text2.getAttribute("Type"));
    System.out.println("输入框是否可见:" + search_text2.isDisplayed());

    driver3.quit();

    }


    //鼠标操作
    /**
    * 在WebDriver中,这些关于鼠标操作的方法封装在ActionChains类中:
    * ⬇️⬇⬇️
    * contextClick() 右击
    * clickAndHold() 鼠标点击并控制
    * doubleClick() 双击
    * dragAndDrop() 拖动
    * release() 释放鼠标
    * perform() 执行所有Actions中存储的行为,可以理解成是对整个操作的提交动作
    */
    private static void MouseOperation(WebDriver driver) throws InterruptedException{

    WebDriver driver4;
    driver4 = driver;

    //找到百度首页设置按钮,并悬停在按钮上
    WebElement search_setting = driver4.findElement(By.linkText("设置"));
    Actions action = new Actions(driver4);
    action.clickAndHold(search_setting).perform();
    Thread.sleep(3000);

    // //鼠标右键点击指定元素
    // action.contextClick(driver4.findElement(By.id("kw"))).perform();
    // action.click(driver4.findElement(By.id("kw"))).perform();
    // Thread.sleep(2000);

    //鼠标双击指定的元素
    action.doubleClick(driver4.findElement(By.id("su"))).perform();
    Thread.sleep(2000);

    //鼠标拖拽动作,将 search_setting 元素拖放到 search_text 元素的位置
    WebElement search_text = driver4.findElement(By.id("kw"));
    WebElement search_setting2 = driver4.findElement(By.linkText("设置"));
    action.dragAndDrop(search_setting2, search_text).perform();
    Thread.sleep(2000);

    //释放鼠标
    action.release().perform();

    driver4.quit();

    //PS:这里我发现 search_setting 被操作以后如果我在后面的 dragAndDrop 中直接
    // 使用 search_setting 会报错,但是我重新建立一个对象就不会报错 -..-
    }


    //键盘操作
    /**
    * 可以模拟键盘按键
    * 以及组合键,例如 Ctrl+A、 Ctrl+C 等
    * 键盘操作都放在 org.openqa.selenium.Keys 里
    * ⬇️⬇⬇️
    * (Keys.BACK_SPACE) 回格键
    * (Keys.SPACE) 空格键(Space)
    * (Keys.TAB) 制表键(Tab)
    * (Keys.ESCAPE) 回退键(Esc)
    * (Keys.ENTER) 回车键(Enter)
    * (Keys.F1) 键盘 F1
    * ...
    * (Keys.F12) 键盘 F12
    */
    private static void KeyBoardOperation(WebDriver driver) throws InterruptedException{

    WebDriver driver5;
    driver5 = driver;

    WebElement input = driver5.findElement(By.id("kw"));

    //输入下准备数据
    input.sendKeys("Seleniumm");
    Thread.sleep(2000);

    //按下删除键,删除一个 "m"
    input.sendKeys(Keys.BACK_SPACE);
    Thread.sleep(2000);

    //输入空格键
    input.sendKeys(Keys.SPACE);
    input.sendKeys(" + Java");
    Thread.sleep(2000);

    //模拟 Ctrl + a ,全选
    input.sendKeys(Keys.CONTROL, "a");
    Thread.sleep(2000);

    //模拟 Ctrl + x ,剪切
    input.sendKeys(Keys.CONTROL, "x");
    Thread.sleep(2000);

    //模拟 Ctrl + v ,粘贴
    input.sendKeys(Keys.CONTROL, "v");
    Thread.sleep(2000);

    //模拟回车键
    input.sendKeys(Keys.ENTER);
    Thread.sleep(2000);

    driver5.quit();
    }


    //获取页面元素
    private static void Assert(WebDriver driver) throws InterruptedException{

    WebDriver driver6;
    driver6 = driver;

    //获取当前的 title 和 url
    System.out.printf("title of current page is %s\n", driver6.getTitle());
    System.out.printf("url of current page is %s\n", driver6.getCurrentUrl());

    //百度搜索
    WebElement search = driver6.findElement(By.id("kw"));
    search.sendKeys("Selenium");
    search.sendKeys(Keys.ENTER);
    Thread.sleep(2000);

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

    //获取当前的 title 和 url 看看
    System.out.printf("title of current page is %s\n", driver6.getTitle());
    System.out.printf("url of current page is %s\n", driver6.getCurrentUrl());
    Thread.sleep(2000);

    //获取第一条搜索结果的标题
    WebElement result = driver6.findElement(By.xpath("//*[@id=\"1\"]/h3/a"));
    System.out.println(result.getText());
    Thread.sleep(2000);

    driver6.quit();
    }


    //设置页面元素等待
    private static void ElementWait(WebDriver driver) throws InterruptedException{

    WebDriver driver7;
    driver7 = driver;

    //显示等待,针对某个元素
    /**
    * WebDriverWait(driver, 10, 1)
    * driver: 浏览器驱动。 10: 最长超时时间, 默认以秒为单位。 1: 检测的的间隔(步长) 时间, 默认为 0.5s
    */
    WebDriverWait wait = new WebDriverWait(driver7, 10,1);

    wait.until(new ExpectedCondition<WebElement>() {
    @Override
    public WebElement apply(WebDriver webDriver) {
    return webDriver.findElement(By.id("kw"));
    }
    }).sendKeys("Selenium");

    driver7.findElement(By.id("su")).click();
    Thread.sleep(2000);

    // driver7.quit();

    //隐式等待
    /**
    * WebDriver提供的几种方法
    * 1. implicitlyWait (识别对象时的超时时间,过了这个时间如果对象还没找到的话就会抛出NoSuchElement异常)
    * 2. setScriptTimeout (异步脚本的超时时间,WebDriver可以异步执行脚本,这个是设置异步执行脚本脚本返回结果的超时时间)
    * 3. pageLoadTimeout (页面加载时的超时时间,因为WebDriver会等页面加载完毕再进行后面的操作,所以如果页面超过设置时间依然没有加载完成,那么WebDriver就会抛出异常)
    */
    //页面加载超时时间设置为 5s
    driver7.manage().timeouts().pageLoadTimeout(5, TimeUnit.SECONDS);
    driver7.get("https://www.baidu.com/");

    //每一个隐式等待都只对下一个对应的 driver 操作有效
    driver7.manage().timeouts().pageLoadTimeout(5, TimeUnit.SECONDS);
    driver7.get("https://www.google.com");

    //定位对象给定 3s 的时间,如果 3s 内没有定位到则抛出异常
    driver7.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    driver7.findElement(By.id("kw")).sendKeys("selenium");
    Thread.sleep(2000);

    //异步脚本的超时时间设置为 3s
    driver7.manage().timeouts().setScriptTimeout(3, TimeUnit.SECONDS);

    driver7.quit();
    }


    //定位『一组』元素
    /**
    * 定位一组元素其实就类似于定位元素,只不过用的方法是 findElements ,多一个 "s"
    */
    private static void ElementsPositioning(WebDriver driver) throws InterruptedException {

    WebDriver driver8;
    driver8 = driver;

    WebElement search_text = driver8.findElement(By.id("kw"));
    search_text.sendKeys("Selenium");
    search_text.submit();
    Thread.sleep(2000);

    /**
    * 通过 xpath ,我们找到匹配到的第一页搜索结果 循环打印
    * 这里打印的是第一页搜索的搜索结果,因为搜索结果展示都可以通过 //div/div/h3 定位到
    */
    List<WebElement> search_result = driver8.findElements(By.xpath("//div/div/h3"));

    //打印元素的个数
    System.out.println(search_result.size());

    //循环打印搜索结果的标题
    for (WebElement result : search_result){
    System.out.println(result.getText());
    }

    System.out.println("-------- *..* --------");

    //打印第 n 结果的标题
    WebElement text = search_result.get(search_result.size() - 10);
    System.out.println(text.getText());

    driver8.quit();
    }


    //多表单切换
    /**
    * WebDriver 只能在一个页面上对元素识别与定位,但是对于 frame/iframe 表单内嵌页面上的元素无法直接定位
    * 这时就需要通过 switchTo().frame()方法将当前定 位的主体切换为 frame/iframe 表单的内嵌页面中
    * iframe 基本已经被h5淘汰,不过我们还是要了解一下,以126邮箱登录为例
    */
    private static void SwitchTable(WebDriver driver) {

    WebDriver driver9;
    driver9 = driver;

    driver9.get("http://www.126.com");

    //这里等待 5s ,因为 iframe 的创建比其它包括 scripts 和 css 的 DOM 元素的创建要慢 1-2 个数量级
    driver9.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
    WebElement frame = driver9.findElement(By.xpath("//*[@id='loginDiv']/iframe"));
    driver9.switchTo().frame(frame); //switchTo 还可以切换到弹出框等

    driver.findElement(By.name("email")).clear();
    driver.findElement(By.name("email")).sendKeys("username");
    driver.findElement(By.name("password")).clear();
    driver.findElement(By.name("password")).sendKeys("password");
    driver.findElement(By.id("dologin")).click();

    //切换回默认页面
    driver.switchTo().defaultContent();

    }


    //多窗口切换
    /**
    * getWindowHandle(): 获得当前窗口句柄
    * getWindowHandles(): 返回的所有窗口的句柄到当前会话
    * switchTo().window(): 用于切换到相应的窗口,与上面的switchTo().frame()类似
    */
    private static void WindowsSwitch(WebDriver driver) throws InterruptedException {

    WebDriver driver10;
    driver10 = driver;

    //获得当前窗口句柄
    String search_handle = driver10.getWindowHandle();

    //打开百度注册窗口
    driver10.findElement(By.linkText("登录")).click();
    Thread.sleep(2000);
    driver10.findElement(By.linkText("立即注册")).click();
    Thread.sleep(2000);

    //获得当前窗口的句柄
    String search_handle_register = driver10.getWindowHandle();

    //获取所有窗口句柄
    Set<String> handles = driver10.getWindowHandles();

    //判断是否为注册窗口, 并操作注册窗口上的元素
    for (String handle : handles){
    if (handle.equals(search_handle_register) == false){
    driver10.switchTo().window(handle);
    System.out.println("现在在注册页面");
    Thread.sleep(2000);
    driver10.findElement(By.name("userName")).clear();
    driver.findElement(By.name("userName")).sendKeys("用户名");
    driver.findElement(By.name("phone")).clear();
    driver.findElement(By.name("phone")).sendKeys("电话号码");
    //......
    Thread.sleep(2000);
    //关闭当前窗口
    driver10.close();
    }
    }
    Thread.sleep(2000);

    driver10.quit();
    }


    //下拉框选择
    /**
    * WebDriver提供了 Select 类来处理下拉框
    * Select类用于定位<select>标签。selectByValue()方法符用于选取<option>标签的value值
    */
    private static void SelectWindow(WebDriver driver) throws InterruptedException {

    WebDriver driver11;
    driver11 = driver;

    //以百度搜索设置页面的下拉框为例
    driver11.findElement(By.linkText("设置")).click();
    driver11.findElement(By.linkText("搜索设置")).click();
    Thread.sleep(2000);

    //<select>标签的下拉框选择
    WebElement el = driver11.findElement(By.xpath("//select"));
    Select sel = new Select(el);
    sel.selectByValue("20");
    Thread.sleep(2000);

    driver11.quit();
    }


    //警告框处理
    /**
    * 在WebDriver中处理JavaScript所生成的alert、confirm以及prompt
    * 1. 使用switchTo().alert()方法定位到alert/confirm/prompt
    * 2. 使用text/accept/dismiss/sendKeys等方法进行操作
    * -----------------------------------------------
    * getText(): 返回 alert/confirm/prompt 中的文字信息
    * accept(): 接受现有警告框
    * dismiss(): 解散现有警告框
    * sendKeys(keysToSend): 发送文本至警告框
    * keysToSend: 将文本发送至警告框
    */
    private static void AlertDemo(WebDriver driver) throws InterruptedException {

    WebDriver driver12;
    driver12 = driver;

    //类似百度设置的弹出框是不能通过前端工具对其进行定位的,这时候就要用到switchTo().alert()了
    driver.findElement(By.linkText("设置")).click();
    driver.findElement(By.linkText("搜索设置")).click();
    Thread.sleep(2000);

    //点击保存设置
    driver12.findElement(By.linkText("保存设置")).click();

    System.out.println(driver12.switchTo().alert().getText());

    //接收弹框
    driver12.switchTo().alert().accept();
    Thread.sleep(2000);

    driver12.quit();
    }


    //文件上传 *
    /**
    * 对于通过input标签实现的上传功能,可以将其看作是一个输入框,可通过sendKeys()指定本地文件路径的方式实现文件上传
    */
    private static void FileUpload(WebDriver driver) throws InterruptedException {

    WebDriver driver13;
    driver13 = driver;

    //找到绝对路径
    File file = new File(" ./xxx(路径)/xxx(路径)/文件");
    String filePath = file.getAbsolutePath();
    driver13.get(filePath);

    //定位上传按钮,添加本地文件
    driver13.findElement(By.name("file")).sendKeys("E:\\\\upload_file.txt");
    Thread.sleep(2000);

    driver13.quit();
    }


    //浏览器Cookie操作
    /**
    * WebDriver操作Cookie相关方法
    * getCookies(): 获得所有cookie信息
    * getCookieNamed(String name): 返回字典的key为"name"的Cookie信息
    * addCookie(cookie dict): 添加Cookie, "cookie dict"指字典对象,必须有 name和 value值
    * deleteCookieNamed(String name): 删除Cookie信息, "name"是要删除的 cookie的名称; "optionsString"是该Cookie 的选项, 目前支持"路径"、"域"
    * deleteAllCookies(): 删除所有的cookie 信息
    */
    private static void BorwserCookie(WebDriver driver) {

    WebDriver driver14;
    driver14 = driver;

    Cookie cookie1 = new Cookie("name", "key-aaaaa");
    Cookie cookie2 = new Cookie("value", "value-bbbbb");
    driver14.manage().addCookie(cookie1);
    driver14.manage().addCookie(cookie2);

    //获得 Cookie
    Set<Cookie> cookies = driver14.manage().getCookies();
    System.out.println(cookies);

    //删除所有 cookie
    //driver.manage().deleteAllCookies();
    driver14.quit();
    }


    //调用JavaScript代码
    /**
    * WebDriver提供了 executeScript()方法来执行 JavaScript代码
    * 以调整浏览器滚动条位置为例
    */
    private static void JavaScript(WebDriver driver) throws InterruptedException {

    WebDriver driver15;
    driver15 = driver;

    //设置浏览器窗口大小
    driver15.manage().window().setSize(new Dimension(700, 600));
    Thread.sleep(2000);

    //百度搜索
    driver15.findElement(By.id("kw")).sendKeys("Selenium");
    driver15.findElement(By.id("su")).click();
    Thread.sleep(2000);

    //将页面滚动条拖动
    ((JavascriptExecutor)driver15).executeScript("window.scrollTo(100,410)");
    Thread.sleep(200);
    ((JavascriptExecutor)driver15).executeScript("window.scrollTo(100,420)");
    Thread.sleep(200);
    ((JavascriptExecutor)driver15).executeScript("window.scrollTo(100,430)");
    Thread.sleep(200);
    ((JavascriptExecutor)driver15).executeScript("window.scrollTo(100,440)");
    Thread.sleep(200);
    ((JavascriptExecutor)driver15).executeScript("window.scrollTo(100,450)");
    Thread.sleep(200);

    driver15.quit();
    }


    //窗口截图
    private static void ScreenShot(WebDriver driver) {

    WebDriver driver16;
    driver16 = driver;

    File srcFile = ((TakesScreenshot)driver16).getScreenshotAs(OutputType.FILE);
    try {
    org.apache.commons.io.FileUtils.copyFile(srcFile, new File("/Users/moooke/screenshot.png"));
    } catch (IOException e) {
    e.printStackTrace();
    }

    driver16.quit();
    }
    }

文章字数:3504,阅读全文大约需要14分钟

分布式特点

  1. 分布性,硬件或软件组件分布在不同网络机器上,彼此间仅仅通过消息传递进行通信和协调的系统
  2. 对等性,服务冗余,微服务有多个副本,彼此直接完全一样
  3. 并发性,
  4. 缺乏全局时钟,每个节点都有自己的本地时间(使用共同的时间服务器解决)
  5. 故障随时发生

分布式系统问题

  1. 通讯异常, 节点间网络异常,会导致脑裂。(多个master)
  2. 网络分区
  3. 三态,正确、错误、超时三种状态。
  4. 节点故障

CAP

C 一致性,数据在多个副本中一致(强一致性只能将数据放在一个节点上)
A 可用, 请求总能得到返回
P 分区容错性(冗余数据),除非整个网络故障,分布式系统在任何网络或节点故障时,仍然能满足一致性(最终一致)和可用的服务

AC,放弃P|数据放在一个节点上,充分保证了一致性和系统可用性,放弃拓展性(P)。放弃分区一致性就不是分布式了
PC,放弃A|当节点故障或网络故障时,受到影响的服务需要等一定时间,等待时间内无法提供服务。一般不会这么做
AP,放弃C|无法保证实时一致,承诺最终一致。

BASE

即使无法做到强一致性,但分布式系统可以根据业务特点,采用适当方式达到最终一致性

  • Basically Avaliable基本可用,当分布式系统出现不可预见故障时,允许损失部分可用性,保障系统基本可用。例如双十一高峰,部分用户会出现页面卡顿或降级处理(换成功能没这么强的服务·)。
  • Soft state软状态,允许系统中的数据存在中间状态,即系统的不同节点数据副本间数据同步存在延时,并认为延时不影响系统可用性。例如买票的正在抢票
  • Eventually consistent最终一致,所有数据经过一段时间的数据同步,最终达到一个一致状态。

分布式一致性算法

算法 说明
2p 两段提交,数据库分布式事务常用。算法简单,容易出现阻塞。某些情况下不一致
3p 对于2p的改进,三段提交,完善了阻塞以及可用性。2p,3p都属于强一致性算法。
paxos算法 两个阶段,少数服从多数。并不需要所有参与者都同一某一协议
zab 借鉴paxos思路,zookeeper解决分布式一致性的算法

zookeeper

高性能,高可用,严格顺序访问控制能力的分布式协调服务。是hadoop和Hbase重要组件

  • 简单数据结构,共享的树形结构,类似文件系统,存储与内存
  • 可构建集群,避免单点故障,3-5台机器就可用组成集群,超过半数正常工作就能对外提供服务
  • 顺序访问,每个写请求,zk会分配一个全局唯一的递增编号,利用这个特性可用实现高级协调服务
  • 高性能,基于内存操作,服务于非事务请求,适用于读操作为主的业务请求。3台kz集群能达到13w QPS

使用场景

  1. 发布订阅
  2. 负载均衡(客户端负载均衡)
  3. 命名服务,注册中心
  4. Master选举
  5. 集群管理,检测集群节点是否健康
  6. 配置管理,配置中心
  7. 分布式队列
  8. 分布式锁

Zookeeper

序号 参数名 说明
7 snapCount 设置多少次事务日志输出后,触发一次快照(snapshot),此时ZK会生产一个snapshot.*文件,同时创建一个新的事务日志文件log.*,默认100000,真实实现会增加一定的随机数,避免所有服务器同一时间快照影响性能

节点

  • create /aaa val创建节点aaa并赋予值val。节点必须有值,否则不能创建

  • zk视图结构和标准unix文件系统类似,从/根节点出发。

  • 节点成为ZNode,每个节点可存储数据,也可以挂载子节点。因此可以成为树

  • 节点类型(不同类型节点名也不能重复)

  1. 持久节点,和客户端连接,断开后数据还在(ZNode
  2. 临时节点,和客户端断开后,数据不在
  3. 顺序节点,临时节点和持久节点都能创建顺序节点,每次创建节点名都会自动递增(名字+自动生成的序列)

节点状态属性

序号 属性 数据结构 描述
1 czxid long 节点被创建的Zxid
2 mzxid long 节点被修改的Zxid
3 paxid long 节点最后一次被修改时的事务ID
4 ctime long 节点被创建的时间
5 mtime long 节点最后一次被修改时间
6 dataVersoin long 节点被修改的版本号(每次修改+1)(CAS保证分布式数据原子性)
7 cversion long 节点所拥有子节点被修改的版本号
8 aversion long 节点的ACL被修改的版本号
9 emphemeralOwner long 如果此阶段为临时节点,这个值就是节点拥有者会话ID,否则0
10 dataLength long 节点数据域长度
umChildren long 节点拥有的子节点个数

ACL

  • getAcl /xxx查看xxx的权限

    1
    2
    'world',anyone
    :cdrwa
  • scheme授权机制, id用户id给谁授权, permissions权限,只读、读写、管理等。

    • create(c)
    • delete(d)
    • read(r)
    • write(w)
    • admin(a) 是否能给子节点设置权限

    机制有

  • world,下面只有一个id,叫anyone, world:anyone代表任何人,ZK中对搜有人有权限的节点就是属于world:anyone

  • auth, 它不需要id, 只需要通过authenticationuser都有权限。ZK支持通过kerberos来进行authencation,也支持username/password形式的authentication(明文)

  • digest, 通过对应的id为username:BASE64(SHA1(password)), 它需要先通过username:password形式的authentication(密文)

  • ip, 它对应的id为客户机的IP地址,设置的时候可以设置一个ip段,比如ip:192.168.1.0/16,表示匹配16bitIP

常用ACL命令

  • getAcl获取指定节点的ACL信息

  • setAcl设置指定节点的ACL信息

    1
    2
    3
    addauth digest username:pwd # 添加用户(会话级别的,退出需要重新操作)
    setAcl /xxx/zzz auth:username:pwd:crwa #给用户添加 auth机制的crwa权限
    setAcl /xxx/zzz digest:username:xxxxmd5:crwa #digest机制的权限添加,密文生产在zookeeper自带的java类 DigestAuthenticationProvider里
  • addauth注册绘画授权信息

  • 注册超级管理员用户可以解决没有权限不能删除的问题

使用

  1. zkCli.sh -server ip连接ZooKeeper服务,连接成功后系统会输出相关环境及配置
  2. 基本操作
    • 显示根目录下、文件:ls / 查看当前ZooKeeper包含的内容
    • 显示根目录下、文件:ls2 /查看当前节点数据并能看到更新次数等数据
    • 创建文件,并设置初始内容。create /zk "val" 创建一个新的znode节点zk ,以及初始化内容 -e 临时节点(客户端端口就删除) -s 顺序节点(名字自增)
    • 获取内容get /zk 确认znode是否包含我们所创建的字符串
    • 修改set /zk "val2"修改节点内容
    • 删除delete /zk将指定znode删除,如果有子节点,删除失败
    • 递归删除rmr /zk删除节点及子节点
    • 退出quit

四字命令

zk支持使用某些特点四字的命令交互获取服务当前状态,可通过telnetnc提交命令

  1. echo stat|nc ip port查看那个节点被选择作为follower或者leader
  2. 使用echo ruok|nc ip port测试是否启动了该server若回复imok表示已经启动
  3. echo dump|nc ip port列出未经处理的会话和临时节点
  4. echo kill |nc ip port关闭server
  5. echo conf | nc ip port输出相关服务配置的详细信息
  6. echo cons | nc ip port列出所有连接到服务器的客户端完全的连接/会话的详细信息
  7. echo envi|nc ip port输出关于服务环境的详细信息
  8. echo reqs|nc ip port列出未经处理的请求
  9. echo wchs|nc ip port列出服务器watch的详细信息
  10. echo wchc|nc ip port通过session列出服务器的watch详细信息,输出的是一个与watch相关会话的列表
  11. echo wchp|nc ip port通过路径列出服务器的watch的详细信息,输出的是与session相关的路径

可视化

  1. 事务日志可视化LogFormatter

    1
    java -cp ../../zookeeper-3.4.5.jar;../../lib/slf4j-api-1.6.1.jar org.apache.zookeeper.server.logFormatter log.xxx
  1. 数据快照可视化SnapshotFormatter

    1
    java -cp ../../zookeeper-3.4.5.jar;../../lib/slf4j-api-1.6.1.jar org.apache.zookeeper.server.SnapshotFormatter snapshot.xxx

一致性原理

2pc

2pc 两段提交,强一致性算法。常用于分布式数据库中。

  • 术语
  1. undo记录原始数据,用于回滚。
  2. redo正常提交数据
  • 流程

    1. 第一阶段,所有资源数据库都写入undoredo到事务日志
      1. 第二阶段,所有资源都返回ok,则全部执行commit,否则rollback
  • 缺点

    1. 同步阻塞,所有都成功才能成功。
      1. 单点故障,一个返回失败,都失败
      2. 数据不一致,网络延迟导致一个资源commit了,另一个没有commit
      3. 容错机制不完善,一个失败都失败

3pc

先询问资源是否可以访问再进行2pc相同步骤

不一样的是第三阶段协调者如果网络超时或异常,参与者也会commit

优点

1. 改善同步阻塞(不会因为某些访问超时占用时间)
   2. 解决单点故障

paxos算法

少数服从多数,角色轮换避免单点故障

第一阶段,提议者订一个K值,然后访问所有资源(prepare请求),多数回应ok就进行下一阶段,否则k+1再重新请求

第二阶段, 提交数据,绝大部分返回ok则整体成功,否则重新进行第一阶段

问题

  1. 主导者故障(单点故障)
  2. 最终一致性

协议要求

  1. 资源端必须接受第一个prepare
  2. 第一个prepare的数据必须要接受

多提议者情况下(解决单点故障)

若干提议者发起prepare,若多数资源同意则进入下一阶段。若同意没超过半数,则k增加再进行prepare。资源会同意更高K的prepare。当提议者认为自己的支持者超过半数就会进行第二阶段,

提交accept,如果资源在次期间遇到更高k的prepare,则会拒绝当前accept,等待最高k发起的提议者的accept。accept接受超过半数则成功,否则k增加,重新prepare。成功后全体接受成功的accept。

ZK使用

Zookeeper原生客户端

1
2
3
4
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
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
private final static String CONNECT = "192.168.1.1:8088,xxxx";// 多个用逗号隔开
private static CountDownLatch cdl = new CountDownLatch(1);
ZooKeeper zk = new ZooKeeper(CONNECT, 5000, new Watch(){// 5000超时
public void process(WatchedEvent watchedEvent) {
// 如果获取到了连接
if(watchedEvent.getState() == Event.keeperState.SyncConnected) {
countDownLatch.countDown();
}
}
});

countDownLatch.watch();//等待连接
zookeeper.create("/path", "val".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
Stat stat = new Stat();// 节点状态
// watch为true代表监听此节点,节点内容发生变化会回调连接时注册的watch。watch是一致性的
// watch之后只会返回当前session最后一次修改此节点的内容,即多个setData,只会最后一次回调
byte[] data = zookeeper.getData("/path", true, stat);// 返回值

List<String> childrens = zookeeper.getChildren("/path", true);//[a,b,c]的形式返回子节点

ACL acl = new ACL(ZooDefs.Perms.ALL, new Id("digest", DigestAuthenticationProvicer.generateDigest("root:root")));
ACL acl2 = new ACL(ZooDefs.Perms.CREATE, new Id("ip", "192.168.1.1"));
List<ACL> acls = new ArrayList<>();
acls.add(acl);
acls.add(acl2);
// 创建持久节点
zookeeper.create("path", "val".getBytes(), acls, CreateMode.PERSISTENT);
// 添加digest方案的权限
zookeeper.addAuthInfo("digest", "root:root".getBytes());

问题

  1. 会话连接是异步的
  2. watch需要重复注册,一次watch只能监听一个
  3. 缺少session重连机制
  4. 复杂,缺少很多功能,例如级联新增

ZkClient

1
2
3
4
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
</dependency>
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
private final static String CONNECT_HOST = "192.168.1.1:8000";
// zkClient不用监听
ZkClient zkClient = new ZkClient(CONNECT_HOST, 4000);
// 提供了递归创建父节点的功能,true代表级联新增,false代表不允许(父节点不存在就会报错)
zkClient.createPersistent("/zk/zkclient/zkclient1", true);
// 获取子节点 [node1,node2,node3]
List<String> list = zkClient.getChildren("/zkclient");
// 监听
// 节点内容修改
zkClient.subscribeDataChange("/nodeName", new IZkDataListener() {
public void handleDataChange(String nodeName, Object newVal) throws Exception {
// nodeName节点名称 newVal修改后的值
}

public void handleDataDeleted(String nodeName) throws Exception {
// ...
}
});

// nodeName中的子节点发升变化触发
zkClient.subscribeChildChanges("/nodeName", new IZkChildListener()) {
public void handleChildChange(String nodeName, List<String> list) throws Exception {
// nodeName节点名 list节点列表
}
}
// 监听器
// subscriptStateChanges
// 权限
public void addAuthInfo(String scheme, final byte[] auth);
public void setAcl(final String path, final List<ACL> acl);

Curator

1
2
3
4
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
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
private final static String CONNECT_HOST="192.168.1.1:8000";
// 尝试三次连接,失败1000毫秒后重试,第二次重试时间2*1000毫秒,第三次3*1000
CuratorFramework curatorFramework = CuratorFrameworkFactory.
newCliebt(CONNECT_HOST, 5000, 5000, new ExponentialBackoffRetry(1000, 3));
curatorFramework.start();// 启动连接

// 另一种写法
CuratorFramework curatorFramework = CuratorFrameworkFactory.builder().connectString(CONNECT_HOST).sessionTimeoutMs(5000).retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
curatorFramework.start();// 启动连接
// 创建节点,返回节点路径
String val = curatorFramework.create()
.createingParentsIfNeeded()//级联创建父节点
.withMode(CreateMode.PERSISTENT)//持久节点
.forPath("/path/path1/path2", "val".getBytes());
// 删除节点,级联删除
curatorFramework.delete().deleteChildrenIfNeed().forPath("/path");

// 异步执行
final CountDownLatch countDownLatch = new CountDownLatch(1);
ExcutorService service = Executors.newFixedThreadPool(1);
curatorFramework.create().createingParentsIfNeeded().withMode(CreateMode.PERSISTENT)
.inBackground(new BackgroundCallback(){
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throw Exception {
curatorFramework.getResultCode();// 结果
curatorFramework.getType();
countDownLatch.countDown();
}
},server).forPath("/path/path1/path2", "val".getBytes());
// 事务, 同时成功才成功
Collection<CuratorTransactionResult> resultCollections = curatorFramework.inTransaction()
.create().forPath("/path/path1/path2", "val".getBytes()).and()
.setData().forPath("/path/path1/path2", "v1".getBytes()).and().commit();

for(CuratorTransactionResult res: resultCollections) {
res.getForPath();// 节点路径
res.getType();// 结果
}

// watch机制
// Pathcache 监听一个路径下子节点的创建、删除、数据更新
// NodeCache 节点的创建、删除、更新
// TreeCache Pathcache+NodeCache
NodeCache nodeCache = new NodeCache(curatorFramework, "/curator", false);
nodeCache.start(true);
nodeCache.getListenable().addListener(()->System.out.println("节点变化,变成了" + new String(nodeCache.getCurrentData().getData())));

pathCache.getListenable().addListener((framework, event)->{
event.getType();//CHILD_ADD CHILD_REMOVED CHILD_UPDATE 子节点增加、删除、更新
});

集群

特点

  1. 顺序一致性,命令执行顺序一致
  2. 原子性,集群中所有机器都成功,否则失败
  3. 单一视图,连接集群任意一个机器数据一致
  4. 可靠性,一个更新被操作之前,数据不变
  5. 实时性,一个节点更改,其他节点很短时间内同步
  6. 角色轮换,避免故障

角色

  1. leader任务调度,事务处理(增,删,改)
  2. follower非事务请求,读。参与投票
  3. observer观察者,读,不参与投票。(3.30以上提供,增加效率)

配置集群

zoo.cfg

1
2
3
server.0=192.168.1.2:2333:2444 # 选举端口:通讯端口
server.1=192.168.1.3:2333:2444 # 1代表 myid ,集群名称,必须是数字
server.2=192.168.1.4:2333:2444

ZAB协议

类似paxos,zk自己实现的协议


文章字数:1278,阅读全文大约需要5分钟

一个用于整合不同功能的工具,在指定的包里创建功能类,并声明分类名称、功能名称、参数名称。就能自动生成调用菜单,是小工具的通用入口。

注解

  • 创建包com.colin.tool.invokeableAnnotation
  • 使用三个注解区分不同功能
  • categoryInfo注释在类上,表示类下的所有方法属于什么分类
  • functionInfo注释在方法上,表示该方法的名称及详细信息(输入帮助时展示)
  • paramName注释在方法参数,参数名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.colin.tool.invokeableAnnotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* 用于注释类的分类名
*
* @author colin.cheng
* @date 2021-12-09 10:03
* @since 1.0.0
*/
@Retention(RetentionPolicy.RUNTIME) //运行环境可用
@Target({ElementType.TYPE})
public @interface categoryInfo {
/** 分类名称 */
String value();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.colin.tool.invokeableAnnotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* 标记该方法为可调用的功能,并且添加说明
*
* @Author colin
* @Date 2021/12/5 22:29
* @Version 1.0k
*/
@Retention(RetentionPolicy.RUNTIME) //运行环境可用
@Target({ElementType.METHOD})
public @interface functionInfo {
/** 功能名称 */
String value();
/** 简介 */
String info();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.colin.tool.invokeableAnnotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* 标记参数名称
*
* @Author colin
* @Date 2021/12/5 22:35
* @Version 1.0
*/
@Retention(RetentionPolicy.RUNTIME) //运行环境可用
@Target({ElementType.PARAMETER})
public @interface paramName {
/** 参数名 */
String value();
}

数据模型

  • 创建包com.colin.tool.model
  • 改类存储功能菜单需要的相关信息
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
package com.colin.tool.model;

import java.util.LinkedList;
import java.util.List;

/**
* 菜单数据内容
*
* @author colin.cheng
* @date 2021-12-06
* @since 1.0.0
*/
public class InvokeMenu {
private String functionName;
private String functionTitle;
private String functionInfo;
private String categoryName;
private Object instance;
private List<String> paramInfo = new LinkedList<>();

public InvokeMenu(String functionName, String functionTitle, String functionInfo, String categoryName, Object instance) {
this.functionName = functionName;
this.functionTitle = functionTitle;
this.functionInfo = functionInfo;
this.categoryName = categoryName;
this.instance = instance;
}

public String getCategoryName() {
return categoryName;
}

public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}

public Object getInstance() {
return instance;
}

public void setInstance(Object instance) {
this.instance = instance;
}

public String getFunctionTitle() {
return functionTitle;
}

public void setFunctionTitle(String functionTitle) {
this.functionTitle = functionTitle;
}

public String getFunctionName() {
return functionName;
}

public void setFunctionName(String functionName) {
this.functionName = functionName;
}

public String getFunctionInfo() {
return functionInfo;
}

public void setFunctionInfo(String functionInfo) {
this.functionInfo = functionInfo;
}

public List<String> getParamInfo() {
return paramInfo;
}

public void setParamInfo(String paramInfo) {
this.paramInfo.add(paramInfo);
}

@Override
public String toString() {
return "InvokeMenu{" +
"functionName='" + functionName + '\'' +
", functionTitle='" + functionTitle + '\'' +
", functionInfo='" + functionInfo + '\'' +
", paramInfo=" + paramInfo +
'}';
}
}

菜单界面展示

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
package com.colin.tool;

import com.colin.tool.model.InvokeMenu;
import java.util.List;
import java.util.Scanner;

/**
* 控制台界面
*
* @author colin.cheng
* @date 2021-12-06
* @since 1.0.0
*/
public class ConsoleMenu {

public void viewMenu(List<InvokeMenu> menus) {
System.out.println("--------------------------菜单------------------------");
System.out.println("请输入序号以选择功能:");
System.out.println("\t[-1] 退出");
System.out.println("\t[0] 帮助");
String currentCategory = "";
for (int i = 0; i < menus.size(); i++) {
final InvokeMenu menu = menus.get(i);
if(!menu.getCategoryName().equals(currentCategory)) {
currentCategory = menu.getCategoryName();
System.out.println("功能分类[" + currentCategory + "]");
}
System.out.println("\t[" + (i + 1) + "] " + menu.getFunctionTitle());
}
System.out.println("--------------------------结束------------------------");
}

public void viewHelp(List<InvokeMenu> menus) {
System.out.println("--------------------------帮助------------------------");
for (int i = 0; i < menus.size(); i++) {
final InvokeMenu menu = menus.get(i);
System.out.println("[" + (i + 1) + "] " +menu.getFunctionTitle() + "[" + menu.getFunctionName() + "]");
System.out.println("\t\t" + menu.getFunctionInfo());
for (int j = 0; j < menu.getParamInfo().size(); j++) {
System.out.println("\t\t参数[" + (j + 1) + "]: " + menu.getParamInfo().get(j));
}
}
System.out.println("--------------------------结束------------------------");
pause("任意输入返回菜单...");
}

public void pause(String str) {
System.out.print(str);
Scanner scanner = new Scanner(System.in);
scanner.hasNextLine();
}

public String getInput(String str) {
Scanner scanner = new Scanner(System.in);
System.out.print(str);
return scanner.next();
}
}

主类

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
package com.colin.tool;

import com.colin.tool.invokeableAnnotation.*;
import com.colin.tool.model.InvokeMenu;

import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.net.URL;
import java.util.*;

/**
* 工具通用调用
*
* @Author colin
* @Date 2021/12/5 22:02
* @Version 1.0
*/
public class UtilToolInvoke {

public static void main(String[] args) throws Exception {
String packageName = "com.colin.tool.function";
String packagePath = packageName.replace(".", "/");
final ClassLoader loader = UtilToolInvoke.class.getClassLoader();
final URL resource = loader.getResource(packagePath);
System.out.println(resource);
final File packageFile = new File(resource.getFile());
List<Class> funClass = new LinkedList<>();
if(packageFile.isDirectory()) {
final File[] files = packageFile.listFiles();
if (files != null) {
for (File classFile : files) {
if(classFile.getName().endsWith(".class")) {
final Class<?> aClass = loader.loadClass(packageName + "." + classFile.getName().replace(".class", ""));
funClass.add(aClass);
}
}
startWithConsole(funClass);
}
}
if(funClass.size() <= 0) {
System.out.println("---------暂无功能----------");
}
System.out.println("---------end--------");
}

// private

private static void startWithConsole(List<Class> functionClasses) throws Exception {
final ConsoleMenu consoleMenu = new ConsoleMenu();
final List<InvokeMenu> menus = getFunctionList(functionClasses);
boolean isContinue = true;
while (isContinue) {
consoleMenu.viewMenu(menus);
final String input = consoleMenu.getInput("请输入您的选择,回车确认:");
if("-1".equals(input)) {
isContinue = false;
} else if("0".equals(input)) {
consoleMenu.viewHelp(menus);
} else if(Integer.parseInt(input) - 1 < menus.size()) {
final InvokeMenu invokeMenu = menus.get(Integer.parseInt(input) - 1);
final String functionName = invokeMenu.getFunctionName();
System.out.println("正在执行功能[" + invokeMenu.getFunctionTitle() + "]");
String[] values = new String[invokeMenu.getParamInfo().size()];
Class[] types = new Class[invokeMenu.getParamInfo().size()];
for (int i = 0; i < invokeMenu.getParamInfo().size(); i++) {
values[i] = consoleMenu.getInput("请输入" + invokeMenu.getParamInfo().get(i) + ":");
types[i] = String.class;
}
final Method method = invokeMenu.getInstance().getClass().getMethod(functionName, types);
String res = method.invoke(invokeMenu.getInstance(), values) + "";
consoleMenu.pause(res + ", 任意输入返回...");
} else {
consoleMenu.pause("输入错误,任意输入返回...");
}
}
}

private static List<InvokeMenu> getFunctionList(List<Class> targetClasses) throws IllegalAccessException, InstantiationException {
List<InvokeMenu> menuList = new LinkedList<>();
for (Class targetClass : targetClasses) {
boolean hasAnnotation = targetClass.isAnnotationPresent(categoryInfo.class);
if(hasAnnotation) {
categoryInfo categoryAnnotation = (categoryInfo)targetClass.getAnnotation(categoryInfo.class);
Object instance = targetClass.newInstance();
for (Method method : targetClass.getMethods()) {
hasAnnotation = method.isAnnotationPresent(functionInfo.class);
if(hasAnnotation) {
functionInfo funcAnnotation = method.getAnnotation(functionInfo.class);
InvokeMenu menu = new InvokeMenu(method.getName(), funcAnnotation.value(), funcAnnotation.info(), categoryAnnotation.value(), instance);
for (Parameter parameter : method.getParameters()) {
paramName paramName = parameter.getAnnotation(paramName.class);
menu.setParamInfo(paramName.value());
}
menuList.add(menu);
}
}
}
}
return menuList;
}
}

声明功能

上面的代码已经是完整的了,但是还没添加功能

  • 创建com.colin.tool.function包,这个包下的类会自动扫描并加载
  • 声明有哪些功能,及功能简介
  1. 之前写的加密相关功能
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
package com.colin.tool.function;

import com.colin.tool.ConsoleMenu;
import com.colin.tool.invokeableAnnotation.*;
import com.colin.tool.file.EncryptionDirectoryProcessor;

/**
* 文件加密相关功能入口
*
* @author colin.cheng
* @date 2021-12-06 15:23
* @since 1.0.0
*/
@categoryInfo("文件加密")
public class CryptoFunction {

private EncryptionDirectoryProcessor processor;

@functionInfo(value = "全局密码设置", info = "加密相关功能需要预先设置该密码然后才能正常使用")
public String setGloblePwd(@paramName("密码") String pwd) {
try {
processor = new EncryptionDirectoryProcessor(pwd).defaultLog();
} catch (Exception e) {
return "设置失败";
}
return "设置成功";
}

@functionInfo(value = "开启加密功能日志打印", info = "打印扫描文件及处理进度,默认开启")
public String enableCryptoLog() {
processor.defaultLog();
return "开启成功";
}

@functionInfo(value = "关闭加密功能日志打印", info = "关闭后将静默处理")
public String disableCryptoLog() {
processor.setSearchLog(null);
processor.setProcessorLog(null);
return "已关闭";
}

@functionInfo(value = "加密文件夹", info = "将指定文件夹内文件加密")
public String encryptDirectory(@paramName(value = "文件夹路径")String path) {
try {
final ConsoleMenu consoleMenu = new ConsoleMenu();
path = path.trim();
final String input = consoleMenu.getInput("确认加密路径[" + path + "] 么? 输入y 确认,其它取消:");
if("y".equals(input)) {
processor.encryptDirectory(path);
}
} catch (Exception e) {
return "加密失败,请检查是否设置全局密码";
}
return "加密成功";
}

@functionInfo(value = "解密文件夹", info = "将指定文件夹内文件解密")
public String decryptDirectory(@paramName(value = "文件夹路径")String path) {
try {
final ConsoleMenu consoleMenu = new ConsoleMenu();
path = path.trim();
final String input = consoleMenu.getInput("确认解密路径[" + path + "] 么? 输入y 确认,其它取消:");
if("y".equals(input)) {
processor.decryptDirectory(path);
}
} catch (Exception e) {
return "解密失败,请检查是否设置全局密码";
}
return "解密成功";
}

@functionInfo(value = "查看加密文件列表", info = "查看指定的加密文件夹内文件列表")
public String listEncryptDirectory(@paramName(value = "文件夹路径")String path) {
try {
path = path.trim();
processor.listDirectory(path, true).forEach(System.out::println);
} catch (Exception e) {
return "解密失败,请检查是否设置全局密码";
}
return "搜索成功";
}
}
  1. 文件搜索相关功能
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
package com.colin.tool.function;

import com.colin.tool.file.FileSearchStream;
import com.colin.tool.invokeableAnnotation.*;

import java.io.File;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;

/**
* 文件搜索入口
*
* @author colin.cheng
* @date 2021-12-09 10:37
* @since 1.0.0
*/
@categoryInfo("文件搜索")
public class FileSearch {

@functionInfo(value = "搜索整个文件夹", info = "列出文件夹内所有文件")
public String searchFileByPath(@paramName("需要搜索的路径") String path) {
AtomicInteger count = new AtomicInteger();
new FileSearchStream(new File(path)).forEach(file -> {
System.out.println(file.getPath());
count.getAndIncrement();
});
return "搜索结束, 一共[" + count + "]个文件";
}

@functionInfo(value = "按文件名模糊搜索", info = "正则匹配路径内所有文件")
public String searchFileLike(@paramName("搜索路径") String path, @paramName("文件名搜索正则规则") String regex) {
AtomicInteger count = new AtomicInteger();
Pattern p = Pattern.compile(regex);
new FileSearchStream(new File(path)).forEach(file -> {
if(p.matcher(file.getName()).matches()) {
System.out.println(file.getPath());
count.getAndIncrement();
}
});
return "搜索结束, 一共[" + count + "]个文件";
}

@functionInfo(value = "按文件后缀搜索", info = "所搜指定后缀(结尾)的文件")
public String searchFileBySuffix(@paramName("搜索路径") String path, @paramName("后缀") String suffix) {
AtomicInteger count = new AtomicInteger();
new FileSearchStream(new File(path)).forEach(file -> {
if(file.getName().endsWith(suffix)) {
System.out.println(file.getPath());
count.getAndIncrement();
}
});
return "搜索结束, 一共[" + count + "]个文件";
}

@functionInfo(value = "搜索指定类型的文件(img/document/application/audio/video)", info = "img[psd,pdd,gif,jpeg,jpg,png] document[doc,docx,xls,xlsx,csv,ppt,pptx,txt] application[exe,bat,cmd,sh,ink,py,class,java] audio[mp3,flac,ape,cd,wave,aiff] video[avi,mov,qt,asf,rm,navi,divX,mpeg,mpg,ogg,mod,rmvb,flv,mp4,3gp]")
public String searchFileByType(@paramName("搜索路径") String path, @paramName("文件类型") String type) {
FileSearchStream.FileSuffix suffix = null;
switch (type.toLowerCase()) {
case "img": suffix = FileSearchStream.FileSuffix.IMG; break;
case "document": suffix = FileSearchStream.FileSuffix.DOCUMENT; break;
case "application": suffix = FileSearchStream.FileSuffix.APPLICATION; break;
case "audio": suffix = FileSearchStream.FileSuffix.AUDIO; break;
case "video": suffix = FileSearchStream.FileSuffix.VIDEO; break;
default:
System.out.println("文件类型[" + type + "]未定义");
}
AtomicInteger count = new AtomicInteger();
final FileSearchStream.FileSuffix checkSuffix = suffix;
if(suffix != null) {
new FileSearchStream(new File(path)).forEach(file -> {
if(checkSuffix.check(file.getName())) {
System.out.println(file.getPath());
count.getAndIncrement();
}
});
}
return "搜索结束, 一共[" + count + "]个文件";
}
}

使用

运行UtilToolInvoke.classmain方法即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
--------------------------菜单------------------------
请输入序号以选择功能:
[-1] 退出
[0] 帮助
功能分类[文件加密]
[1] 查看加密文件列表
[2] 加密文件夹
[3] 解密文件夹
[4] 全局密码设置
[5] 开启加密功能日志打印
[6] 关闭加密功能日志打印
功能分类[文件搜索]
[7] 按文件后缀搜索
[8] 按文件名模糊搜索
[9] 搜索整个文件夹
[10] 搜索指定类型的文件(img/document/application/audio/video)
--------------------------结束------------------------
请输入您的选择,回车确认:

文章字数:935,阅读全文大约需要3分钟

抓取百度翻译接口,将一个国际化文件翻译成若干指定语言的国际化文件

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
package com.colin.util;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import javax.net.ssl.SSLContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;

/**
* @author colin.cheng
* @date 2020-05-19
* @since 1.0.0
*/
public class Test1 {

// 源文件
private static String basePath = "D:\\test\\translate\\123\\";
private static String fromName = "eventCenter_en_US.properties";

// 百度翻译接口相关
private static String path = "https://fanyi.baidu.com/v2transapi?";
private static String token = "5a9892b6584a2fed08f75bed87736039";
private static String windowgtk = "'320305.131321201'";

private static Charset fileCharset = StandardCharsets.UTF_8;
private static String fileSuffix = fromName.split("\\.")[1];

// 如果目标语言国际化存在,是否覆盖。默认跳过。
private static boolean override = false;
// 每次翻译之后休眠时间,太快会被封禁ip
private static int sleepTime = 2;

// 网络异常后继续上次的进度
private static Integer lastLine = 13;
private static LanguageEnum lastLanguage = LanguageEnum.AR;

private static AtomicInteger count = new AtomicInteger();

public static void main(String[] args) {
try {
List<LanguageEnum> to = new LinkedList<>();
LanguageEnum from;
String modelName = fromName.split("\\.")[0];
modelName = modelName.split("_")[0];
from = LanguageEnum.getByZKName(fromName.split("\\.")[0].replace(modelName + "_", ""));

// 翻译成那些语言
// 指定某个文件
// to.add(LanguageEnum.ZH_TW);
// 或者全部翻译
to.addAll(from.getOther());

List<String> fromLine = getLineByFile(basePath + fromName);
for (LanguageEnum toLang : to) {
createToFile(from, toLang, modelName, fromLine);
}
System.out.println("处理完毕,总共翻译 [" + count.get() + "] 次");
} catch (Exception e) {
e.printStackTrace();
}
}

private static ScriptEngine scriptEngine;
private static RestTemplate restTemplate;

enum LanguageEnum {
// 中文
ZH_CN("zh_CN", "zh"),
// 英文
EN("en_US", "en"),
// 繁体
ZH_TW("zh_TW", "cht"),
// 越南语
VI("vi", "vie"),
// 泰语
TH("th", "th"),
// 俄语
RU("ru_RU", "ru"),
// 罗马尼亚
RO("ro", "rom"),
// 葡萄牙
PT("pt_BR", "pt"),
// 波兰语
PL("pl", "pl"),
// 韩语
KO("ko_KR", "kor"),
// 日语
JA("ja_JP", "jp"),
// 意大利
IT("it", "it"),
// 印尼
IN("in_ID", "id"),
// 法语
FR("fr", "fra"),
// 西班牙
ES("es", "spa"),
// 德语
DE("de", "de"),
// 阿拉伯
AR("ar", "ara"),
// 土耳其语
TR("tr", "tr");

public String zkName;
public String bdName;

LanguageEnum(String zkName, String bdName) {
this.bdName = bdName;
this.zkName = zkName;
}

public static LanguageEnum getByZKName(String zkName) {
for (LanguageEnum value : LanguageEnum.values()) {
if (value.zkName.equals(zkName)) {
return value;
}
}
return null;
}

public List<LanguageEnum> getOther() {
List<LanguageEnum> list = new LinkedList<>();
for (LanguageEnum value : LanguageEnum.values()) {
if (value != this) {
list.add(value);
}
}
return list;
}
}

/**
* 翻译
*
* @param fromEnum 当前语言
* @param toEnmu 需要翻译的语言
* @param val 需要翻译的值
* @return
* @throws Exception
*/
public static String getTranslate(LanguageEnum fromEnum, LanguageEnum toEnmu, String val) throws Exception {
String from = fromEnum.bdName, to = toEnmu.bdName;
String url = path + "from=" + from + "&to=" + to;
JSONObject res =
postFromUrl(url, new Object[] {"from", from}, new Object[] {"to", to}, new Object[] {"query", val},
new Object[] {"transtype", "translang"}, new Object[] {"simple_means_flag", "3"},
new Object[] {"sign", sign(val)}, new Object[] {"token", token}, new Object[] {"domain", "common"});
String resStr = res.getJSONObject("trans_result").getJSONArray("data").getJSONObject(0).getString("dst");
System.out
.println("正在翻译 [" + val + "] , translate = [" + from + " => " + to + "]" + " , 翻译结果 [" + resStr + "]");
count.getAndIncrement();
return resStr;
}

public static String sign(String v) throws ScriptException {
v = v.replace("'", "\\'");
scriptEngine.eval("var sign = e('" + v + "')");
String sign = scriptEngine.get("sign") + "";
return sign;
}

private static JSONObject postFromUrl(String url, Object[]... param) throws Exception {
final HttpEntity<MultiValueMap<Object, Object>> request = getRequestByParam(param);
ResponseEntity<String> entity;
entity = restTemplate.postForEntity(url, request, String.class);
if (entity.getStatusCode().is2xxSuccessful()) {
return JSONObject.parseObject(entity.getBody());
}
throw new RuntimeException("err");
}

private static void createToFile(LanguageEnum from, LanguageEnum to, String modelName, List<String> lines)
throws Exception {
String name = basePath + modelName + "_" + to.zkName + "." + fileSuffix;
if (!override && Files.exists(Paths.get(name))) {
if (lastLanguage == null || lastLine == null) {
System.out.println("文件 [" + name + "] 已存在,跳过");
return;
} else if (!isAppend(to, lastLanguage)) {
System.out.println("文件 [" + name + "] 已存在,跳过");
return;
}
}
System.out.println("当前处理文件为 [" + name + "]");
try (FileOutputStream outputStream = new FileOutputStream(name, isAppend(to, lastLanguage))) {
try (OutputStreamWriter writer = new OutputStreamWriter(outputStream, fileCharset)) {
for (int index = 0; index < lines.size(); index++) {
String line = lines.get(index);
System.out.println("当前文件进度: " + index + "/" + lines.size());
if (to.equals(lastLanguage) && index < lastLine) {
continue;
}
if (line.startsWith("#") || StringUtils.isEmpty(line)) {
writer.write(line + "\r\n");
} else {
String key = line.split("=")[0];
String val = line.split("=")[1];
writer.write(key + "=" + getTranslate(from, to, val) + "\r\n");
TimeUnit.SECONDS.sleep(sleepTime);
}
}
}
}
}

private static boolean isAppend(LanguageEnum to, LanguageEnum lastLanguage) {
return lastLanguage != null && to.equals(lastLanguage);
}

private static List<String> getLineByFile(String path) throws Exception {
try (FileInputStream inputStream = new FileInputStream(path)) {
try (InputStreamReader reader = new InputStreamReader(inputStream, fileCharset)) {
try (BufferedReader bufferedReader = new BufferedReader(reader)) {
return bufferedReader.lines().collect(Collectors.toList());
}
}
}
}

private static HttpEntity<MultiValueMap<Object, Object>> getRequestByParam(Object[]... params) {
final HttpHeaders headers = new HttpHeaders();
final LinkedMultiValueMap<Object, Object> map = new LinkedMultiValueMap<>();
if (params != null) {
for (Object[] param : params) {
map.add(param[0], param[1]);
}
}
String paramStr = "Host: fanyi.baidu.com\n"
+ "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0\n"
+ "Accept: */*\n" + "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2\n"
+ "Accept-Encoding: gzip, deflate, br\n"
+ "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\n" + "X-Requested-With: XMLHttpRequest\n"
+ "Origin: https://fanyi.baidu.com\n" + "Connection: keep-alive\n" + "Referer: https://fanyi.baidu.com/\n"
+ "Cookie: BAIDUID=1F3AA9B69AA7D53DE31F86572B715FAE:FG=1; BIDUPSID=1F3AA9B69AA7D53DDA50BBE8079D1BC7; PSTM=1630997334; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; td_cookie=2315277960; __yjs_duid=1_580e46fc7808cbbe7243e345c691bd4c1635751328621; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1635751323,1635822756,1635904954; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; H_PS_PSSID=34889_34068_31253_34862_34599_34584_34505_34916_34606_26350_34972_34868; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1635904954; delPer=0; PSINO=5\n"
+ "Sec-Fetch-Dest: empty\n" + "Sec-Fetch-Mode: cors\n" + "Sec-Fetch-Site: same-origin";
final String[] split = paramStr.split("\n");
for (String paramVal : split) {
final String[] split1 = paramVal.split(": ");
headers.set(split1[0], split1[1].trim());
}
return new HttpEntity<>(map, headers);
}

public static RestTemplate getRestTemplate()
throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory csf =
new SSLConnectionSocketFactory(sslContext, new String[] {"TLSv1.2"}, null, NoopHostnameVerifier.INSTANCE);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(requestFactory);
return restTemplate;
}

static {
try {
ScriptEngineManager sem = new ScriptEngineManager();
scriptEngine = sem.getEngineByName("javascript");
String signFunc = "var window = [];\n" + "\tfunction e(r) {\n" + "\tvar i = null;\n"
+ " var o = r.match(/[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g);\n" + " if (null === o) {\n"
+ " var t = r.length;\n"
+ " t > 30 && (r = '' + r.substr(0, 10) + r.substr(Math.floor(t / 2) - 5, 10) + r.substr( - 10, 10))\n"
+ " } else {\n"
+ " for (var e = r.split(/[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/), C = 0, h = e.length, f = [\n"
+ " ]; h > C; C++) '' !== e[C] && f.push.apply(f, a(e[C].split(''))),\n"
+ " C !== h - 1 && f.push(o[C]);\n" + " var g = f.length;\n"
+ " g > 30 && (r = f.slice(0, 10).join('') + f.slice(Math.floor(g / 2) - 5, Math.floor(g / 2) + 5).join('') + f.slice( - 10).join(''))\n"
+ " }\n" + " var u = void 0,\n"
+ " l = '' + String.fromCharCode(103) + String.fromCharCode(116) + String.fromCharCode(107);\n"
+ " u = null !== i ? i : (i = " + windowgtk + " || '') || '';\n"
+ " for (var d = u.split('.'), m = Number(d[0]) || 0, s = Number(d[1]) || 0, S = [\n"
+ " ], c = 0, v = 0; v < r.length; v++) {\n" + " var A = r.charCodeAt(v);\n"
+ " 128 > A ? S[c++] = A : (2048 > A ? S[c++] = A >> 6 | 192 : (55296 === (64512 & A) && v + 1 < r.length && 56320 === (64512 & r.charCodeAt(v + 1)) ? (A = 65536 + ((1023 & A) << 10) + (1023 & r.charCodeAt(++v)), S[c++] = A >> 18 | 240, S[c++] = A >> 12 & 63 | 128) : S[c++] = A >> 12 | 224, S[c++] = A >> 6 & 63 | 128), S[c++] = 63 & A | 128)\n"
+ " }\n"
+ " for (var p = m, F = '' + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(97) + ('' + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(54)), D = '' + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(51) + ('' + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(98)) + ('' + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(102)), b = 0; b < S.length; b++) p += S[b],\n"
+ " p = n(p, F);\n" + " return p = n(p, D),\n" + " p ^= s,\n"
+ " 0 > p && (p = (2147483647 & p) + 2147483648),\n" + " p %= 1000000,\n"
+ " p.toString() + '.' + (p ^ m)\n" + " }\n" + " \n" + " function a(r) {\n"
+ " if (Array.isArray(r)) {\n"
+ " for (var o = 0, t = Array(r.length); o < r.length; o++) t[o] = r[o];\n" + " return t\n"
+ " }\n" + " return Array.from(r)\n" + " }\n" + " function n(r, o) {\n"
+ " for (var t = 0; t < o.length - 2; t += 3) {\n" + " var a = o.charAt(t + 2);\n"
+ " a = a >= 'a' ? a.charCodeAt(0) - 87 : Number(a),\n"
+ " a = '+' === o.charAt(t + 1) ? r >>> a : r << a,\n"
+ " r = '+' === o.charAt(t) ? r + a & 4294967295 : r ^ a\n" + " }\n" + " return r\n" + " }";
scriptEngine.eval(signFunc);
restTemplate = getRestTemplate();
List<HttpMessageConverter<?>> list = restTemplate.getMessageConverters();
for (HttpMessageConverter<?> httpMessageConverter : list) {
if (httpMessageConverter instanceof StringHttpMessageConverter) {
((StringHttpMessageConverter)httpMessageConverter).setDefaultCharset(StandardCharsets.UTF_8);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

文章字数:1200,阅读全文大约需要4分钟

摘自今日头条,一些以后可能会用到的代码片段。

  1. 原生JavaScript实现字符串长度截取
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    function cutstr(str, len) {
    var temp;
    var icount = 0;
    var patrn = /[^\x00-\xff]/; // 匹配双字节字符(包括汉字在内)
    var strren = "";
    for (var i = 0; i < str.length; i++) {
    if (icount < len - 1) {
    temp = str.substr(i, 1);
    if (patrn.exec(temp) == null) {
    icount = icount + 1;
    } else {
    icount = icount + 2;
    }
    } else {
    break;
    }
    }
    return strre + "...";
    }
  2. 原生JavaScript获取域名主机
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function getHost(url) {
    var host = "null";
    if (typeof url == undefined || url === null) {
    url = window.location.href;
    }
    var regex = /^w+://([^/]*).*/;
    var match = url.match(regex);
    if (typeof match != undefined && match != null) {
    host = match[1];
    }
    return host;
    }
  3. 原生JavaScript清除空格
    1
    2
    3
    4
    String.prototype.trim = function() {
    var reExtraSpace = /^s*(.*?)s+$/;
    return this.replace(reExtraSpace, "$1");
    }
  4. 原生JavaScript替换全部
    1
    2
    3
    String.prototype.replaceAll = function(s1, s2) {
    return this.replace(new RegExp(s1, "gm"), s2);
    }
  5. 原生JavaScript转义html标签
    1
    2
    3
    4
    5
    6
    function HtmlEncode(text) {
    return text.replace(/&/g, '&amp')
    .replace(/"/g, '&quot')
    .replace(/</g, '&lt')
    .replace(/>/g, '&gt');
    }
  6. 原生JavaScript还原html标签
    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
    function HtmlDecode(text) {
    return text.replace('&amp', /&/g)
    .replace('&quot', /"/g)
    .replace('&lt', /</g)
    .replace('&gt', />/g);
    }
    7. 原生JavaScript时间日期格式替换
    ```javascript
    Date.prototype.Format = function(formatStr) {
    var str = formatStr;
    var Week = ['日', '一', '二', '三', '四', '五', '六'];
    str = str.replace(/yyyy|YYYY/, this.getFullYear());
    str = str.replace(/yy|YY/, (this.getYear() % 100) > 9 ? (this.getYear() % 100).toString() : '0' + (this.getYear() % 100));
    str = str.replace(/MM/, (this.getMonth() + 1) > 9 ? (this.getMonth() + 1).toString() : '0' + (this.getMonth() + 1));
    str = str.replace(/M/g, (this.getMonth() + 1));
    str = str.replace(/w|W/g, Week[this.getDay()]);
    str = str.replace(/dd|DD/, this.getDate() > 9 ? this.getDate().toString() : '0' + this.getDate());
    str = str.replace(/d|D/g, this.getDate());
    str = str.replace(/hh|HH/, this.getHours() > 9 ? this.getHours().toString() : '0' + this.getHours());
    str = str.replace(/h|H/g, this.getHours());
    str = str.replace(/mm/, this.getMinutes() > 9 ? this.getMinutes().toString() : '0' + this.getMinutes());
    str = str.replace(/m/g, this.getMinutes());
    str = str.replace(/ss|SS/, this.getSeconds() > 9 ? this.getSeconds().toString() : '0' + this.getSeconds());
    str = str.replace(/s|S/g, this.getSeconds());
    return str
    }
  7. 原生JavaScript判断是否为数字类型
    1
    2
    3
    4
    5
    6
    7
    8
    function isDigit(value) {
    var patrn = /^[0-9]*$/;
    if (patrn.exec(value) == null || value == "") {
    return false
    } else {
    return true
    }
    }
  8. 原生JavaScript设置cookie值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function setCookie(name, value, Hours) {
    var d = new Date();
    var offset = 8;
    var utc = d.getTime() + (d.getTimezoneOffset() * 60000);
    var nd = utc + (3600000 * offset);
    var exp = new Date(nd);
    exp.setTime(exp.getTime() + Hours * 60 * 60 * 1000);
    document.cookie = name + "=" + escape(value) + ";path=/;expires=" + exp.toGMTString() + ";domain=360doc.com;"
    }
  9. 原生JavaScript获取cookie值
    1
    2
    3
    4
    5
    function getCookie(name) {
    var arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
    if (arr != null) return unescape(arr[2]);
    return null
    }
  10. 原生JavaScript加入收藏夹
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function AddFavorite(sURL, sTitle) {
    try {
    window.external.addFavorite(sURL, sTitle)
    } catch(e) {
    try {
    window.sidebar.addPanel(sTitle, sURL, "")
    } catch(e) {
    alert("加入收藏失败,请使用Ctrl+D进行添加")
    }
    }
    }
  11. 原生JavaScript设为首页
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function setHomepage() {
    if (document.all) {
    document.body.style.behavior = 'url(#default#homepage)';
    document.body.setHomePage('http://***');
    } else if (window.sidebar) {
    if (window.netscape) {
    try {
    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect")
    } catch(e) {
    alert("该操作被浏览器拒绝,如果想启用该功能,请在地址栏内输入 about:config,然后将项 signed.applets.codebase_principal_support 值该为true")
    }
    }
    var prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefBranch);
    prefs.setCharPref('browser.startup.homepage', 'http://***')
    }
    }
  12. 原生JavaScript判断IE6
    1
    2
    3
    4
    5
    6
    7
    var ua = navigator.userAgent.toLowerCase();
    var isIE6 = ua.indexOf("msie 6") > -1;
    if (isIE6) {
    try {
    document.execCommand("BackgroundImageCache", false, true)
    } catch(e) {}
    }
  13. 原生JavaScript加载样式文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function LoadStyle(url) {
    try {
    document.createStyleSheet(url)
    } catch(e) {
    var cssLink = document.createElement('link');
    cssLink.rel = 'stylesheet';
    cssLink.type = 'text/css';
    cssLink.href = url;
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(cssLink)
    }
    }
  14. 原生JavaScript返回脚本内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function evalscript(s) {
    if(s.indexOf('<script') == -1) return s;
    var p = /<script[^>]*?>([^\x00]*?)</script>/ig;
    var arr = [];
    while(arr = p.exec(s)) {
    var p1 = /<script[^>]*?src="([^>]*?)"[^>]*?(reload="1")?(?:charset="([w-]+?)")?></script>/i;
    var arr1 = [];
    arr1 = p1.exec(arr[0]);
    if(arr1) {
    appendscript(arr1[1], '', arr1[2], arr1[3]);
    } else {
    p1 = /<script(.*?)>([^\x00]+?)</script>/i;
    arr1 = p1.exec(arr[0]);
    appendscript('', arr1[2], arr1[1].indexOf('reload=') != -1);
    }
    }
    return s;
    }
  15. 原生JavaScript清除脚本内容
    1
    2
    3
    function stripscript(s) {
    return s.replace(/<script.*?>.*?</script>/ig, '');
    }
  16. 原生JavaScript动态加载脚本文件
    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
    function appendscript(src, text, reload, charset) {
    var id = hash(src + text);
    if(!reload && in_array(id, evalscripts)) return;
    if(reload && $(id)) {
    $(id).parentNode.removeChild($(id));
    }

    evalscripts.push(id);
    var scriptNode = document.createElement("script");
    scriptNode.type = "text/javascript";
    scriptNode.id = id;
    scriptNode.charset = charset ? charset : (BROWSER.firefox ? document.characterSet : document.charset);
    try {
    if(src) {
    scriptNode.src = src;
    scriptNode.onloadDone = false;
    scriptNode.onload = function () {
    scriptNode.onloadDone = true;
    JSLOADED[src] = 1;
    };
    scriptNode.onreadystatechange = function () {
    if((scriptNode.readyState == 'loaded' || scriptNode.readyState == 'complete') && !scriptNode.onloadDone) {
    scriptNode.onloadDone = true;
    JSLOADED[src] = 1;
    }
    };
    } else if(text){
    scriptNode.text = text;
    }
    document.getElementsByTagName('head')[0].appendChild(scriptNode);
    } catch(e) {}
    }
  17. 原生JavaScript返回按ID检索的元素对象
    1
    2
    3
    function $(id) {
    return !id ? null : document.getElementById(id);
    }
  18. 原生JavaScript返回浏览器版本内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function browserVersion(types) {
    var other = 1;
    for(i in types) {
    var v = types[i] ? types[i] : i;
    if(USERAGENT.indexOf(v) != -1) {
    var re = new RegExp(v + '(\/|\s)([\d\.]+)', 'ig');
    var matches = re.exec(USERAGENT);
    var ver = matches != null ? matches[2] : 0;
    other = ver !== 0 && v != 'mozilla' ? 0 : other;
    }else {
    var ver = 0;
    }
    eval('BROWSER.' + i + '= ver');
    }
    BROWSER.other = other;
    }
  19. 原生JavaScript元素显示的通用方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function $(id) {
    return !id ? null : document.getElementById(id);
    }
    function display(id) {
    var obj = $(id);
    if(obj.style.visibility) {
    obj.style.visibility = obj.style.visibility == 'visible' ? 'hidden' : 'visible';
    } else {
    obj.style.display = obj.style.display == '' ? 'none' : '';
    }
    }
  20. 原生JavaScript中有insertBefore方法,可惜却没有insertAfter方法?用如下函数实现
    1
    2
    3
    4
    5
    6
    7
    8
    function insertAfter(newChild, refChild) {
    var parElem = refChild.parentNode;
    if(parElem.lastChild == refChild){
    refChild.appendChild(newChild);
    }else{
    parElem.insertBefore(newChild, refChild.nextSibling);
    }
    }
  21. 原生JavaScript中兼容浏览器绑定元素事件
    1
    2
    3
    4
    5
    6
    7
    function addEventSamp(obj, evt, fn){ 
    if (obj.addEventListener) {
    obj.addEventListener(evt, fn, false);
    }else if(obj.attachEvent){
    obj.attachEvent('on' + evt, fn);
    }
    }
  22. 原生JavaScript光标停在文字的后面,文本框获得焦点时调用
    1
    2
    3
    4
    5
    6
    7
    function focusLast(){ 
    var e = event.srcElement;
    var r =e.createTextRange();
    r.moveStart('character',e.value.length);
    r.collapse(true);
    r.select();
    }
  23. 原生JavaScript检验URL链接是否有效
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    function getUrlState(URL) { 
    var xmlhttp = new ActiveXObject("microsoft.xmlhttp");
    xmlhttp.Open("GET", URL, false);
    try {
    xmlhttp.Send();
    } catch(e) {

    } finally {
    var result = xmlhttp.responseText;
    if(result) {
    if(xmlhttp.Status==200){
    return true;
    }else{
    return false;
    }
    } else {
    return false;
    }
    }
    }
  24. 原生JavaScript格式化CSS样式代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function formatCss(s){ //格式化代码
    s = s.replace(/s*([{}:;,])s*/g, "$1");
    s = s.replace(/;s*;/g, ";"); //清除连续分号
    s = s.replace(/,[s.#d]*{/g, "{");
    s = s.replace(/([^s]){([^s])/g, "$1 {
    $2");
    s = s.replace(/([^s])}([^
    ]*)/g, "$1
    }
    $2");
    s = s.replace(/([^s]);([^s}])/g, "$1;
    $2");
    return s;
    }
  25. 原生JavaScript压缩CSS样式代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function yasuoCss (s) { //压缩代码
    s = s.replace(//*(.|
    )*?*//g, ""); //删除注释
    s = s.replace(/s*([{}:;,])s*/g, "$1");
    s = s.replace(/,[s.#d]*{/g, "{"); //容错处理
    s = s.replace(/;s*;/g, ";"); //清除连续分号
    s = s.match(/^s*(S+(s+S+)*)s*$/); //去掉首尾空白
    return (s == null) ? "" : s[1];
    }
  26. 原生JavaScript获取当前路径
    1
    2
    3
    4
    5
    6
    7
    var currentPageUrl = "";
    if (typeof this.href === undefined) {
    currentPageUrl = document.location.toString().toLowerCase();
    }
    else {
    currentPageUrl = this.href.toString().toLowerCase();
    }
  27. 原生JavaScript将IP地址转成整型
    1
    2
    3
    4
    5
    6
    7
    function _ip2int(ip){
    var num = 0;
    ip = ip.split(".");
    num = Number(ip[0]) * 256 * 256 * 256 + Number(ip[1]) * 256 * 256 + Number(ip[2]) * 256 + Number(ip[3]);
    num = num >>> 0;
    return num;
    }
  28. 原生JavaScript整型解析为IP地址
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function _int2iP(num){
    var str;
    var tt = new Array();
    tt[0] = (num >>> 24) >>> 0;
    tt[1] = ((num << 8) >>> 24) >>> 0;
    tt[2] = (num << 16) >>> 24;
    tt[3] = (num << 24) >>> 24;
    str = String(tt[0]) + "." + String(tt[1]) + "." + String(tt[2]) + "." + String(tt[3]);
    return str;
    }
  29. 原生JavaScript实现checkbox全选与全不选
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function checkAll() {
    var selectall = document.getElementById("selectall");
    var allbox = document.getElementsByName("allbox");
    if (selectall.checked) {
    for (var i = 0; i < allbox.length; i++) {
    allbox[i].checked = true;
    }
    } else {
    for (var i = 0; i < allbox.length; i++) {
    allbox[i].checked = false;
    }
    }
    }
  30. 原生JavaScript判断是否移动设备
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function isMobile(){
    if (typeof this._isMobile === 'boolean'){
    return this._isMobile;
    }
    var screenWidth = this.getScreenWidth();
    var fixViewPortsExperiment = rendererModel.runningExperiments.FixViewport || rendererModel.runningExperiments.fixviewport;
    var fixViewPortsExperimentRunning = fixViewPortsExperiment && (fixViewPortsExperiment.toLowerCase() === "new");
    if(!fixViewPortsExperiment){
    if(!this.isAppleMobileDevice()){
    screenWidth = screenWidth/window.devicePixelRatio;
    }
    }
    var isMobileScreenSize = screenWidth < 600;
    var isMobileUserAgent = false;
    this._isMobile = isMobileScreenSize && this.isTouchScreen();
    return this._isMobile;
    }
  31. 原生JavaScript判断是否移动设备访问
    1
    2
    3
    function isMobileUserAgent() {
    return (/iphone|ipod|android.*mobile|windows.*phone|blackberry.*mobile/i.test(window.navigator.userAgent.toLowerCase()));
    }
  32. 原生JavaScript判断是否苹果移动设备访问
    1
    2
    3
    function isAppleMobileDevice() {
    return (/iphone|ipod|ipad|Macintosh/i.test(navigator.userAgent.toLowerCase()));
    }
  33. 原生JavaScript判断是否安卓移动设备访问
    1
    2
    3
    function isAndroidMobileDevice(){
    return (/android/i.test(navigator.userAgent.toLowerCase()));
    }
  34. 原生JavaScript判断是否Touch屏幕
    1
    2
    3
    function isTouchScreen() {
    return (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);
    }
  35. 原生JavaScript判断是否在安卓上的谷歌浏览器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function isNewChromeOnAndroid(){
    if(this.isAndroidMobileDevice()){
    var userAgent = navigator.userAgent.toLowerCase();
    if((/chrome/i.test(userAgent))){
    var parts = userAgent.split('chrome/');
    var fullVersionString = parts[1].split(" ")[0];
    var versionString = fullVersionString.split('.')[0];
    var version = parseInt(versionString);
    if(version >= 27){
    return true;
    }
    }
    }
    return false;
    }
  36. 原生JavaScript判断是否打开视窗
    1
    2
    3
    function isViewportOpen() {
    return !!document.getElementById('wixMobileViewport');
    }
  37. 原生JavaScript获取移动设备初始化大小
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function getInitZoom() {
    if(!this._initZoom) {
    var screenWidth = Math.min(screen.height, screen.width);
    if(this.isAndroidMobileDevice() && !this.isNewChromeOnAndroid()) {
    screenWidth = screenWidth / window.devicePixelRatio;
    }
    this._initZoom = screenWidth /document.body.offsetWidth;
    }
    return this._initZoom;
    }
  38. 原生JavaScript获取移动设备最大化大小
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function getZoom(){
    var screenWidth = (Math.abs(window.orientation) === 90) ? Math.max(screen.height, screen.width) : Math.min(screen.height, screen.width);
    if(this.isAndroidMobileDevice() && !this.isNewChromeOnAndroid()){
    screenWidth = screenWidth/window.devicePixelRatio;
    }
    var FixViewPortsExperiment = rendererModel.runningExperiments.FixViewport || rendererModel.runningExperiments.fixviewport;
    var FixViewPortsExperimentRunning = FixViewPortsExperiment && (FixViewPortsExperiment === "New" || FixViewPortsExperiment === "new");
    if(FixViewPortsExperimentRunning){
    return screenWidth / window.innerWidth;
    }else{
    return screenWidth / document.body.offsetWidth;
    }
    }
  39. 原生JavaScript获取移动设备屏幕宽度
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function getScreenWidth(){
    var smallerSide = Math.min(screen.width, screen.height);
    var fixViewPortsExperiment = rendererModel.runningExperiments.FixViewport || rendererModel.runningExperiments.fixviewport;
    var fixViewPortsExperimentRunning = fixViewPortsExperiment && (fixViewPortsExperiment.toLowerCase() === "new");
    if(fixViewPortsExperiment){
    if(this.isAndroidMobileDevice() && !this.isNewChromeOnAndroid()){
    smallerSide = smallerSide/window.devicePixelRatio;
    }
    }
    return smallerSide;
    }
  40. 原生JavaScript完美判断是否为网址
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function IsURL(strUrl) {
    var regular = /^(((https?|ftp)://)?[-a-z0-9]+(.[-a-z0-9]+)*.(?:com|edu|gov|int|mil|net|org|biz|info|name|museum|asia|coop|aero|[a-z][a-z]|((25[0-5])|(2[0-4]d)|(1dd)|([1-9]d)|d))(/[-a-z0-9_:@&?=+,.!/~%$]*)?)$/i
    if (regular.test(strUrl)) {
    return true;
    }
    else {
    return false;
    }
    }
  41. 原生JavaScript根据样式名称检索元素对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function getElementsByClassName(name) {
    var tags = document.getElementsByTagName('*') || document.all;
    var els = [];
    for (var i = 0; i < tags.length; i++) {
    if (tags[i].className) {
    var cs = tags[i].className.split(' ');
    for (var j = 0; j < cs.length; j++) {
    if (name == cs[j]) {
    els.push(tags[i]);
    break;
    }
    }
    }
    }
    return els;
    }
  42. 原生JavaScript判断是否以某个字符串开头
    1
    2
    3
    String.prototype.startWith = function (s) {
    return this.indexOf(s) == 0;
    }
  43. 原生JavaScript判断是否以某个字符串结束
    1
    2
    3
    4
    String.prototype.endWith = function (s) {
    var d = this.length - s.length;
    return (d >= 0 && this.lastIndexOf(s) == d);
    }
  44. 原生JavaScript返回IE浏览器的版本号
    1
    2
    3
    4
    5
    6
    7
    function getIE(){
    if (window.ActiveXObject){
    var v = navigator.userAgent.match(/MSIE ([^;]+)/)[1];
    return parseFloat(v.substring(0, v.indexOf(".")));
    }
    return false;
    }
  45. 原生JavaScript获取页面高度
    1
    2
    3
    4
    5
    6
    function getPageHeight() {
    var g = document, a = g.body, f = g.documentElement, d = g.compatMode == "BackCompat"
    ? a
    : g.documentElement;
    return Math.max(f.scrollHeight, a.scrollHeight, d.clientHeight);
    }
  46. 原生JavaScript获取页面scrollLeft
    1
    2
    3
    4
    function getPageScrollLeft(){
    var a = document;
    return a.documentElement.scrollLeft || a.body.scrollLeft;
    }
  47. 原生JavaScript获取页面可视宽度
    1
    2
    3
    4
    5
    6
    function getPageViewWidth(){
    var d = document, a = d.compatMode == "BackCompat"
    ? d.body
    : d.documentElement;
    return a.clientWidth; // 可视宽度为clientWidth
    }
  48. 原生JavaScript获取页面宽度
    1
    2
    3
    4
    5
    6
    7
    // 考虑带滚动条的全部宽度
    function getPageWidth(){
    var g = document, a = g.body, f = g.documentElement, d = g.compatMode == "BackCompat"
    ? a
    : g.documentElement;
    return Math.max(f.scrollWidth, a.scrollWidth, d.clientWidth);
    }
  49. 原生JavaScript获取页面scrollTop
    1
    2
    3
    4
    function getPageScrollTop(){
    var a = document;
    return a.documentElement.scrollTop || a.body.scrollTop;
    }

文章字数:1045,阅读全文大约需要4分钟

主要功能是将指定文件加密到加密库中,以及从加密库中解密相应文件

相关文件

  • ShaUtil.java sha256工具类,主要用于密码签名成aes256的秘钥
  • AesUtil.java加密工具类
  • EncryptionFileProcessor.java单个文件加密,调用前面的工具类加密文件
  • FileSearchStream.java文件搜索主类,搜索根目录下的文件
  • EncryptionDirectoryProcessor.java调用搜索和加密类完成文件夹加密解密,查看操作
  • Test.java测试及演示类

加密相关工具

  • ShaUtil.java
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
package com.colin.tool.crypto;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
* sha256工具
*
* @author colin.cheng
* @date 2021-11-11
* @since 1.0.0
*/
public class ShaUtil {

private static final String KEY_ALGORITHM = "SHA-256";
private static final String DEFAULT_CHARSET = "UTF-8";

/**
* sha256签名
*
* @param str
* @return
* @throws NoSuchAlgorithmException
* @throws UnsupportedEncodingException
*/
public static byte[] encodingStr(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest messageDigest;
messageDigest = MessageDigest.getInstance(KEY_ALGORITHM);
messageDigest.update(str.getBytes(DEFAULT_CHARSET));
return messageDigest.digest();
}
}
  • AesUtil.java
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
package com.colin.tool.crypto;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
/**
* AES加密工具类
*
* @author colin.cheng
* @date 2021-11-11 10:11
* @since 1.0.0
*/
public class AesUtil {

/** 算法名 */
private static final String KEY_ALGORITHM = "AES";
/** 默认的加密算法及模式 */
private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";

/**
* AES 加密操作
*
* @param byteContent
* 待加密内容
* @param key
* 加密密钥
* @return 加密数据
*/
public static byte[] encrypt(byte[] byteContent, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
// 创建密码器
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
// 初始化为加密模式的密码器
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));
// 加密
return cipher.doFinal(byteContent);
}

public static void encryptByStream(InputStream from, OutputStream to, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IOException {
// 创建密码器
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
// 初始化为加密模式的密码器
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));
try (CipherInputStream cipherInputStream = new CipherInputStream(from, cipher)) {
int l;
byte[] cache = new byte[16 * 100];
while ((l = cipherInputStream.read(cache)) != -1) {
to.write(cache, 0, l);
to.flush();
}
}
}

public static void decryptByStream(InputStream from, OutputStream to, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IOException {
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
try (CipherOutputStream cipherOutputStream = new CipherOutputStream(to, cipher)){
int l;
byte[] cache = new byte[16 * 100];
while ((l = from.read(cache)) != -1) {
cipherOutputStream.write(cache, 0, l);
}
}
}

/**
* AES 加密操作,返回Base64字符串
*
* @param byteContent
* 待加密内容
* @param key
* 加密密钥
* @return Base64转码后的加密数据
*/
public static String base64Encrypt(byte[] byteContent, byte[] key) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
byte[] encrypt = encrypt(byteContent, key);
if (encrypt != null) {
return Base64.getEncoder().encodeToString(encrypt);
}
return null;
}

/**
* AES 解密操作
*
* @param content
* 密文
* @param key
* 秘钥
* @return 解密后的数据
*/
public static byte[] decrypt(byte[] content, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
// 实例化
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
// 使用密钥初始化,设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
// 执行操作
return cipher.doFinal(content);
}

/**
* AES 解密操作
*
* @param content
* base64形式的密文
* @param key
* 秘钥
* @return 解密后的数据
*/
public static byte[] decrypt(String content, byte[] key) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
if (content != null) {
byte[] decode = Base64.getDecoder().decode(content);
return decrypt(decode, key);
}
return null;
}

/**
* 生成加密秘钥
*
* @return 生成指定算法密钥生成器的 KeyGenerator 对象
*/
private static SecretKeySpec getSecretKey(final byte[] key) {
return new SecretKeySpec(key, KEY_ALGORITHM);
}
}

文件加密相关工具类

  • EncryptionFileProcessor.java
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
package com.colin.tool.file;

import com.colin.tool.crypto.AesUtil;
import com.colin.tool.crypto.ShaUtil;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;

/**
* 单个文件加密解密相关工具
*
* @author colin.cheng
* @date 2021-11-11
* @since 1.0.0
*/
public class EncryptionFileProcessor {

/** 全局秘钥 */
private byte[] key = null;
/** 默认是否保存源文件 */
private boolean saveResource = false;
/** 默认保存位置为源文件所在文件夹,可以自定义 */
private String toPath = null;

private static String cryptoSuffix = ".cl";
private static String cryptoPrefix = "cry-";

public EncryptionFileProcessor(String pwd) throws UnsupportedEncodingException, NoSuchAlgorithmException {
this.key = pwd != null ? ShaUtil.encodingStr(pwd) : null;
}

/**
* 设置全局秘钥
*
* @param pwd
* @throws UnsupportedEncodingException
* @throws NoSuchAlgorithmException
*/
public EncryptionFileProcessor setPwd(String pwd) throws UnsupportedEncodingException, NoSuchAlgorithmException {
this.key = pwd != null ? ShaUtil.encodingStr(pwd) : null;
return this;
}

/**
* 设置加密、解密生成的文件存放文件夹
*
* @param toPath
*/
public void setToPath(String toPath) {
this.toPath = toPath;
}

/**
* 设置是否保存源文件
*
* @param saveResource
*/
public EncryptionFileProcessor setSaveResource(boolean saveResource) {
this.saveResource = saveResource;
return this;
}

/**
* 加密文件
*
* @param resource
* @throws Exception
*/
public void encryptFile(File resource) throws Exception {
encryptFile(resource, key, saveResource, this.toPath);
}

/**
* 解密文件
*
* @param resource
* @throws Exception
*/
public void decryptFile(File resource) throws Exception {
decryptFile(resource, key, saveResource, this.toPath);
}

/**
* 加密文件名
*
* @param fileName
* @return
* @throws Exception
*/
public String encryptFileName(String fileName) throws Exception {
return encryptFileName(fileName, key);
}

/**
* 解密文件名
*
* @param fileName
* @return
* @throws Exception
*/
public String decryptFileName(String fileName) throws Exception {
return decryptFileName(fileName, key);
}

// static

/**
* 加密文件
*
* @param resource 源文件
* @param pwd 密码
* @param saveResource 加密之后是否删除源文件
* @param toPath 存放位置,空则放在源文件所在文件夹
* @throws Exception
*/
public static void encryptFile(File resource, String pwd, boolean saveResource, String toPath) throws Exception {
final byte[] key = ShaUtil.encodingStr(pwd);
encryptFile(resource, key, saveResource, toPath);
}

/**
* 解密文件
*
* @param resource 加密文件
* @param pwd 密码
* @param saveResource 解密之后是否删除加密文件
* @param toPath 存放位置,空则放在源文件所在文件夹
* @throws Exception
*/
public static void decryptFile(File resource, String pwd, boolean saveResource, String toPath) throws Exception {
final byte[] key = ShaUtil.encodingStr(pwd);
decryptFile(resource, key, saveResource, toPath);
}


/**
* 加密文件名
*
* @param fileName
* @param pwd
* @return
* @throws Exception
*/
public static String encryptFileName(String fileName, String pwd) throws Exception {
final byte[] key = ShaUtil.encodingStr(pwd);
return encryptFileName(fileName, key);
}

/**
* 解密文件名
*
* @param fileName
* @param pwd
* @return
* @throws Exception
*/
public static String decryptFileName(String fileName, String pwd) throws Exception {
final byte[] key = ShaUtil.encodingStr(pwd);
return decryptFileName(fileName, key);
}

// private

private static void decryptFile(File resource, byte[] key, boolean saveResource, String toPath) throws Exception {
if(resource.exists() && isEncryptedFileName(resource.getName())) {
assert key != null;
try (InputStream inputStream = new FileInputStream(resource)) {
final String encryptName = resource.getName();
final String fileName = decryptFileName(encryptName, key);
if(toPath == null || "".equals(toPath.trim())) {
toPath = resource.getParent();
}
final File file = new File(toPath + File.separator + fileName);
if(file.exists()) {
throw new RuntimeException("decrypt file is exists, encrypt name = [" + encryptName + "], decrypt name = [" + fileName + "]");
}
try (final FileOutputStream outputStream = new FileOutputStream(file)) {
AesUtil.decryptByStream(inputStream, outputStream, key);
}
}
if(!saveResource) {
resource.delete();
}
}
}

private static void encryptFile(File resource, byte[] key, boolean saveResource, String toPath) throws Exception {
if(resource.exists() && !isEncryptedFileName(resource.getName())) {
assert key != null;
try (FileInputStream inputStream = new FileInputStream(resource)) {
final String fileName = encryptFileName(resource.getName(), key);
if(toPath == null || "".equals(toPath.trim())) {
toPath = resource.getParent();
}
final File encryptFile = new File(toPath + File.separator + fileName);
if(encryptFile.exists()) {
throw new RuntimeException("encrypt file is exists! resource name = [" + fileName + "]");
}
try (final FileOutputStream outputStream = new FileOutputStream(encryptFile)){
AesUtil.encryptByStream(inputStream, outputStream, key);
}
}
if(!saveResource) {
resource.delete();
}
}
}

private static String encryptFileName(String fileName, byte[] key) throws Exception {
assert key != null;
if(!isEncryptedFileName(fileName)) {
String encrypt = AesUtil.base64Encrypt(fileName.getBytes(StandardCharsets.UTF_8), key);
assert encrypt != null;
return cryptoPrefix + encrypt.replace("/", "#") + cryptoSuffix;
}
return fileName;
}

private static String decryptFileName(String fileName, byte[] key) throws Exception {
assert key != null;
if(isEncryptedFileName(fileName)) {
fileName = fileName.replace("#", "/").replace(cryptoSuffix, "").replace(cryptoPrefix, "");
final byte[] decrypt = AesUtil.decrypt(fileName, key);
assert decrypt != null;
return new String(decrypt, StandardCharsets.UTF_8);
}
return fileName;
}

private static boolean isEncryptedFileName(String fileName) {
return fileName.startsWith(cryptoPrefix) && fileName.endsWith(cryptoSuffix);
}
}
  • FileSearchStream.java
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
package com.colin.tool.file;

import java.io.File;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;

/**
* 文件搜索流
*
* @author colin.cheng
* @since 1.0.0
*/
public class FileSearchStream {

private File[] root;
private boolean parallel;
private Consumer<File> afterConsumer;
private Function<File, Boolean> filter;
private boolean deep = true;

private FileSearchStream() {}

public FileSearchStream(File... root) {
init(root);
}

/**
* 获取一个查询对象
*
* @param root
* @return
*/
public static FileSearchStream of(File... root) {
return new FileSearchStream(root);
}

public boolean isDeep() {
return deep;
}

/** 如果是文件夹,是否遍历 */
public FileSearchStream setDeep(boolean deep) {
this.deep = deep;
return this;
}

/**
* 获取本地所有盘符
*/
public static File[] getSystemRoot() {
return File.listRoots();
}

/**
* 过滤条件
*
* @param filter
* @return
*/
public FileSearchStream filter(Function<File, Boolean> filter) {
this.filter = filter;
return this;
}

/**
* 找到之后如何处理
*
* @param afterConsumer
* @return
*/
public void forEach(Consumer<File> afterConsumer) {
this.afterConsumer = afterConsumer;
searchRoot();
}

/**
* 转换成list
*
* @param listFunction
* @param <T>
* @return
*/
public <T> List<T> toList(Function<File, T> listFunction) {
List<T> list = new LinkedList<>();
this.afterConsumer = file -> list.add(listFunction.apply(file));
searchRoot();
return list;
}

/**
* 分组保存
*
* @param keyFunction
* @param valFunction
* @param <T>
* @param <R>
* @return
*/
public <T, R> Map<T, List<R>> groupingBy(Function<File, T> keyFunction, Function<File, R> valFunction) {
Map<T, List<R>> res = new LinkedHashMap<>();
this.afterConsumer = file -> {
T key = keyFunction.apply(file);
R val = valFunction.apply(file);
if (res.containsKey(key)) {
res.get(key).add(val);
} else {
List<R> list = new LinkedList<>();
list.add(val);
res.put(key, list);
}
};
searchRoot();
return res;
}

/**
* 根据父级文件夹分组
*
* @return
*/
public Map<String, List<String>> groupingByPath() {
return groupingBy(File::getParent, File::getName);
}

/**
* 重置
*
* @return
*/
public FileSearchStream reset(File... root) {
init(root);
return this;
}

/**
* 初始化
*
* @param root
*/
private void init(File... root) {
this.root = root;
this.parallel = false;
this.afterConsumer = null;
this.filter = (file) -> true;
}

/**
* 开始搜索
*
* @return
*/
private void searchRoot() {
final Stream<File> fileStream = Arrays.stream(root);
if (parallel) {
fileStream.parallel().forEach(this::search);
} else {
fileStream.forEach(this::search);
}
}

/**
* 获取对应盘符下符合要求的文件
*/
private void search(File file) {
File[] f = file.listFiles();
if (f != null) {
if (f.length > 0) {
for (File files : f) {
if(deep) {
if (files.isDirectory()) {
search(files);
} else {
if (filter.apply(files)) {
if (afterConsumer != null) {
afterConsumer.accept(files);
}
}
}
} else {
if (filter.apply(files)) {
if (afterConsumer != null) {
afterConsumer.accept(files);
}
}
}
}
}
}
}

/**
* 文件后缀
*/
public enum FileSuffix {
/** 图片 */
IMG("psd", "pdd", "gif", "jpeg", "jpg", "png"),
/** 文档 */
DOCUMENT("doc", "docx", "xls", "xlsx", "csv", "ppt", "pptx", "txt"),
/** 程序 */
APPLICATION("exe", "bat", "cmd", "sh", "ink", "py", "class", "java"),
/** 音频 */
AUDIO("mp3", "flac", "ape", "cd", "wave", "aiff"),
/** 视频 */
VIDEO(
"avi", "mov", "qt", "asf", "rm", "navi", "divX", "mpeg", "mpg", "ogg", "mod", "rmvb", "flv", "mp4", "3gp");

private String[] suffix;

FileSuffix(String... suffix) {
this.suffix = suffix;
}

public boolean check(String fileName) {
if (fileName.contains(".")) {
String fileSuffix = fileName.split("\\.")[1];
fileSuffix = fileSuffix.toLowerCase();
for (String s : suffix) {
String b = s.toLowerCase();
if (fileSuffix.equals(b)) {
return true;
}
}
}
return false;
}

public String[] getSuffix() {
return suffix;
}
}
}
  • EncryptionDirectoryProcessor.java
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
package com.colin.tool.file;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;

/**
* 文件夹加密解密工具
*
* @author colin.cheng
* @date 2021-12-03
* @since 1.0.0
*/
public class EncryptionDirectoryProcessor {

private EncryptionFileProcessor processor;

private Consumer<File> searchLog = null;
private Consumer<File> processorLog = null;

/**
* 新建一个文件夹加密处理器
*
* @param pwd 密码
* @throws UnsupportedEncodingException
* @throws NoSuchAlgorithmException
*/
public EncryptionDirectoryProcessor(String pwd) throws UnsupportedEncodingException, NoSuchAlgorithmException {
this.processor = new EncryptionFileProcessor(pwd);
}

/**
* 是否保存源文件
*
* @param saveResource
* @return
*/
public EncryptionDirectoryProcessor setSaveResource(boolean saveResource) {
this.processor.setSaveResource(saveResource);
return this;
}

/**
* 设置文件存放位置,默认是源文件所在文件夹
*
* @param toPath
* @return
*/
public EncryptionDirectoryProcessor setToPath(String toPath) {
this.processor.setToPath(toPath);
return this;
}

/**
* 加密文件夹
*
* @param path
* @throws Exception
*/
public void encryptDirectory(String path) throws Exception {
assert this.processor != null;
encryptDirectory(path, this.processor, this.searchLog, this.processorLog);
}

/**
* 解密文件夹
*
* @param path
* @throws Exception
*/
public void decryptDirectory(String path) throws Exception {
assert this.processor != null;
decryptDirectory(path, this.processor, this.searchLog, this.processorLog);
}

/**
* 解密并查看文件夹内文件名
*
* @param path
* @param deep 如果内部包含文件夹,是否遍历文件夹
* @return
* @throws Exception
*/
public List<String> listDirectory(String path, boolean deep) throws Exception {
return listDirectory(path, this.processor, deep);
}

public Consumer<File> getSearchLog() {
return searchLog;
}

public void setSearchLog(Consumer<File> searchLog) {
this.searchLog = searchLog;
}

public Consumer<File> getProcessorLog() {
return processorLog;
}

public void setProcessorLog(Consumer<File> processorLog) {
this.processorLog = processorLog;
}

AtomicLong index;
AtomicLong processorIndex = new AtomicLong();

public EncryptionDirectoryProcessor defaultLog() {
this.index = new AtomicLong();
this.processorIndex = new AtomicLong();
this.setSearchLog(file ->
System.out.println("[" + index.incrementAndGet() + "] file find, path = [" + file.getPath() + "]"));
this.setProcessorLog(file ->
System.out.println("[" + processorIndex.incrementAndGet() + "/" + index.get() + "] file is Processor " + ((int) (((double) processorIndex.get() / (double) index.get()) * 100)) + "%"));
return this;
}

// static

public static void encryptDirectory(String path, EncryptionFileProcessor processor) throws Exception {
encryptDirectory(path, processor, null, null);
}

public static void encryptDirectory(String path, EncryptionFileProcessor processor, Consumer<File> searchLog, Consumer<File> processorLog) throws Exception {
List<File> fileList = new LinkedList<>();
FileSearchStream.of(new File(path)).forEach(file -> {
if(searchLog != null) {
searchLog.accept(file);
}
fileList.add(file);
});
for (File file : fileList) {
if(processorLog != null) {
processorLog.accept(file);
}
processor.encryptFile(file);
}
}

public static void decryptDirectory(String path, EncryptionFileProcessor processor) throws Exception {
decryptDirectory(path, processor, null, null);
}

public static void decryptDirectory(String path, EncryptionFileProcessor processor, Consumer<File> searchLog, Consumer<File> processorLog) throws Exception {
List<File> fileList = new LinkedList<>();
FileSearchStream.of(new File(path)).forEach(file -> {
if(searchLog != null) {
searchLog.accept(file);
}
fileList.add(file);
});
for (File file : fileList) {
if(processorLog != null) {
processorLog.accept(file);
}
processor.decryptFile(file);
}
}

public static List<String> listDirectory(String path, EncryptionFileProcessor processor, boolean deep) throws Exception {
List<String> res = new LinkedList<>();
for (File file : FileSearchStream.of(new File(path)).setDeep(deep).toList(file -> file)) {
if(file.isDirectory()) {
res.add("directory [" + file.getName() + "]");
} else {
res.add("file [" + processor.decryptFileName(file.getName()) + "]");
}
}
return res;
}
}

测试

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
package com.colin.tool;

import com.colin.tool.file.EncryptionDirectoryProcessor;

/**
*
* @author colin.cheng
* @date 2021-12-02
* @since 1.0.0
*/
public class Test {

public static void main(String[] args) throws Exception {

// 设置密码及默认打印日志
final EncryptionDirectoryProcessor processor = new EncryptionDirectoryProcessor("12333");

// 可选设置

// 使用内置的打印方法,也可以单独设置
//processor.defaultLog();
// 是否保存源文件,默认不保存
//processor.setSaveResource(true);
// 处理后的文件存放位置,默认是源文件所在文件夹
//processor.setToPath("D:\\test\\store");
// 也可以链式调用
// processor = new EncryptionDirectoryProcessor("12333").defaultLog().setSaveResource(true).setToPath("D:\\test\\store");

// 加密
processor.encryptDirectory("D:\\test");
// 查看加密文件原始信息,deep表示遍历子目录
processor.listDirectory("D:\\test", true).forEach(System.out::println);
// 解密
processor.decryptDirectory("D:\\test");
}
}

常用方法

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
package com.colin.tool.file;

/**
* @author colin.cheng
* @date
* @since 1.0.0
*/
public class EncryptionUtil {

/** 密码测试 */
public static String testPwd(String path, String... pwds) {
for (int i = 0; i < pwds.length; i++) {
try {
EncryptionDirectoryProcessor processor = new EncryptionDirectoryProcessor(pwds[i]);
processor.listDirectory(path,false);
return pwds[i];
} catch (Exception e) {}
}
return null;
}

public static void show(String path, String pwd) throws Exception {
// 设置密码及默认打印日志
final EncryptionDirectoryProcessor processor = new EncryptionDirectoryProcessor(pwd);
processor.listDirectory(path, true).forEach(System.out::println);
}

public static void encryptDirectory(String path, String pwd) throws Exception {
final EncryptionDirectoryProcessor processor = new EncryptionDirectoryProcessor(pwd);
processor.encryptDirectory(path);
}

public static void decryptDirectory(String path, String pwd) throws Exception {
final EncryptionDirectoryProcessor processor = new EncryptionDirectoryProcessor(pwd);
processor.decryptDirectory(path);
}
}

文章字数:2723,阅读全文大约需要10分钟

来自今日头条

  1. 原生JavaScript获取页面可视高度
    1
    2
    3
    4
    5
    6
    function getPageViewHeight() {
    var d = document, a = d.compatMode == "BackCompat"
    ? d.body
    : d.documentElement;
    return a.clientHeight;
    }
  2. 原生JavaScript跨浏览器添加事件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function addEvt(oTarget, sEvtType, fnHandle) {
    if(!oTarget) {return;}
    if(oTarget.addEventListener) {
    oTarget.addEventListener(sEvtType, fnHandle, false);
    } else if(oTarget.attachEvent) {
    oTarget.attachEvent("on" + sEvtType, fnHandle);
    } else {
    oTarget["on" + sEvtType] = fnHandle;
    }
    }
  3. 原生JavaScript跨浏览器删除事件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function delEvt(oTarget, sEvtType, fnHandle){
    if(!oTarget) {return;}
    if(oTarget.addEventListener) {
    oTarget.addEventListener(sEvtType,fnHandle,false);
    } else if(oTarget.attachEvent) {
    oTarget.attachEvent("on" + sEvtType,fnHandle);
    } else {
    oTarget["on" + sEvtType] = fnHandle;
    }
    }
  4. 原生JavaScript去掉url前缀
    1
    2
    3
    4
    5
    6
    7
    function removeUrlPrefix(a) {
    a = a.replace(/:/g,":").replace(/./g,".").replace(///g,"/");
    while(trim(a).toLowerCase().indexOf("http://") == 0) {
    a = trim(a.replace(/http:///i,""));
    }
    return a;
    }
  5. 原生JavaScript随机数时间戳
    1
    2
    3
    4
    function uniqueId() {
    var a = Math.random, b = parseInt;
    return Number(new Date()).toString()+b(10*a())+b(10*a())+b(10*a());
    }
  6. 原生JavaScript全角半角转换,iCase: 0全到半,1半到全,其他不转化
    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
    function chgCase(sStr,iCase){
    if(typeof sStr != "string" || sStr.length <= 0 || !(iCase === 0 || iCase == 1)){
    return sStr;
    }
    var i,oRs=[],iCode;
    if(iCase){/*半->全*/
    for(i=0; i<sStr.length;i+=1){
    iCode = sStr.charCodeAt(i);
    if(iCode == 32){
    iCode = 12288;
    }else if(iCode < 127){
    iCode += 65248;
    }
    oRs.push(String.fromCharCode(iCode));
    }
    }else{/*全->半*/
    for(i=0; i<sStr.length;i+=1){
    iCode = sStr.charCodeAt(i);
    if(iCode == 12288){
    iCode = 32;
    }else if(iCode > 65280 && iCode < 65375){
    iCode -= 65248;
    }
    oRs.push(String.fromCharCode(iCode));
    }
    }
    return oRs.join("");
    }
  7. 原生JavaScript确认是否键盘有效输入值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function checkKey(iKey){
    if(iKey == 32 || iKey == 229){return true;} /*空格和异常*/
    if(iKey>47 && iKey < 58){return true;} /*数字*/
    if(iKey>64 && iKey < 91){return true;} /*字母*/
    if(iKey>95 && iKey < 108){return true;} /*数字键盘1*/
    if(iKey>108 && iKey < 112){return true;} /*数字键盘2*/
    if(iKey>185 && iKey < 193){return true;} /*符号1*/
    if(iKey>218 && iKey < 223){return true;} /*符号2*/
    return false;
    }
  8. 原生JavaScript获取网页被卷去的位置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function getScrollXY() {
    return document.body.scrollTop ? {
    x: document.body.scrollLeft,
    y: document.body.scrollTop
    }: {
    x: document.documentElement.scrollLeft,
    y: document.documentElement.scrollTop
    }
    }
  9. 原生JavaScript另一种正则日期格式化函数+调用方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Date.prototype.format = function(format) { // author: meizz
    var o = {
    "M+" : this.getMonth() + 1, // month
    "d+" : this.getDate(), // day
    "h+" : this.getHours(), // hour
    "m+" : this.getMinutes(), // minute
    "s+" : this.getSeconds(), // second
    "q+" : Math.floor((this.getMonth() + 3) / 3), // quarter
    "S" : this.getMilliseconds() // millisecond
    }
    if(/(y+)/.test(format)) {
    format=format.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
    }
    for(var k in o)if(new RegExp("("+ k +")").test(format)) {
    format = format.replace(RegExp.$1, RegExp.$1.length==1 ? o[k] : ("00"+ o[k]).substr((""+ o[k]).length));
    }
    return format;
    }
    alert(new Date().format("yyyy-MM-dd hh:mm:ss"));
  10. 原生JavaScript时间个性化输出功能
    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
    /*
    1、< 60s, 显示为“刚刚”
    2、>= 1min && < 60 min, 显示与当前时间差“XX分钟前”
    3、>= 60min && < 1day, 显示与当前时间差“今天 XX:XX”
    4、>= 1day && < 1year, 显示日期“XX月XX日 XX:XX”
    5、>= 1year, 显示具体日期“XXXX年XX月XX日 XX:XX”
    */
    function timeFormat(time){
    var date = new Date(time)
    , curDate = new Date()
    , year = date.getFullYear()
    , month = date.getMonth() + 1
    , day = date.getDate()
    , hour = date.getHours()
    , minute = date.getMinutes()
    , curYear = curDate.getFullYear()
    , curHour = curDate.getHours()
    , timeStr;
    if(year < curYear){
    timeStr = year +'年'+ month +'月'+ day +'日 '+ hour +':'+ minute;
    }else{
    var pastTime = curDate - date
    , pastH = pastTime/3600000;
    if(pastH > curHour){
    timeStr = month +'月'+ day +'日 '+ hour +':'+ minute;
    }else if(pastH >= 1){
    timeStr = '今天 ' + hour +':'+ minute +'分';
    }else{
    var pastM = curDate.getMinutes() - minute;
    if(pastM > 1){
    timeStr = pastM +'分钟前';
    }else{
    timeStr = '刚刚';
    }
    }
    }
    return timeStr;
    }
  11. 原生JavaScript解决offsetX兼容性问题
    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
    // 针对火狐不支持offsetX/Y
    function getOffset(e) {
    var target = e.target, // 当前触发的目标对象
    eventCoord,
    pageCoord,
    offsetCoord;
    // 计算当前触发元素到文档的距离
    pageCoord = getPageCoord(target);
    // 计算光标到文档的距离
    eventCoord = {
    X : window.pageXOffset + e.clientX,
    Y : window.pageYOffset + e.clientY
    };
    // 相减获取光标到第一个定位的父元素的坐标
    offsetCoord = {
    X : eventCoord.X - pageCoord.X,
    Y : eventCoord.Y - pageCoord.Y
    };
    return offsetCoord;
    }
    function getPageCoord(element) {
    var coord = { X : 0, Y : 0 };
    // 计算从当前触发元素到根节点为止,
    // 各级 offsetParent 元素的 offsetLeft 或 offsetTop 值之和
    while (element){
    coord.X += element.offsetLeft;
    coord.Y += element.offsetTop;
    element = element.offsetParent;
    }
    return coord;
    }
  12. 原生JavaScript常用的正则表达式
    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
    //正整数
    /^[0-9]*[1-9][0-9]*$/;
    //负整数
    /^-[0-9]*[1-9][0-9]*$/;
    //正浮点数
    /^(([0-9]+.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*.[0-9]+)|([0-9]*[1-9][0-9]*))$/;
    //负浮点数
    /^(-(([0-9]+.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*.[0-9]+)|([0-9]*[1-9][0-9]*)))$/;
    //浮点数
    /^(-?d+)(.d+)?$/;
    //email地址
    /^[w-]+(.[w-]+)*@[w-]+(.[w-]+)+$/;
    //url地址
    /^[a-zA-z]+://(w+(-w+)*)(.(w+(-w+)*))*(?S*)?$/;
    //年/月/日(年-月-日、年.月.日)
    /^(19|20)dd[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$/;
    //匹配中文字符
    /[\u4e00-\u9fa5]/;
    //匹配帐号是否合法(字母开头,允许5-10字节,允许字母数字下划线)
    /^[a-zA-Z][a-zA-Z0-9_]{4,9}$/;
    //匹配空白行的正则表达式
    /
    s*
    /;
    //匹配中国邮政编码
    /[1-9]d{5}(?!d)/;
    //匹配身份证
    /d{15}|d{18}/;
    //匹配国内电话号码
    /(d{3}-|d{4}-)?(d{8}|d{7})?/;
    //匹配IP地址
    /((2[0-4]d|25[0-5]|[01]?dd?).){3}(2[0-4]d|25[0-5]|[01]?dd?)/;
    //匹配首尾空白字符的正则表达式
    /^s*|s*$/;
    //匹配HTML标记的正则表达式
    < (S*?)[^>]*>.*?|< .*? />;
  13. 原生JavaScript实现返回顶部的通用方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    function backTop(btnId) {
    var btn = document.getElementById(btnId);
    var d = document.documentElement;
    var b = document.body;
    window.onscroll = set;
    btn.style.display = "none";
    btn.onclick = function() {
    btn.style.display = "none";
    window.onscroll = null;
    this.timer = setInterval(function() {
    d.scrollTop -= Math.ceil((d.scrollTop + b.scrollTop) * 0.1);
    b.scrollTop -= Math.ceil((d.scrollTop + b.scrollTop) * 0.1);
    if ((d.scrollTop + b.scrollTop) == 0) clearInterval(btn.timer, window.onscroll = set);
    },
    10);
    };
    function set() {
    btn.style.display = (d.scrollTop + b.scrollTop > 100) ? 'block': "none";
    }
    };
    backTop('goTop');
  14. 原生JavaScript获得URL中的GET参数值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 用法:如果地址是 test.htm?t1=1&t2=2&t3=3, 那么能取得:GET["t1"], GET["t2"], GET["t3"]
    function get_get() {
    querystr = window.location.href.split("?");
    if(querystr[1]) {
    var GETs = querystr[1].split("&"),
    GET = new Array();
    for(i = 0; i < GETs.length; i++){
    tmp_arr = GETs[i].split("=");
    key = tmp_arr[0];
    GET[key] = tmp_arr[1];
    }
    }
    return querystr[1];
    }
  15. 原生JavaScript实现全选通用方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function checkall(form, prefix, checkall) {
    var checkall = checkall ? checkall : 'chkall';
    for(var i = 0; i < form.elements.length; i++) {
    var e = form.elements[i];
    if(e.type=="checkbox"){
    e.checked = form.elements[checkall].checked;
    }
    }
    }
  16. 原生JavaScript实现全部取消选择通用方法
    1
    2
    3
    4
    5
    6
    7
    function uncheckAll(form) {
    for (var i = 0; i < form.elements.length; i++){
    var e = form.elements[i];
    if (e.name != 'chkall')
    e.checked = !e.checked;
    }
    }
  17. 原生JavaScript实现打开一个窗体通用方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    function openWindow(url,windowName,width,height){
    var x = parseInt(screen.width / 2.0) - (width / 2.0);
    var y = parseInt(screen.height / 2.0) - (height / 2.0);
    var isMSIE= (navigator.appName == "Microsoft Internet Explorer");
    if (isMSIE) {
    var p = "resizable=1,location=no,scrollbars=no,width=";
    p = p+width;
    p = p+",height=";
    p = p+height;
    p = p+",left=";
    p = p+x;
    p = p+",top=";
    p = p+y;
    retval = window.open(url, windowName, p);
    } else {
    var win = window.open(url, "ZyiisPopup", "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=yes,modal=yes,width=" + width + ",height=" + height + ",resizable=no" );
    eval("try { win.resizeTo(width, height); } catch(e) { }");
    win.focus();
    }
    }
  18. 原生JavaScript判断是否为客户端设备
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function client(o){ 
    var b = navigator.userAgent.toLowerCase();
    var t = false;
    if (o == 'isOP'){
    t = b.indexOf('opera') > -1;
    }
    if (o == 'isIE'){
    t = b.indexOf('msie') > -1;
    }
    if (o == 'isFF'){
    t = b.indexOf('firefox') > -1;
    }
    return t;
    }
  19. 原生JavaScript获取单选按钮的值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function get_radio_value(field){
    if(field && field.length){
    for(var i = 0; i < field.length; i++){
    if(field[i].checked){
    return field[i].value;
    }
    }
    }else {
    return;
    }
    }
  20. 原生JavaScript获取复选框的值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function get_checkbox_value(field) { 
    if(field && field.length){
    for(var i = 0; i < field.length; i++){
    if(field[i].checked && !field[i].disabled){
    return field[i].value;
    }
    }
    } else {
    return;
    }
    }
  21. 原生JavaScript判断是否为邮箱
    1
    2
    3
    4
    5
    6
    7
    8
    function isEmail(str){
    var re=/^w+((-w+)|(.w+))*@[A-Za-z0-9]+((.|-)[A-Za-z0-9]+)*.[A-Za-z0-9]+$/;
    if (re.test(str) != true) {
    return false;
    }else{
    return true;
    }
    }
  22. 原生JavaScript判断是否有列表中的危险字符
    1
    2
    3
    4
    5
    6
    7
    8
    function isValidReg(chars){
    var re=/<|>|[|]|{|}|『|』|※||||§|||||||□||㊣|﹋|⊕|⊙|〒|ㄅ|ㄆ|ㄇ|ㄈ|ㄉ|ㄊ|ㄋ|ㄌ|ㄍ|ㄎ|ㄏ|ㄐ|ㄑ|ㄒ|ㄓ|ㄔ|ㄕ|ㄖ|ㄗ|ㄘ|ㄙ|ㄚ|ㄛ|ㄜ|ㄝ|ㄞ|ㄟ|ㄢ|ㄣ|ㄤ|ㄥ|ㄦ|ㄧ|ㄨ|ㄩ|■|▄|▆|*|@|#|^|\/;
    if (re.test( chars) == true) {
    return false;
    }else{
    return true;
    }
    }
  23. 原生JavaScript判断字符串是否大于规定的长度
    1
    2
    3
    4
    5
    6
    function isValidLength(chars, len) {
    if (chars.length < len) {
    return false;
    }
    return true;
    }
  24. 原生JavaScript判断字符串是为网址不区分大小写
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function isValidURL( chars ) {
    var re=/^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(S+.S+)$/;
    if (!isNULL(chars)) {
    chars = jsTrim(chars);
    if (chars.match(re) == null)
    return false;
    else
    return true;
    }
    return false;
    }
  25. 原生JavaScript判断字符串是否为小数
    1
    2
    3
    4
    5
    6
    7
    function isValidDecimal( chars ) {
    var re=/^d*.?d{1,2}$/;
    if (chars.match(re) == null)
    return false;
    else
    return true;
    }
  26. 原生JavaScript判断字符串是否为整数
    1
    2
    3
    4
    5
    6
    7
    function isNumber(chars) {
    var re=/^d*$/;
    if (chars.match(re) == null)
    return false;
    else
    return true;
    }
  27. 原生JavaScript判断字符串是否为浮点数
    1
    2
    3
    4
    5
    6
    7
    8
    function isFloat(str) {
    for(i=0;i<str.length;i++) {
    if((str.charAt(i)<"0" || str.charAt(i)>"9")&& str.charAt(i) != '.') {
    return false;
    }
    }
    return true;
    }
  28. 原生JavaScript判断字符是否为A-Za-z英文字母
    1
    2
    3
    4
    5
    6
    7
    function isLetters(str) {
    var re = /^[A-Za-z]+$/;
    if (str.match(re) == null)
    return false;
    else
    return true;
    }
  29. 原生JavaScript判断字符串是否邮政编码
    1
    2
    3
    4
    5
    6
    7
    function isValidPost( chars ) {
    var re=/^d{6}$/;
    if (chars.match(re) == null)
    return false;
    else
    return true;
    }
  30. 原生JavaScript判断字符是否空NULL
    1
    2
    3
    4
    5
    6
    7
    function isNULL( chars ) {
    if (chars == null)
    return true;
    if (jsTrim(chars).length == 0)
    return true;
    return false;
    }
  31. 原生JavaScript用正则表达式提取页面代码中所有网址
    1
    2
    3
    var aa = document.documentElement.outerHTML.match(/(url(|src=|href=)["']*([^"'()<>[] ]+)["')]*|(http://[w-.]+[^"'()<>[] ]+)/ig).join("
    ").replace(/^(src=|href=|url()["']*|["'>) ]*$/igm,"");
    alert(aa);
  32. 原生JavaScript用正则表达式清除相同的数组(低效率)
    1
    2
    3
    Array.prototype.unique = function() {
    return this.reverse().join(",").match(/([^,]+)(?!.*)/ig).reverse();
    }
  33. 原生JavaScript用正则表达式清除相同的数组(高效率)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    String.prototype.unique = function() {
    var x = this.split(/[
    ]+/);
    var y = '';
    for(var i = 0; i < x.length; i++){
    if(!new RegExp("^"+x[i].replace(/([^w])/ig,"\$1")+"$","igm").test(y)) {
    y + = x[i]+"
    ";
    }
    }
    return y;
    }
  34. 原生JavaScript用正则表达式按字母排序,对每行进行数组排序
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function SetSort(){
    var text = K1.value.split(/[
    ]/).sort().join("
    "); // 顺序
    var test = K1.value.split(/[
    ]/).sort().reverse().join("
    "); // 反序
    K1.value = (K1.value != text) ? text : test;
    }
  35. 原生JavaScript字符串反序
    1
    2
    3
    function IsReverse(text) {
    return text.split('').reverse().join('');
    }
  36. 原生JavaScript用正则表达式清除html代码中的脚本
    1
    2
    3
    function clear_script() {
    K1.valu e= K1.value.replace(/<script.*?>[sS]*?</script>|s+on[a-zA-Z]{3,16}s?=s?"[sS]*?"|s+on[a-zA-Z]{3,16}s?=s?'[sS]*?'|s+on[a-zA-Z]{3,16}s?=[^ >]+/ig,"");
    }
  37. 原生JavaScript动态执行JavaScript脚本
    1
    2
    3
    4
    5
    6
    7
    function javascript(){
    try{
    eval(K1.value);
    }catch(e){
    alert(e.message);
    }
    }
  38. 原生JavaScript动态执行VBScript脚本
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function vbscript() {
    try{
    var script = document.getElementById("K1").value;
    if(script.trim()=="") return;
    window.execScript('On Error Resume Next
    '+script+'
    If Err.Number<>0 Then
    MsgBox "请输入正确的VBScript脚本!",48,"脚本错误!"
    End If',"vbscript")
    } catch(e) {
    alert(e.message);
    }
    }
  39. 原生JavaScript实现金额大写转换函数
    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
    function transform(tranvalue) {
    try {
    var i = 1;
    var dw2 = new Array("", "万", "亿"); //大单位
    var dw1 = new Array("拾", "佰", "仟"); //小单位
    var dw = new Array("零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"); //整数部分用
    //以下是小写转换成大写显示在合计大写的文本框中
    //分离整数与小数
    var source = splits(tranvalue);
    var num = source[0];
    var dig = source[1];
    //转换整数部分
    var k1 = 0; //计小单位
    var k2 = 0; //计大单位
    var sum = 0;
    var str = "";
    var len = source[0].length; //整数的长度
    for (i = 1; i <= len; i++) {
    var n = source[0].charAt(len - i); //取得某个位数上的数字
    var bn = 0;
    if (len - i - 1 >= 0) {
    bn = source[0].charAt(len - i - 1); //取得某个位数前一位上的数字
    }
    sum = sum + Number(n);
    if (sum != 0) {
    str = dw[Number(n)].concat(str); //取得该数字对应的大写数字,并插入到str字符串的前面
    if (n == '0') sum = 0;
    }
    if (len - i - 1 >= 0) { //在数字范围内
    if (k1 != 3) { //加小单位
    if (bn != 0) {
    str = dw1[k1].concat(str);
    }
    k1++;
    } else { //不加小单位,加大单位
    k1 = 0;
    var temp = str.charAt(0);
    if (temp == "万" || temp == "亿") //若大单位前没有数字则舍去大单位
    str = str.substr(1, str.length - 1);
    str = dw2[k2].concat(str);
    sum = 0;
    }
    }
    if (k1 == 3) //小单位到千则大单位进一
    {
    k2++;
    }
    }
    //转换小数部分
    var strdig = "";
    if (dig != "") {
    var n = dig.charAt(0);
    if (n != 0) {
    strdig += dw[Number(n)] + "角"; //加数字
    }
    var n = dig.charAt(1);
    if (n != 0) {
    strdig += dw[Number(n)] + "分"; //加数字
    }
    }
    str += "元" + strdig;
    } catch(e) {
    return "0元";
    }
    return str;
    }
    //拆分整数与小数
    function splits(tranvalue) {
    var value = new Array('', '');
    temp = tranvalue.split(".");
    for (var i = 0; i < temp.length; i++) {
    value[i] = temp[i];
    }
    return value;
    }
  40. 原生JavaScript常用的正则表达式大收集
    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
    匹配中文字符的正则表达式: [\u4e00-\u9fa5] 
    匹配双字节字符(包括汉字在内):[^\x00-\xff]
    匹配空行的正则表达式:
    [s| ]*

    匹配 HTML 标记的正则表达式:<(.*)>.*</>|<(.*) />
    匹配首尾空格的正则表达式:(^s*)|(s*$)
    匹配 IP 地址的正则表达式:/(d+).(d+).(d+).(d+)/g
    匹配 Email 地址的正则表达式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
    匹配网址 URL 的正则表达式:http://(/[w-]+.)+[w-]+(/[w- ./?%&=]*)?
    sql 语句:^(select|drop|delete|create|update|insert).*$
    非负整数:^d+$
    正整数:^[0-9]*[1-9][0-9]*$
    非正整数:^((-d+)|(0+))$
    负整数:^-[0-9]*[1-9][0-9]*$
    整数:^-?d+$
    非负浮点数:^d+(.d+)?$
    正浮点数:^((0-9)+.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*.[0-9]+)|([0-9]*[1-9][0-9]*))$
    非正浮点数:^((-d+.d+)?)|(0+(.0+)?))$
    英文字符串:^[A-Za-z]+$
    英文大写串:^[A-Z]+$
    英文小写串:^[a-z]+$
    英文字符数字串:^[A-Za-z0-9]+$
    英数字加下划线串:^w+$
    E-mail地址:^[w-]+(.[w-]+)*@[w-]+(.[w-]+)+$
    URL:^[a-zA-Z]+://(w+(-w+)*)(.(w+(-w+)*))*(?s*)?$ 或:^http://[A-Za-z0-9]+.[A-Za-z0-9]+[/=?%-&_~`@[]':+!]*([^<>""])*$
    邮政编码:^[1-9]d{5}$
    电话号码:^(((d{2,3}))|(d{3}-))?((0d{2,3})|0d{2,3}-)?[1-9]d{6,7}(-d{1,4})?$
    手机号码:^(((d{2,3}))|(d{3}-))?13d{9}$
    双字节字符(包括汉字在内):^\x00-\xff
    匹配首尾空格:(^s*)|(s*$)
    匹配 HTML 标记:<(.*)>.*</>|<(.*) />
    匹配空行:
    [s| ]*

    提取信息中的网络链接:(h|H)(r|R)(e|E)(f|F) *= *('|")?(w|\|/|.)+('|"| *|>)?
    提取信息中的邮件地址:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
    提取信息中的图片链接:(s|S)(r|R)(c|C) *= *('|")?(w|\|/|.)+('|"| *|>)?
    提取信息中的 IP 地址:(d+).(d+).(d+).(d+)
    提取信息中的中国手机号码:(86)*0*13d{9}
    提取信息中的中国固定电话号码:((d{3,4})|d{3,4}-|s)?d{8}
    提取信息中的中国电话号码(包括移动和固定电话):((d{3,4})|d{3,4}-|s)?d{7,14}
    提取信息中的中国邮政编码:[1-9]{1}(d+){5}
    提取信息中的浮点数(即小数):(-?d*).?d+
    提取信息中的任何数字 :(-?d*)(.d+)?
    IP:(d+).(d+).(d+).(d+)
    电话区号:^0d{2,3}$
    腾讯 QQ 号:^[1-9]*[1-9][0-9]*$
    帐号(字母开头,允许 5-16 字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
    中文、英文、数字及下划线:^[\u4e00-\u9fa5_a-zA-Z0-9]+$
  41. 原生JavaScript实现窗体改变事件resize的操作(兼容所有的浏览器)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    (function(){
    var fn = function(){
    var w = document.documentElement ? document.documentElement.clientWidth : document.body.clientWidth
    ,r = 1255
    ,b = Element.extend(document.body)
    ,classname = b.className;
    if(w < r){
    // 当窗体的宽度小于1255的时候执行相应的操作
    }else{
    // 当窗体的宽度大于1255的时候执行相应的操作
    }
    }
    if(window.addEventListener){
    window.addEventListener('resize', function(){ fn(); });
    }else if(window.attachEvent){
    window.attachEvent('onresize', function(){ fn(); });
    }
    fn();
    })();
  42. 原生JavaScript用正则清除空格分左右
    1
    2
    3
    function ltrim(s){ return s.replace( /^(s*| *)/, ""); } 
    function rtrim(s){ return s.replace( /(s*| *)$/, ""); }
    function trim(s){ return ltrim(rtrim(s)); }
  43. 原生JavaScript判断变量是否空值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    /**
    * 判断变量是否空值
    * undefined, null, '', false, 0, [], {} 均返回true,否则返回false
    */
    function empty(v){
    switch (typeof v){
    case 'undefined' : return true;
    case 'string' : if(trim(v).length == 0) return true; break;
    case 'boolean' : if(!v) return true; break;
    case 'number' : if(0 === v) return true; break;
    case 'object' :
    if(null === v) return true;
    if(undefined !== v.length && v.length==0) return true;
    for(var k in v){return false;} return true;
    break;
    }
    return false;
    }
  44. 原生JavaScript实现base64解码
    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
    function base64_decode(data){
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,ac = 0,dec = "",tmp_arr = [];
    if (!data) { return data; }
    data += '';
    do {
    h1 = b64.indexOf(data.charAt(i++));
    h2 = b64.indexOf(data.charAt(i++));
    h3 = b64.indexOf(data.charAt(i++));
    h4 = b64.indexOf(data.charAt(i++));
    bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
    o1 = bits >> 16 & 0xff;
    o2 = bits >> 8 & 0xff;
    o3 = bits & 0xff;
    if (h3 == 64) {
    tmp_arr[ac++] = String.fromCharCode(o1);
    } else if (h4 == 64) {
    tmp_arr[ac++] = String.fromCharCode(o1, o2);
    } else {
    tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
    }
    } while (i < data.length);
    dec = tmp_arr.join('');
    dec = utf8_decode(dec);
    return dec;
    }
    95, 原生JavaScript实现utf8解码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    function utf8_decode(str_data){
    var tmp_arr = [],i = 0,ac = 0,c1 = 0,c2 = 0,c3 = 0;str_data += '';
    while (i < str_data.length) {
    c1 = str_data.charCodeAt(i);
    if (c1 < 128) {
    tmp_arr[ac++] = String.fromCharCode(c1);
    i++;
    } else if (c1 > 191 && c1 < 224) {
    c2 = str_data.charCodeAt(i + 1);
    tmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
    i += 2;
    } else {
    c2 = str_data.charCodeAt(i + 1);
    c3 = str_data.charCodeAt(i + 2);
    tmp_arr[ac++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
    i += 3;
    }
    }
    return tmp_arr.join('');
    }
  45. 原生JavaScript获取窗体可见范围的宽与高
    1
    2
    3
    4
    5
    6
    7
    function getViewSize() {
    var de = document.documentElement;
    var db = document.body;
    var viewW = de.clientWidth == 0 ? db.clientWidth : de.clientWidth;
    var viewH = de.clientHeight == 0 ? db.clientHeight : de.clientHeight;
    return Array(viewW ,viewH);
    }
  46. 原生JavaScript判断IE版本号(既简洁、又向后兼容!)
    1
    2
    3
    4
    5
    6
    7
    8
    var _IE = (function(){
    var v = 3, div = document.createElement('div'), all = div.getElementsByTagName('i');
    while (
    div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
    all[0]
    );
    return v > 4 ? v : false ;
    }());
  47. 原生JavaScript获取浏览器版本号
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function browserVersion(types) {
    var other = 1;
    for (i in types) {
    var v = types[i] ? types[i] : i;
    if (USERAGENT.indexOf(v) != -1) {
    var re = new RegExp(v + '(\/|\s|:)([\d\.]+)', 'ig');
    var matches = re.exec(USERAGENT);
    var ver = matches != null ? matches[2] : 0;
    other = ver !== 0 && v != 'mozilla' ? 0 : other;
    } else {
    var ver = 0;
    }
    eval('BROWSER.' + i + '= ver');
    }
    BROWSER.other = other;
    }
  48. 原生JavaScript半角转换为全角函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function ToDBC(str){
    var result = '';
    for(var i=0; i < str.length; i++){
    code = str.charCodeAt(i);
    if(code >= 33 && code <= 126){
    result += String.fromCharCode(str.charCodeAt(i) + 65248);
    }else if (code == 32){
    result += String.fromCharCode(str.charCodeAt(i) + 12288 - 32);
    }else{
    result += str.charAt(i);
    }
    }
    return result;
    }
  49. 原生JavaScript全角转换为半角函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function ToCDB(str){
    var result = '';
    for(var i=0; i < str.length; i++){
    code = str.charCodeAt(i);
    if(code >= 65281 && code <= 65374){
    result += String.fromCharCode(str.charCodeAt(i) - 65248);
    }else if (code == 12288){
    result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32);
    }else{
    result += str.charAt(i);
    }
    }
    return result;
    }

文章字数:6058,阅读全文大约需要24分钟

maven是apache的一个纯java的管理项目构建,依赖构建,项目报告,项目文档等步骤的工具。
maven基于POM( Project Object Model,项目对象模型 )这个xml文档里的项目信息管理构建项目

基本构成

所有 POM 文件都需要 project 元素和三个必需字段:groupId,artifactId,version。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<project xmlns = "http://maven.apache.org/POM/4.0.0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">

<!-- 模型版本 -->
<modelVersion>4.0.0</modelVersion>
<!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如com.companyname.project-group,maven会将该项目打成的jar包放本地路径:/com/companyname/project-group -->
<groupId>com.companyname.project-group</groupId>

<!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->
<artifactId>project</artifactId>

<!-- 版本号 -->
<version>1.0</version>
</project>

除了以上的基本信息外,还有很多默认信息。maven没有指定父级pom(Super pom)时会指定一个默认的父级。父级和自身的构建信息组成了effective pom,这是maven执行的依据。
查看effective pom-也就是父级+自身配置

1
mvn help:effective-pom

maven 配置文件

类型 位置
项目级(Per Project) 定义在项目的POM文件pom.xml中
用户级 (Per User) 定义在Maven的设置xml文件中 (%USER_HOME%/.m2/settings.xml)
全局(Global) 定义在 Maven 全局的设置 xml 文件中 (%M2_HOME%/conf/settings.xml)

也可以在pom中写入多个profile信息,并激活某一个

1
2
//-P+id
mvn test -Pporfileid

仓库

maven通过中央仓库(maven提供),本地仓库(使用过的都会保存在本地),远程仓库(自定义)组成

远程仓库定义,先本地找,再中央仓库找不到会去远程找再找不到报错。

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
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.companyname.projectgroup</groupId>
<artifactId>project</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>com.companyname.common-lib</groupId>
<artifactId>common-lib</artifactId>
<version>1.0.0</version>
</dependency>
<dependencies>
<repositories>
<repository>
<id>companyname.lib1</id>
<url>http://download.companyname.org/maven2/lib1</url>
</repository>
<repository>
<id>companyname.lib2</id>
<url>http://download.companyname.org/maven2/lib2</url>
</repository>
</repositories>
</project>

alibaba国内maven镜像,可以解决maven仓库速度慢的问题
maven根目录->conf->setting.xml添加到mirrors节点下。

1
2
3
4
5
6
7
8
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>

pom里添加

1
2
3
4
5
6
7
8
9
10
11
12
13
<repositories>  
<repository>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>

其它功能

  • 快照,相对于版本,快照信息可以自动获取最新的快照,而版本则是固定的。在开发阶段快照比较试用
  • 文档构建,maven可以生成软件说明文档
  • 自动化构建部署
  • 依赖管理,插件使用

maven标签大全

摘自菜鸟教程,control+f可以快速查找标签信息。

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
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/maven-v4_0_0.xsd">
<!--父项目的坐标。如果项目中没有规定某个元素的值,那么父项目中的对应值即为项目的默认值。 坐标包括group ID,artifact ID和
version。 -->
<parent>
<!--被继承的父项目的构件标识符 -->
<artifactId />
<!--被继承的父项目的全球唯一标识符 -->
<groupId />
<!--被继承的父项目的版本 -->
<version />
<!-- 父项目的pom.xml文件的相对路径。相对路径允许你选择一个不同的路径。默认值是../pom.xml。Maven首先在构建当前项目的地方寻找父项
目的pom,其次在文件系统的这个位置(relativePath位置),然后在本地仓库,最后在远程仓库寻找父项目的pom。 -->
<relativePath />
</parent>
<!--声明项目描述符遵循哪一个POM模型版本。模型本身的版本很少改变,虽然如此,但它仍然是必不可少的,这是为了当Maven引入了新的特性或者其他模型变更的时候,确保稳定性。 -->
<modelVersion>4.0.0</modelVersion>
<!--项目的全球唯一标识符,通常使用全限定的包名区分该项目和其他项目。并且构建时生成的路径也是由此生成, 如com.mycompany.app生成的相对路径为:/com/mycompany/app -->
<groupId>asia.banseon</groupId>
<!-- 构件的标识符,它和group ID一起唯一标识一个构件。换句话说,你不能有两个不同的项目拥有同样的artifact ID和groupID;在某个
特定的group ID下,artifact ID也必须是唯一的。构件是项目产生的或使用的一个东西,Maven为项目产生的构件包括:JARs,源 码,二进制发布和WARs等。 -->
<artifactId>banseon-maven2</artifactId>
<!--项目产生的构件类型,例如jar、war、ear、pom。插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型 -->
<packaging>jar</packaging>
<!--项目当前版本,格式为:主版本.次版本.增量版本-限定版本号 -->
<version>1.0-SNAPSHOT</version>
<!--项目的名称, Maven产生的文档用 -->
<name>banseon-maven</name>
<!--项目主页的URL, Maven产生的文档用 -->
<url>http://www.baidu.com/banseon</url>
<!-- 项目的详细描述, Maven 产生的文档用。 当这个元素能够用HTML格式描述时(例如,CDATA中的文本会被解析器忽略,就可以包含HTML标
签), 不鼓励使用纯文本描述。如果你需要修改产生的web站点的索引页面,你应该修改你自己的索引页文件,而不是调整这里的文档。 -->
<description>A maven project to study maven.</description>
<!--描述了这个项目构建环境中的前提条件。 -->
<prerequisites>
<!--构建该项目或使用该插件所需要的Maven的最低版本 -->
<maven />
</prerequisites>
<!--项目的问题管理系统(Bugzilla, Jira, Scarab,或任何你喜欢的问题管理系统)的名称和URL,本例为 jira -->
<issueManagement>
<!--问题管理系统(例如jira)的名字, -->
<system>jira</system>
<!--该项目使用的问题管理系统的URL -->
<url>http://jira.baidu.com/banseon</url>
</issueManagement>
<!--项目持续集成信息 -->
<ciManagement>
<!--持续集成系统的名字,例如continuum -->
<system />
<!--该项目使用的持续集成系统的URL(如果持续集成系统有web接口的话)。 -->
<url />
<!--构建完成时,需要通知的开发者/用户的配置项。包括被通知者信息和通知条件(错误,失败,成功,警告) -->
<notifiers>
<!--配置一种方式,当构建中断时,以该方式通知用户/开发者 -->
<notifier>
<!--传送通知的途径 -->
<type />
<!--发生错误时是否通知 -->
<sendOnError />
<!--构建失败时是否通知 -->
<sendOnFailure />
<!--构建成功时是否通知 -->
<sendOnSuccess />
<!--发生警告时是否通知 -->
<sendOnWarning />
<!--不赞成使用。通知发送到哪里 -->
<address />
<!--扩展配置项 -->
<configuration />
</notifier>
</notifiers>
</ciManagement>
<!--项目创建年份,4位数字。当产生版权信息时需要使用这个值。 -->
<inceptionYear />
<!--项目相关邮件列表信息 -->
<mailingLists>
<!--该元素描述了项目相关的所有邮件列表。自动产生的网站引用这些信息。 -->
<mailingList>
<!--邮件的名称 -->
<name>Demo</name>
<!--发送邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建 -->
<post>banseon@126.com</post>
<!--订阅邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建 -->
<subscribe>banseon@126.com</subscribe>
<!--取消订阅邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建 -->
<unsubscribe>banseon@126.com</unsubscribe>
<!--你可以浏览邮件信息的URL -->
<archive>http:/hi.baidu.com/banseon/demo/dev/</archive>
</mailingList>
</mailingLists>
<!--项目开发者列表 -->
<developers>
<!--某个项目开发者的信息 -->
<developer>
<!--SCM里项目开发者的唯一标识符 -->
<id>HELLO WORLD</id>
<!--项目开发者的全名 -->
<name>banseon</name>
<!--项目开发者的email -->
<email>banseon@126.com</email>
<!--项目开发者的主页的URL -->
<url />
<!--项目开发者在项目中扮演的角色,角色元素描述了各种角色 -->
<roles>
<role>Project Manager</role>
<role>Architect</role>
</roles>
<!--项目开发者所属组织 -->
<organization>demo</organization>
<!--项目开发者所属组织的URL -->
<organizationUrl>http://hi.baidu.com/banseon</organizationUrl>
<!--项目开发者属性,如即时消息如何处理等 -->
<properties>
<dept>No</dept>
</properties>
<!--项目开发者所在时区, -11到12范围内的整数。 -->
<timezone>-5</timezone>
</developer>
</developers>
<!--项目的其他贡献者列表 -->
<contributors>
<!--项目的其他贡献者。参见developers/developer元素 -->
<contributor>
<name />
<email />
<url />
<organization />
<organizationUrl />
<roles />
<timezone />
<properties />
</contributor>
</contributors>
<!--该元素描述了项目所有License列表。 应该只列出该项目的license列表,不要列出依赖项目的 license列表。如果列出多个license,用户可以选择它们中的一个而不是接受所有license。 -->
<licenses>
<!--描述了项目的license,用于生成项目的web站点的license页面,其他一些报表和validation也会用到该元素。 -->
<license>
<!--license用于法律上的名称 -->
<name>Apache 2</name>
<!--官方的license正文页面的URL -->
<url>http://www.baidu.com/banseon/LICENSE-2.0.txt</url>
<!--项目分发的主要方式: repo,可以从Maven库下载 manual, 用户必须手动下载和安装依赖 -->
<distribution>repo</distribution>
<!--关于license的补充信息 -->
<comments>A business-friendly OSS license</comments>
</license>
</licenses>
<!--SCM(Source Control Management)标签允许你配置你的代码库,供Maven web站点和其它插件使用。 -->
<scm>
<!--SCM的URL,该URL描述了版本库和如何连接到版本库。欲知详情,请看SCMs提供的URL格式和列表。该连接只读。 -->
<connection>
scm:svn:http://svn.baidu.com/banseon/maven/banseon/banseon-maven2-trunk(dao-trunk)
</connection>
<!--给开发者使用的,类似connection元素。即该连接不仅仅只读 -->
<developerConnection>
scm:svn:http://svn.baidu.com/banseon/maven/banseon/dao-trunk
</developerConnection>
<!--当前代码的标签,在开发阶段默认为HEAD -->
<tag />
<!--指向项目的可浏览SCM库(例如ViewVC或者Fisheye)的URL。 -->
<url>http://svn.baidu.com/banseon</url>
</scm>
<!--描述项目所属组织的各种属性。Maven产生的文档用 -->
<organization>
<!--组织的全名 -->
<name>demo</name>
<!--组织主页的URL -->
<url>http://www.baidu.com/banseon</url>
</organization>
<!--构建项目需要的信息 -->
<build>
<!--该元素设置了项目源码目录,当构建项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。 -->
<sourceDirectory />
<!--该元素设置了项目脚本源码目录,该目录和源码目录不同:绝大多数情况下,该目录下的内容 会被拷贝到输出目录(因为脚本是被解释的,而不是被编译的)。 -->
<scriptSourceDirectory />
<!--该元素设置了项目单元测试使用的源码目录,当测试项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。 -->
<testSourceDirectory />
<!--被编译过的应用程序class文件存放的目录。 -->
<outputDirectory />
<!--被编译过的测试class文件存放的目录。 -->
<testOutputDirectory />
<!--使用来自该项目的一系列构建扩展 -->
<extensions>
<!--描述使用到的构建扩展。 -->
<extension>
<!--构建扩展的groupId -->
<groupId />
<!--构建扩展的artifactId -->
<artifactId />
<!--构建扩展的版本 -->
<version />
</extension>
</extensions>
<!--当项目没有规定目标(Maven2 叫做阶段)时的默认值 -->
<defaultGoal />
<!--这个元素描述了项目相关的所有资源路径列表,例如和项目相关的属性文件,这些资源被包含在最终的打包文件里。 -->
<resources>
<!--这个元素描述了项目相关或测试相关的所有资源路径 -->
<resource>
<!-- 描述了资源的目标路径。该路径相对target/classes目录(例如${project.build.outputDirectory})。举个例
子,如果你想资源在特定的包里(org.apache.maven.messages),你就必须该元素设置为org/apache/maven /messages。然而,如果你只是想把资源放到源码目录结构里,就不需要该配置。 -->
<targetPath />
<!--是否使用参数值代替参数名。参数值取自properties元素或者文件里配置的属性,文件在filters元素里列出。 -->
<filtering />
<!--描述存放资源的目录,该路径相对POM路径 -->
<directory />
<!--包含的模式列表,例如**/*.xml. -->
<includes />
<!--排除的模式列表,例如**/*.xml -->
<excludes />
</resource>
</resources>
<!--这个元素描述了单元测试相关的所有资源路径,例如和单元测试相关的属性文件。 -->
<testResources>
<!--这个元素描述了测试相关的所有资源路径,参见build/resources/resource元素的说明 -->
<testResource>
<targetPath />
<filtering />
<directory />
<includes />
<excludes />
</testResource>
</testResources>
<!--构建产生的所有文件存放的目录 -->
<directory />
<!--产生的构件的文件名,默认值是${artifactId}-${version}。 -->
<finalName />
<!--当filtering开关打开时,使用到的过滤器属性文件列表 -->
<filters />
<!--子项目可以引用的默认插件信息。该插件配置项直到被引用时才会被解析或绑定到生命周期。给定插件的任何本地配置都会覆盖这里的配置 -->
<pluginManagement>
<!--使用的插件列表 。 -->
<plugins>
<!--plugin元素包含描述插件所需要的信息。 -->
<plugin>
<!--插件在仓库里的group ID -->
<groupId />
<!--插件在仓库里的artifact ID -->
<artifactId />
<!--被使用的插件的版本(或版本范围) -->
<version />
<!--是否从该插件下载Maven扩展(例如打包和类型处理器),由于性能原因,只有在真需要下载时,该元素才被设置成enabled。 -->
<extensions />
<!--在构建生命周期中执行一组目标的配置。每个目标可能有不同的配置。 -->
<executions>
<!--execution元素包含了插件执行需要的信息 -->
<execution>
<!--执行目标的标识符,用于标识构建过程中的目标,或者匹配继承过程中需要合并的执行目标 -->
<id />
<!--绑定了目标的构建生命周期阶段,如果省略,目标会被绑定到源数据里配置的默认阶段 -->
<phase />
<!--配置的执行目标 -->
<goals />
<!--配置是否被传播到子POM -->
<inherited />
<!--作为DOM对象的配置 -->
<configuration />
</execution>
</executions>
<!--项目引入插件所需要的额外依赖 -->
<dependencies>
<!--参见dependencies/dependency元素 -->
<dependency>
......
</dependency>
</dependencies>
<!--任何配置是否被传播到子项目 -->
<inherited />
<!--作为DOM对象的配置 -->
<configuration />
</plugin>
</plugins>
</pluginManagement>
<!--使用的插件列表 -->
<plugins>
<!--参见build/pluginManagement/plugins/plugin元素 -->
<plugin>
<groupId />
<artifactId />
<version />
<extensions />
<executions>
<execution>
<id />
<phase />
<goals />
<inherited />
<configuration />
</execution>
</executions>
<dependencies>
<!--参见dependencies/dependency元素 -->
<dependency>
......
</dependency>
</dependencies>
<goals />
<inherited />
<configuration />
</plugin>
</plugins>
</build>
<!--在列的项目构建profile,如果被激活,会修改构建处理 -->
<profiles>
<!--根据环境参数或命令行参数激活某个构建处理 -->
<profile>
<!--构建配置的唯一标识符。即用于命令行激活,也用于在继承时合并具有相同标识符的profile。 -->
<id />
<!--自动触发profile的条件逻辑。Activation是profile的开启钥匙。profile的力量来自于它 能够在某些特定的环境中自动使用某些特定的值;这些环境通过activation元素指定。activation元素并不是激活profile的唯一方式。 -->
<activation>
<!--profile默认是否激活的标志 -->
<activeByDefault />
<!--当匹配的jdk被检测到,profile被激活。例如,1.4激活JDK1.4,1.4.0_2,而!1.4激活所有版本不是以1.4开头的JDK。 -->
<jdk />
<!--当匹配的操作系统属性被检测到,profile被激活。os元素可以定义一些操作系统相关的属性。 -->
<os>
<!--激活profile的操作系统的名字 -->
<name>Windows XP</name>
<!--激活profile的操作系统所属家族(如 'windows') -->
<family>Windows</family>
<!--激活profile的操作系统体系结构 -->
<arch>x86</arch>
<!--激活profile的操作系统版本 -->
<version>5.1.2600</version>
</os>
<!--如果Maven检测到某一个属性(其值可以在POM中通过${名称}引用),其拥有对应的名称和值,Profile就会被激活。如果值 字段是空的,那么存在属性名称字段就会激活profile,否则按区分大小写方式匹配属性值字段 -->
<property>
<!--激活profile的属性的名称 -->
<name>mavenVersion</name>
<!--激活profile的属性的值 -->
<value>2.0.3</value>
</property>
<!--提供一个文件名,通过检测该文件的存在或不存在来激活profile。missing检查文件是否存在,如果不存在则激活 profile。另一方面,exists则会检查文件是否存在,如果存在则激活profile。 -->
<file>
<!--如果指定的文件存在,则激活profile。 -->
<exists>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/
</exists>
<!--如果指定的文件不存在,则激活profile。 -->
<missing>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/
</missing>
</file>
</activation>
<!--构建项目所需要的信息。参见build元素 -->
<build>
<defaultGoal />
<resources>
<resource>
<targetPath />
<filtering />
<directory />
<includes />
<excludes />
</resource>
</resources>
<testResources>
<testResource>
<targetPath />
<filtering />
<directory />
<includes />
<excludes />
</testResource>
</testResources>
<directory />
<finalName />
<filters />
<pluginManagement>
<plugins>
<!--参见build/pluginManagement/plugins/plugin元素 -->
<plugin>
<groupId />
<artifactId />
<version />
<extensions />
<executions>
<execution>
<id />
<phase />
<goals />
<inherited />
<configuration />
</execution>
</executions>
<dependencies>
<!--参见dependencies/dependency元素 -->
<dependency>
......
</dependency>
</dependencies>
<goals />
<inherited />
<configuration />
</plugin>
</plugins>
</pluginManagement>
<plugins>
<!--参见build/pluginManagement/plugins/plugin元素 -->
<plugin>
<groupId />
<artifactId />
<version />
<extensions />
<executions>
<execution>
<id />
<phase />
<goals />
<inherited />
<configuration />
</execution>
</executions>
<dependencies>
<!--参见dependencies/dependency元素 -->
<dependency>
......
</dependency>
</dependencies>
<goals />
<inherited />
<configuration />
</plugin>
</plugins>
</build>
<!--模块(有时称作子项目) 被构建成项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径 -->
<modules />
<!--发现依赖和扩展的远程仓库列表。 -->
<repositories>
<!--参见repositories/repository元素 -->
<repository>
<releases>
<enabled />
<updatePolicy />
<checksumPolicy />
</releases>
<snapshots>
<enabled />
<updatePolicy />
<checksumPolicy />
</snapshots>
<id />
<name />
<url />
<layout />
</repository>
</repositories>
<!--发现插件的远程仓库列表,这些插件用于构建和报表 -->
<pluginRepositories>
<!--包含需要连接到远程插件仓库的信息.参见repositories/repository元素 -->
<pluginRepository>
<releases>
<enabled />
<updatePolicy />
<checksumPolicy />
</releases>
<snapshots>
<enabled />
<updatePolicy />
<checksumPolicy />
</snapshots>
<id />
<name />
<url />
<layout />
</pluginRepository>
</pluginRepositories>
<!--该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。它们自动从项目定义的仓库中下载。要获取更多信息,请看项目依赖机制。 -->
<dependencies>
<!--参见dependencies/dependency元素 -->
<dependency>
......
</dependency>
</dependencies>
<!--不赞成使用. 现在Maven忽略该元素. -->
<reports />
<!--该元素包括使用报表插件产生报表的规范。当用户执行"mvn site",这些报表就会运行。 在页面导航栏能看到所有报表的链接。参见reporting元素 -->
<reporting>
......
</reporting>
<!--参见dependencyManagement元素 -->
<dependencyManagement>
<dependencies>
<!--参见dependencies/dependency元素 -->
<dependency>
......
</dependency>
</dependencies>
</dependencyManagement>
<!--参见distributionManagement元素 -->
<distributionManagement>
......
</distributionManagement>
<!--参见properties元素 -->
<properties />
</profile>
</profiles>
<!--模块(有时称作子项目) 被构建成项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径 -->
<modules />
<!--发现依赖和扩展的远程仓库列表。 -->
<repositories>
<!--包含需要连接到远程仓库的信息 -->
<repository>
<!--如何处理远程仓库里发布版本的下载 -->
<releases>
<!--true或者false表示该仓库是否为下载某种类型构件(发布版,快照版)开启。 -->
<enabled />
<!--该元素指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳。这里的选项是:always(一直),daily(默认,每日),interval:X(这里X是以分钟为单位的时间间隔),或者never(从不)。 -->
<updatePolicy />
<!--当Maven验证构件校验文件失败时该怎么做:ignore(忽略),fail(失败),或者warn(警告)。 -->
<checksumPolicy />
</releases>
<!-- 如何处理远程仓库里快照版本的下载。有了releases和snapshots这两组配置,POM就可以在每个单独的仓库中,为每种类型的构件采取不同的
策略。例如,可能有人会决定只为开发目的开启对快照版本下载的支持。参见repositories/repository/releases元素 -->
<snapshots>
<enabled />
<updatePolicy />
<checksumPolicy />
</snapshots>
<!--远程仓库唯一标识符。可以用来匹配在settings.xml文件里配置的远程仓库 -->
<id>banseon-repository-proxy</id>
<!--远程仓库名称 -->
<name>banseon-repository-proxy</name>
<!--远程仓库URL,按protocol://hostname/path形式 -->
<url>http://192.168.1.169:9999/repository/</url>
<!-- 用于定位和排序构件的仓库布局类型-可以是default(默认)或者legacy(遗留)。Maven 2为其仓库提供了一个默认的布局;然
而,Maven 1.x有一种不同的布局。我们可以使用该元素指定布局是default(默认)还是legacy(遗留)。 -->
<layout>default</layout>
</repository>
</repositories>
<!--发现插件的远程仓库列表,这些插件用于构建和报表 -->
<pluginRepositories>
<!--包含需要连接到远程插件仓库的信息.参见repositories/repository元素 -->
<pluginRepository>
......
</pluginRepository>
</pluginRepositories>


<!--该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。它们自动从项目定义的仓库中下载。要获取更多信息,请看项目依赖机制。 -->
<dependencies>
<dependency>
<!--依赖的group ID -->
<groupId>org.apache.maven</groupId>
<!--依赖的artifact ID -->
<artifactId>maven-artifact</artifactId>
<!--依赖的版本号。 在Maven 2里, 也可以配置成版本号的范围。 -->
<version>3.8.1</version>
<!-- 依赖类型,默认类型是jar。它通常表示依赖的文件的扩展名,但也有例外。一个类型可以被映射成另外一个扩展名或分类器。类型经常和使用的打包方式对应,
尽管这也有例外。一些类型的例子:jar,war,ejb-client和test-jar。如果设置extensions为 true,就可以在 plugin里定义新的类型。所以前面的类型的例子不完整。 -->
<type>jar</type>
<!-- 依赖的分类器。分类器可以区分属于同一个POM,但不同构建方式的构件。分类器名被附加到文件名的版本号后面。例如,如果你想要构建两个单独的构件成
JAR,一个使用Java 1.4编译器,另一个使用Java 6编译器,你就可以使用分类器来生成两个单独的JAR构件。 -->
<classifier></classifier>
<!--依赖范围。在项目发布过程中,帮助决定哪些构件被包括进来。欲知详情请参考依赖机制。 - compile :默认范围,用于编译 - provided:类似于编译,但支持你期待jdk或者容器提供,类似于classpath
- runtime: 在执行时需要使用 - test: 用于test任务时使用 - system: 需要外在提供相应的元素。通过systemPath来取得
- systemPath: 仅用于范围为system。提供相应的路径 - optional: 当项目自身被依赖时,标注依赖是否传递。用于连续依赖时使用 -->
<scope>test</scope>
<!--仅供system范围使用。注意,不鼓励使用这个元素,并且在新的版本中该元素可能被覆盖掉。该元素为依赖规定了文件系统上的路径。需要绝对路径而不是相对路径。推荐使用属性匹配绝对路径,例如${java.home}。 -->
<systemPath></systemPath>
<!--当计算传递依赖时, 从依赖构件列表里,列出被排除的依赖构件集。即告诉maven你只依赖指定的项目,不依赖项目的依赖。此元素主要用于解决版本冲突问题 -->
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
<!--可选依赖,如果你在项目B中把C依赖声明为可选,你就需要在依赖于B的项目(例如项目A)中显式的引用对C的依赖。可选依赖阻断依赖的传递性。 -->
<optional>true</optional>
</dependency>
</dependencies>
<!--不赞成使用. 现在Maven忽略该元素. -->
<reports></reports>
<!--该元素描述使用报表插件产生报表的规范。当用户执行"mvn site",这些报表就会运行。 在页面导航栏能看到所有报表的链接。 -->
<reporting>
<!--true,则,网站不包括默认的报表。这包括"项目信息"菜单中的报表。 -->
<excludeDefaults />
<!--所有产生的报表存放到哪里。默认值是${project.build.directory}/site。 -->
<outputDirectory />
<!--使用的报表插件和他们的配置。 -->
<plugins>
<!--plugin元素包含描述报表插件需要的信息 -->
<plugin>
<!--报表插件在仓库里的group ID -->
<groupId />
<!--报表插件在仓库里的artifact ID -->
<artifactId />
<!--被使用的报表插件的版本(或版本范围) -->
<version />
<!--任何配置是否被传播到子项目 -->
<inherited />
<!--报表插件的配置 -->
<configuration />
<!--一组报表的多重规范,每个规范可能有不同的配置。一个规范(报表集)对应一个执行目标 。例如,有1,2,3,4,5,6,7,8,9个报表。1,2,5构成A报表集,对应一个执行目标。2,5,8构成B报表集,对应另一个执行目标 -->
<reportSets>
<!--表示报表的一个集合,以及产生该集合的配置 -->
<reportSet>
<!--报表集合的唯一标识符,POM继承时用到 -->
<id />
<!--产生报表集合时,被使用的报表的配置 -->
<configuration />
<!--配置是否被继承到子POMs -->
<inherited />
<!--这个集合里使用到哪些报表 -->
<reports />
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
<!-- 继承自该项目的所有子项目的默认依赖信息。这部分的依赖信息不会被立即解析,而是当子项目声明一个依赖(必须描述group ID和 artifact
ID信息),如果group ID和artifact ID以外的一些信息没有描述,则通过group ID和artifact ID 匹配到这里的依赖,并使用这里的依赖信息。 -->
<dependencyManagement>
<dependencies>
<!--参见dependencies/dependency元素 -->
<dependency>
......
</dependency>
</dependencies>
</dependencyManagement>
<!--项目分发信息,在执行mvn deploy后表示要发布的位置。有了这些信息就可以把网站部署到远程服务器或者把构件部署到远程仓库。 -->
<distributionManagement>
<!--部署项目产生的构件到远程仓库需要的信息 -->
<repository>
<!--是分配给快照一个唯一的版本号(由时间戳和构建流水号)?还是每次都使用相同的版本号?参见repositories/repository元素 -->
<uniqueVersion />
<id>banseon-maven2</id>
<name>banseon maven2</name>
<url>file://${basedir}/target/deploy</url>
<layout />
</repository>
<!--构件的快照部署到哪里?如果没有配置该元素,默认部署到repository元素配置的仓库,参见distributionManagement/repository元素 -->
<snapshotRepository>
<uniqueVersion />
<id>banseon-maven2</id>
<name>Banseon-maven2 Snapshot Repository</name>
<url>scp://svn.baidu.com/banseon:/usr/local/maven-snapshot</url>
<layout />
</snapshotRepository>
<!--部署项目的网站需要的信息 -->
<site>
<!--部署位置的唯一标识符,用来匹配站点和settings.xml文件里的配置 -->
<id>banseon-site</id>
<!--部署位置的名称 -->
<name>business api website</name>
<!--部署位置的URL,按protocol://hostname/path形式 -->
<url>
scp://svn.baidu.com/banseon:/var/www/localhost/banseon-web
</url>
</site>
<!--项目下载页面的URL。如果没有该元素,用户应该参考主页。使用该元素的原因是:帮助定位那些不在仓库里的构件(由于license限制)。 -->
<downloadUrl />
<!--如果构件有了新的group ID和artifact ID(构件移到了新的位置),这里列出构件的重定位信息。 -->
<relocation>
<!--构件新的group ID -->
<groupId />
<!--构件新的artifact ID -->
<artifactId />
<!--构件新的版本号 -->
<version />
<!--显示给用户的,关于移动的额外信息,例如原因。 -->
<message />
</relocation>
<!-- 给出该构件在远程仓库的状态。不得在本地项目中设置该元素,因为这是工具自动更新的。有效的值有:none(默认),converted(仓库管理员从
Maven 1 POM转换过来),partner(直接从伙伴Maven 2仓库同步过来),deployed(从Maven 2实例部 署),verified(被核实时正确的和最终的)。 -->
<status />
</distributionManagement>
<!--以值替代名称,Properties可以在整个POM中使用,也可以作为触发条件(见settings.xml配置文件里activation元素的说明)。格式是<name>value</name>。 -->
<properties />
</project>

文章字数:14675,阅读全文大约需要58分钟
0000 操作已成功完成。
0001 错误的函数。
0002 系统找不到指定的文件。
0003 系统找不到指定的路径。
0004 系统无法打开文件。
0005 拒绝访问。
0006 句柄无效。
0007 存储区控制块已损坏。
0008 可用的存储区不足,无法执行该命令。
0009 存储区控制块地址无效。
0010 环境错误。

0011 试图使用不正确的格式加载程序。
0012 访问代码无效。
0013 数据无效。
0014 可用的存储区不足,无法完成该操作。
0015 系统找不到指定的驱动器。
0016 无法删除该目录。
0017 系统无法将文件移到其他磁盘驱动器上。
0018 没有其他文件。
0019 媒体写保护。
0020 系统找不到指定的设备。

0021 设备尚未准备好。
0022 设备无法识别该命令。
0023 数据错误(循环冗余检查)。
0024 程序发出命令,但是该命令的长度错误。
0025 驱动器在磁盘上无法定位指定的区域或磁道。
0026 无法访问指定的磁盘或软盘。
0027 驱动器找不到所请求的扇区。
0028 打印机缺纸。
0029 系统无法写入指定的设备。
0030 系统无法读取指定的设备。

0031 与系统连接的设备不能正常运转。
0032 其他进程正使用该文件,因此现在无法访问。
0033 另一进程已锁定该文件的某一部分,因此现在无法访问。
0034 驱动器中的软盘不正确。请将 %2 (卷标序列号: %3)插入驱动器 %1。
0036 打开共享的文件太多。
0038 已到达文件结尾。
0039 磁盘已满。
0050 不支持此网络请求。

0051 远程计算机无法使用。
0052 网络中存在重名。
0053 找不到网络路径。
0054 网络正忙。
0055 指定的网络资源或设备已不可用。
0056 已经达到网络命令的极限。
0057 网络适配器出现错误。
0058 指定的服务器无法执行所请求的操作。
0059 网络出现意外错误。
0060 远程适配器不兼容。

0061 打印机队列已满。
0062 服务器上没有存储等待打印的文件的空间。
0063 已经删除等候打印的文件。
0064 指定的网络名无法使用。
0065 拒绝访问网络。
0066 网络资源类型错误。
0067 找不到网络名。
0068 已超过本地计算机网络适配器卡的名称极限。
0069 已超过网络 BIOS 会话的极限。
0070 远程服务器已经暂停或者正在启动过程中。

0071 由于该计算机的连接数目已达到上限,此时无法再连接到该远程计算机。
0072 指定的打印机或磁盘设备已经暂停。
0080 该文件存在。
0082 无法创建该目录或文件。
0083 INT 24 失败。
0084 处理该请求的存储区不可用。
0085 正在使用该本地设备名。
0086 指定的网络密码不正确。
0087 参数错误。
0088 网络出现写入错误。
0089 此时系统无法启动其他进程。
0100 无法创建其他系统标志。

0101 属于其他进程的专用标志。
0102 标志已经设置,无法关闭。
0103 无法再次设置该标志。
0104 中断时无法请求专用标志。
0105 此标志先前的所有权已终止。
0106 请将软盘插入驱动器 %1。
0107 后续软盘尚未插入,程序停止。
0108 磁盘正在使用或已由其他进程锁定。
0109 管道已经结束。
0110 系统无法打开指定的设备或文件。

0111 文件名太长。
0112 磁盘空间不足。
0113 没有其他可用的内部文件标识符。
0114 目标内部文件标识符不正确。
0117 该应用程序所运行的 IOCTL 调用不正确。
0118 校验写入的开关参数值不正确。
0119 系统不支持所请求的命令。
0120 该系统上不支持此功能。

0121 标记已超时。
0123 文件名、目录名或卷标语法错误。
0124 系统调用层不正确。
0125 磁盘没有卷标。
0126 找不到指定的模块。
0127 找不到指定的过程。
0128 没有要等候的子进程。
0129 模式下运行。
0130 试图使用操作(而非原始磁盘I/O)的已打开磁盘分区的文件句柄。

0131 试图将文件指针移至文件开头之前。
0132 无法在指定的设备或文件中设置文件指针。
0133 对于包含已连接驱动器的驱动器,不能使用 JOIN 或 SUBST 命令。
0134 试图在已经连接的驱动器上使用 JOIN 或 SUBST 命令。
0135 试图在已经替换的驱动器上使用 JOIN 或 SUBST 命令。
0136 系统试图删除尚未连接的驱动器的 JOIN。
0137 系统试图删除尚未替换的驱动器的替换项。
0138 系统试图将驱动器连接到已连接的驱动器下的目录。
0139 系统试图将驱动器替换成已替换的驱动器下的目录。
0140 系统试图将驱动器连接到已替换的驱动器的一个目录中。

0141 系统试图将驱动器替换成到已连接的驱动器下的目录。
0142 此时系统无法运行 JOIN 或 SUBST。
0143 系统无法将驱动器连接到或替换成同一驱动器下的目录。
0144 此目录不是该根目录的子目录。
0145 该目录未清空。
0146 指定的路径已经在替换中使用。
0147 资源不足,无法执行该命令。
0148 此时无法使用指定的路径。
0149 试图连接或替换某个驱动器目录,该驱动器上的某个目录是上一次替换的目标目录。
0150 CONFIG.SYS 文件未指定系统跟踪信息,或禁止跟踪。

0151 DosMuxSemWait 的指定信号事件的数目不正确。
0152 DosMuxSemWait 没有运行;已经设置太多的标志。
0153 DosMuxSemWait 列表不正确。
0154 输入的卷标超过目标文件系统的标号字符长度极限。
0155 无法创建其他线程。
0156 接收进程拒绝该信号。
0157 已经放弃该区域,因此无法锁定。
0158 该区域已经解除锁定。
0159 线程标识符的地址错误。
0160 传到 DosExecPgm 的参数字符串错误。

0161 指定的路径无效。
0162 信号已挂起。
0164 系统无法创建其他线程。
0167 无法锁定文件的范围。
0170 所要求的资源正在使用中。
0173 锁定请求对于提供的取消区域不重要。
0174 文件系统不支持到锁定类型的自动更改。
0180 系统检测到错误的区域号码。

0182 操作系统无法运行 %1。
0183 不能创建已经存在的文件。
0186 传送的标志不正确。
0187 找不到指定的系统信号名称。
0188 操作系统无法运行 %1。
0189 操作系统无法运行 %1。
0190 操作系统无法运行 %1。

0191 无法在 Win32 模式下运行 %1。
0192 操作系统无法运行 %1。
0193 %1 不是有效的 Win32 应用程序。
0194 操作系统无法运行 %1。
0195 操作系统无法运行 %1。
0196 操作系统无法运行此应用程序。
0197 当前无法配置操作系统运行此应用程序。
0198 操作系统无法运行 %1。
0199 操作系统无法运行此应用程序。
0200 代码段应小于 64K。

0201 操作系统无法运行 %1。
0202 操作系统无法运行 %1。
0203 系统找不到输入的环境选项。
0205 在命令子树中的进程没有信号句柄。
0206 文件名或扩展名太长。
0207 环 2 堆栈正在使用中。
0208 输入的全局文件名字符 * 或 ? 不正确,或指定的全局文件名字符太多。
0209 所发送的信号不正确。
0210 无法设置信号处理程序。

0212 区域已锁定,无法重新分配。
0214 附加到此程序或动态链接模块的动态链接模块太多。
0215 无法嵌套调用 LoadModule。
0216 图像文件 %1 有效,但不适用于本机类型。
0230 管道状态无效。
0231 所有的管道实例都处于忙状态。
0232 管道正在关闭。
0233 在管道的另一端没有进程。
0234 有更多可用的数据。
0240 已取消会话。

0254 指定的扩展属性名无效。
0255 扩展属性不一致。
0258 等待操作过时。
0259 没有其他可用数据。
0266 无法使用复制功能。
0267 目录名无效。
0275 扩展属性不匹配缓冲区。
0276 所装载的文件系统上的扩展属性文件已被损坏。
0277 扩展属性表格文件已满。
0278 指定的扩展属性句柄无效。

0282 安装的文件系统不支持扩展属性。
0288 试图释放不属于调用者的多路同步信号。
0298 信号投递的次数太多。
0299 仅完成部分 ReadProcessMemory 或 WriteProcessMemory 请求。
0300 操作锁定请求被拒绝。
0301 系统接收了一个无效的操作锁定确认。
0317 在 %2 的消息文件中,系统无法找到消息号为 0x%1 的消息文本。
0487 试图访问无效地址。
0534 运算结果超过 32 位。
0535 该管道的另一方有一进程。
0536 等候进程打开管道的另一端。

0994 拒绝对扩展属性的访问。
0995 由于线程退出或应用程序的要求,I/O 操作异常终止。
0996 重叠的 I/O 事件不处于已标记状态。
0997 正在处理重叠的 I/O 操作。
0998 对内存位置的无效访问。
0999 执行页内操作出错。

1001 递归太深;堆栈溢出。
1002 窗口无法用来发送消息。
1003 无法完成此项功能。
1004 标志无效。
1005 卷不包含已识别的文件系统。请确认所有需要的文件系统驱动程序都已经加载,而且卷没有任何损坏。
1006 某文件的卷已在外部改变,因而打开的文件不再有效。
1007 要求的操作无法以全屏幕模式执行。
1008 试图引用并不存在的符号。
1009 配置注册表数据库已损坏。
1010 配置注册表主键无效。

1011 无法打开配置注册表主键。
1012 无法读取配置注册表主键。
1013 无法写入配置注册表主键。
1014 必须使用日志文件或其他副本来恢复注册表数据库中的某个文件。恢复成功。
1015 注册表已损坏。可能是一个包含注册表数据文件的结构已损坏,也可能内存中该文件的系统映像已损坏,或者因为备份副本(或日志)不存在(或损坏)导致无法恢复该文件。
1016 由注册表引起的 I/O 操作发生了不可恢复的错误。注册表将不能读取、写出或刷新包含注册表系统映像的其中一个文件。
1017 系统试图将文件加载或还原到注册表中,但是,指定的文件不是注册表文件格式。
1018 试图在注册表键(已经标记为删除)中完成的操作非法。
1019 系统无法在注册表日志文件中分配所需的空间。
1020 无法在已经有子键或键值的注册表项中创建符号链接。
1021 在易失的父键下不能创建固定的子键。
1022 通知的更改请求已经完成,并且返回信息还没有被送到调用者的缓冲区中。调用者需要列举所有文件以找到改动的内容。

1051 已将停止控制发送给与其他运行服务相关的服务。
1052 所要求的控制对此服务无效。
1053 服务没有及时地响应启动或控制请求。
1054 无法为该服务创建线程。
1055 服务数据库已锁定。
1056 该服务的实例已在运行。
1057 帐户名无效或者不存在,或者指定帐户名的密码无效。
1058 服务无法启动,可能因为被禁用,也可能因为没有关联的可用设备。
1059 已经指定了循环服务的从属关系。
1060 指定的服务不是所安装的服务。

1061 该服务此时无法接收控制消息。
1062 服务尚未启动。
1063 服务进程无法连接到服务控制程序。
1064 处理控制请求时,服务出现意外情况。
1065 指定的数据库不存在。
1066 服务返回服务特定的错误码。
1067 进程意外地终止。
1068 无法启动从属服务或组。
1069 由于登录失败,没有启动服务。
1070 启动后,服务保持在启动挂起状态。

1071 指定的服务数据库锁定无效。
1072 指定的服务已经标记为删除。
1073 指定的服务已经存在。
1074 系统当前正以上一次运行成功的配置运行。
1075 从属服务不存在,或已经标记为删除。
1076 已接受使用当前引导作为最后的有效控制设置。
1077 自从上一次启动以后,没有再次启动过该服务。
1078 该名称已经用作服务名或服务显示名。
1079 此服务的帐户不同于运行于同一进程上的其它服务的帐户。
1080 只能为 Win32 服务设置失败操作,不能为驱动程序设置。
1081 这个服务所运行的进程和服务控制管理器相同。所以,如果服务进程意外中止的话,服务控制管理器无法进行任何操作。
1082 这个服务没有设置恢复程序。
1083 配置成在该可执行程序中运行的这个服务不能执行该服务。
1100 已经到达磁带的物理尽头。

1101 磁带访问到文件标记。
1102 到达磁带或分区首部。
1103 磁带访问到文件组的末尾。
1104 磁带上没有其他数据。
1105 磁带无法分区。
1106 访问多重卷分区的新磁带时,当前的区块大小不正确。
1107 加载磁带时,找不到磁带分区信息。
1108 无法锁定媒体退出功能。
1109 无法卸载媒体。
1110 驱动器中的媒体已经更改。

1111 已经复位 I/O 总线。
1112 驱动器中没有媒体。
1113 在目标多字节代码页中不存在对单码字符的映射。
1114 动态链接库 (DLL) 初始化例程失败。
1115 正在关闭系统。
1116 无法终止系统关机,因为没有进行中的关机操作。
1117 由于 I/O 设备出现错误,无法运行该请求。
1118 串行设备初始化失败。将卸载串行驱动程序。
1119 无法打开正与其他设备共享中断请求 (IRQ) 的设备。至少有一个使用该 IRQ 的设备已经打开。
1120 由于再次写入串行口,串行 I/O 操作已结束。(IOCTL_SERIAL_XOFF_COUNTER 为零。)

1121 由于超时,串行 I/O 操作已结束。 (IOCTL_SERIAL_XOFF_COUNTER 未达到零。)
1122 在软盘上找不到标识符地址标记。
1123 软盘扇区标识符字段与软盘控制器磁道地址不匹配。
1124 软盘控制器报告软盘驱动程序不能识别的错误。
1125 软盘控制器返回的结果和注册的不一致。
1126 访问硬盘时,再校准操作失败,再试一次后也无法操作。
1127 访问硬盘时,磁盘操作失败,再试一次后仍没有作用。
1128 访问硬盘时,需要重启动磁盘控制器,但仍未成功。
1129 磁带已卷到尽头。
1130 可用的服务器存储区不足,无法执行该命令。

1131 检测到潜在的死锁情况。
1132 指定的基址或文件偏移量没有正确对齐。
1140 试图更改系统电源状态的操作被另一应用程序或驱动程序禁止。
1141 系统 BIOS 无法更改系统电源状态。
1142 试图在一文件上创建超过系统允许数额的链接。
1150 指定的程序需要新的 Windows 版本。

1151 指定的程序不是 Windows 或 MS-DOS 程序。
1152 无法启动指定程序的多个实例。
1153 指定的程序是为 Windows 的早期版本编写的。
1154 运行此应用程序所需的某个库文件已损。
1155 没有应用程序与该操作中所指定的文件关联。
1156 将命令发送到应用程序时出现错误。
1157 找不到运行此应用程序所需的某个库文件。
1158 当前进程已使用了 Window 管理器对象的系统允许的所有句柄。
1159 消息只能与同步操作一起使用。
1160 指出的源元素没有媒体。

1161 指出的目标元素已包含媒体。
1162 指出的元素不存在。
1163 指出的元素是未显示的存储资源的一部分。
1164 指出的设备需要重新初始化,因为硬件有错误。
1165 设备显示在尝试进一步操作之前需要清除。
1166 设备显示它的门仍是打开状态。
1167 设备没有连接。
1168 找不到元素。
1169 索引中没有同指定项相匹配的项。
1170 在对象上不存在指定的属性集。

1171 传递到 GetMouseMovePoints 的点不在缓冲区中。
1172 跟踪(工作站)服务没运行。
1173 找不到卷 ID。
1175 无法删除要被替换的文件。
1176 无法将替换文件移到要被替换的文件。要被替换的文件保持原来的名称。
1177 无法将替换文件移到要被替换的文件。要被替换的文件已被重新命名为备份名称。
1178 卷更改记录被删除。
1179 卷更改记录服务不处于活动中。
1180 找到一份文件,但是可能不是正确的文件。
1181 日志项已从日志中删除。
1200 指定的设备名无效。

1201 设备当前虽然未连接,但它是记忆连接。
1202 试图记起已经记住的设备。
1203 网络供应商不接受给定的网络路径。
1204 指定的网络供应商名无效。
1205 无法打开网络连接配置文件。
1206 网络连接配置文件已损坏。
1207 无法列举非包容类。
1208 出现扩展错误。
1209 指定组名的格式无效。
1210 指定计算机名的格式无效。

1211 指定事件名的格式无效。
1212 指定域名的格式无效。
1213 指定服务名的格式无效。
1214 指定网络名的格式无效。
1215 指定共享名的格式无效。
1216 指定密码的格式无效。
1217 指定的邮件名无效。
1218 指定邮件目的地的格式无效。
1219 所提供的凭据与现有凭据设置冲突。
1220 试图与网络服务器建立会话,但目前与该服务器建立的会话太多。

1221 网络上的其他计算机已经使用该工作组或域名。
1222 网络不存在或者没有启动。
1223 用户已经取消该操作。
1224 所要求的操作无法在已经打开用户映射区域的文件中运行。
1225 远程系统拒绝网络连接。
1226 已经关闭网络连接。
1227 网络传输的终点已经有一个地址与其关联。
1228 网络终点尚未与地址关联。
1229 试图在不存在的网络连接中操作。
1230 试图在活动的网络连接上进行无效操作。

1231 不能访问网络位置。有关网络疑难解答的信息,请参阅 Windows 帮助。
1232 不能访问网络位置。有关网络疑难解答的信息,请参阅 Windows 帮助。
1233 不能访问网络位置。有关网络疑难解答的信息,请参阅 Windows 帮助。
1234 远程系统的目标网络端点没有运行任何服务。
1235 该请求已经终止。
1236 本地系统已经终止网络连接。
1237 无法完成操作。请再试一次。
1238 无法创建到该服务器的连接,因为已经到达了该帐户同时连接的最大数目。
1239 试图在该帐户未授权的时间内登录。
1240 尚未授权此帐户从该站登录网络。

1241 网络地址无法用于要求的操作。
1242 服务已经注册。
1243 指定的服务不存在。
1244 由于尚未验证用户身份,无法执行要求的操作。
1245 由于用户尚未登录网络,无法运行要求的操作。指定的服务不存在。
1246 继续工作。
1247 完成初始化操作后,试图再次运行初始化操作。
1248 没有其他本地设备。
1249 指定的站点不存在。
1250 具有指定名称的域控制器已经存在。

1251 只有连接到服务器上时,才支持该操作。
1252 即使没有改动,组策略框架也应该调用扩展。
1253 指定的用户没有一个有效的配置文件。
1254 Microsoft Small Business Server 不支持此操作。
1300 不是对所有的调用方分配引用特权。

1301 帐户名与安全标识符之间的映射未完成。
1302 没有为该帐户明确地设置系统配额限制。
1303 没有可用的密钥。返回已知的密钥。
1304 密码太复杂,无法转换成 LAN Manager 密码。返回的 LAN Manager 密码是空字符串。
1305 修订级别未知。
1306 表示两个修订级别不兼容。
1307 无法将此安全标识符指定为该对象的拥有者。
1308 无法将此安全标识符指定为主要的对象组。
1309 当前并未模拟客户的线程试图操作模拟令牌。
1310 不可以禁用该组。

1311 目前没有可用的登录服务器处理登录请求。
1312 指定的登录会话不存在。该会话可能已终止。
1313 指定的权限不存在。
1314 客户不保留请求的权限。
1315 提供的名称不是正确的帐户名称格式。
1316 指定的用户已经存在。
1317 指定的用户不存在。
1318 指定的组已经存在。
1319 指定的组不存在。
1320 或者指定的用户帐户已经是某个特定组的成员,或者也可能指定的组非空而不能被删除。

1321 指定的用户帐户不是所指定组帐户的成员。
1322 上次保留的管理帐户无法关闭或删除。
1323 无法更新密码。所输入的密码不正确。
1324 无法更新密码。所提供的新密码包含不可用于密码的值。
1325 无法更新密码。为新密码提供的值不符合字符域的长度、复杂性或历史要求。
1326 登录失败: 用户名未知或密码错误。
1327 登录失败: 用户帐户限制。
1328 登录失败: 违反帐户登录时间限制。
1329 登录失败: 禁止用户登录到该计算机上。
1330 登录失败: 指定的帐户密码已过期。

1331 登录失败: 当前禁用帐户。
1332 未完成帐户名与安全性标识符之间的映射。
1333 一次请求的本地用户标识符(LUID)太多。
1334 没有其他可用的本地用户标识符(LUID)。
1335 对这个特定使用来说,安全标识符的子部分是无效的。
1336 访问控制清单(ACL)结构无效。
1337 安全标识符结构无效。
1338 安全描述符结构无效。
1340 无法创建继承的访问控制列表(ACL)或访问控制项目(ACE)。

1341 当前已禁用服务器。
1342 当前已启用服务器。
1343 所提供的值是无效的标识符授权值。
1344 没有更多的内存用于更新安全信息。
1345 指定的属性无效,或指定的属性与整个组的属性不兼容。
1346 或者没有提供所申请的模仿级别,或者提供的模仿级别无效。
1347 无法打开匿名级安全性符号。
1348 所请求的验证信息类别无效。
1349 该类符号不能以所尝试的方式使用。
1350 无法在没有相关安全性的对象上运行安全操作。

1351 未能从域控制器读取配置信息,或者是因为机器不可使用,或者是访问被拒绝。
1352 安全帐户管理程序(SAM)或本地安全颁发机构(LSA)服务器状态不正确,所以无法运行安全操作。
1353 域处于执行安全操作的错误状态。
1354 该操作只能在域的主域控制器中执行。
1355 指定的域不存在或联系不上。
1356 指定的域已经存在。
1357 试图超过每个服务器域数目的极限。
1358 由于严重的媒体错误或磁盘的数据结构损坏,无法完成所请求的操作。
1359 发生内部错误。
1360 通用的访问类型包含在访问掩码中,该掩码已经映射为非通用类型。

1361 安全性描述符的格式错误(绝对或自相关)。
1362 请求的操作只准登录进程使用。该调用过程并未被记录为登录进程。
1363 无法用已经使用的标识符来启动新的登录会话。
1364 指定的确认数据包未知。
1365 登录会话的状态与请求的操作不一致。
1366 登录会话标识符正在使用中。
1367 登录请求包含无效的登录类型值。
1368 在使用命名管道读取数据之前,无法经由该管道模拟。
1369 注册表子树的事务状态与所请求的操作不兼容。
1370 突发的内部安全性数据库故障。

1371 无法在内部帐户下运行该操作。
1372 无法在该内部特定组中运行该操作。
1373 无法在该内部特定用户中运行该操作。
1374 因为该组当前是用户的主要组,所以不能从此组中删除用户。
1375 该符号已作为主要符号使用。
1376 指定的本地组不存在。
1377 指定的帐户名不是本地组的成员。
1378 指定的帐户名已经是本地组的成员。
1379 指定的本地组已经存在。
1380 登录失败: 用户在本计算机上没有被授与所需注册类型。

1381 超过了可以存储在单个系统中的最大机密限制。
1382 机密的长度超过了最大允许值。
1383 本地安全授权数据库包含内部不一致的错误。
1384 登录时,用户的安全性上下文累积太多的安全标识符。
1385 登录失败: 用户在本计算机上没有被授与所需注册类型。
1386 经交叉加密的密码必须更改用户密码。
1387 成员不存在,因此无法将其添加到本地组或从中删除。
1388 新成员的帐户类型有误,因此无法将其添加到本地组。
1389 指定的安全标识符太多。
1390 经交叉加密的密码必须更改该用户密码。

1391 表示 ACL 没有可继承的组件。
1392 文件或目录已损坏,无法读取数据。
1393 磁盘结构已损坏,无法读取数据。
1394 指定的登录会话没有用户会话密钥。
1395 正在访问的服务允许特定数目的连接。因为连接的数目已达到服务可接受的数目,所以此时无法创建新的服务连接。
1396 登录失败: 该目标帐户名称不正确。
1397 相互身份验证失败。该服务器在域控制器的密码过期。
1398 在客户机和服务器之间有一个时间差。
1400 窗口句柄无效。

1401 菜单句柄无效。
1402 光标句柄无效。
1403 加速键表的句柄无效。
1404 挂接句柄无效。
1405 多重窗口位置结构句柄无效。
1406 无法创建最上层的子窗口。
1407 找不到窗口类。
1408 窗口无效;属于其他线程。
1409 已经注册热键。
1410 类已经存在。

1411 类不存在。
1412 类窗口仍打开着。
1413 索引无效。
1414 图标句柄无效。
1415 使用私人对话框窗口字。
1416 找不到列表框标识符。
1417 找不到任何通配符。
1418 线程没有打开剪贴板。
1419 尚未注册热键。
1420 该窗口不是有效的对话框窗口。

1421 找不到控制标识符。
1422 由于没有编辑控制,因此该组合框的消息无效。
1423 窗口不是组合框。
1424 高度必须小于 256。
1425 设备上下文(DC)句柄无效。
1426 挂接过程类型无效。
1427 挂接过程无效。
1428 不能在无模块句柄的情况下设置非本地的挂接。
1429 只能全局设置该挂接过程。
1430 已安装日记挂接过程。

1431 未安装挂接过程。
1432 单选列表框的消息无效。
1433 LB_SETCOUNT 发送到活动的列表框。
1434 该列表框不支持制表符。
1435 无法破坏由其他线程所创建的对象。
1436 子窗口不能有菜单。
1437 窗口没有系统菜单。
1438 消息框样式无效。
1439 系统范围内的(SPI_*)的参数无效。
1440 屏幕已经锁定。

1441 多重窗口位置结构中所有窗口句柄必须具有相同的父窗口。
1442 窗口不是子窗口。
1443 GW_* 命令无效。
1444 线程标识符无效。
1445 无法处理非多文档接口(MDI)窗口的消息。
1446 弹出式菜单已激活。
1447 窗口没有滚动条。
1448 滚动条范围不能大于 MAXLONG。
1449 无法以指定的方式显示或关闭窗口。
1450 系统资源不足,无法完成所请求的服务。

1451 系统资源不足,无法完成所请求的服务。
1452 系统资源不足,无法完成所请求的服务。
1453 配额不足,无法完成请求的服务。
1454 配额不足,无法完成请求的服务。
1455 页面交换文件太小,无法完成此项操作。
1456 找不到菜单项。
1457 键盘布局句柄无效。
1458 不允许使用挂钩类型。
1459 该操作需要交互式窗口工作站。
1460 由于超时时间已过,该操作返回。
1461 无效监视器句柄。
1500 事件日志文件已损坏。
1501 无法打开事件日志文件,因此无法启动事件记录服务。
1502 事件日志文件已满。
1503 事件日志文件在两次读取操作间已发生变化。
1601 无法访问 Windows 安装服务。请与技术支持人员联系,确认 Windows 安装服务是否注册正确。
1602 用户取消了安装。
1603 安装时发生严重错误。
1604 安装已挂起,未完成。
1605 这个操作只对当前安装的产品有效。
1606 功能 ID 未注册。
1607 组件 ID 未注册。
1608 未知属性。
1609 句柄处于不正确的状态。
1610 这个产品的配置数据已损坏。请与技术支持人员联系。

1611 组件限制语不存在。
1612 这个产品的安装来源无法使用。请验证来源是否存在,是否可以访问。
1613 Windows 安装服务无法安装这个安装程序包。您必须安装含有 Windows 安装服务新版本的 Windows Service Park。
1614 产品已卸载。
1615 SQL 查询语法不正确或不被支持。
1616 记录字符域不存在。
1617 设备已被删除。
1618 正在进行另一个安装操作。请在继续这个安装操作之前完成那个操作。
1619 未能打开这个安装程序包。请验证程序包是否存在,是否可以访问;或者与应用程序供应商联系,验证这是否是有效的 Windows 安装程序包。
1620 未能打开这个安装程序包。请与应用程序供应商联系,验证这是否是有效的 Windows 安装程序包。

1621 启动 Windows 安装服务用户界面时有错误。请与技术支持人员联系。
1622 打开安装日志文件时出错。请验证指定的日志文件位置是否存在,是否可以写入。
1623 安装程序包的语言不受系统支持。
1624 应用变换时出错。请验证指定的变换路径是否有效。
1625 系统策略禁止这个安装。请与系统管理员联系。
1626 无法执行函数。
1627 执行期间,函数出了问题。
1628 指定了无效的或未知的表格。
1629 提供的数据类型不对。
1630 这个类型的数据不受支持。

1631 Windows 安装服务未能启动。请与技术支持人员联系。
1632 临时文件夹已满或无法使用。请验证临时文件夹是否存在,是否可以写入。
1633 这个处理器类型不支持该安装程序包。请与产品供应商联系。
1634 组件没有在这台计算机上使用。
1635 无法打开修补程序包。请验证修补程序包是否存在,是否可以访问;或者与应用程序供应商联系,验证这是否是有效的 Windows 安装修补程序包。
1636 无法打开修补程序包。请与应用程序供应商联系,验证这是否是有效的 Windows 安装修补程序包。
1637 Windows 安装服务无法处理这个修补程序包。您必须安装含有 Windows 安装服务新版本的 Windows Service Pack。
1638 已安装这个产品的另一个版本。这个版本的安装无法继续。要配置或删除这个产品的现有版本,请用“控制面板”上的“添加/删除程序”。
1639 无效的命令行参数。有关详细的命令行帮助,请查阅 Windows 安装服务的 SDK。
1640 在终端服务远程会话期间,只有管理员有添加、删除或配置服务器软件的权限。如果您要在服务器上安装或配置软件,请与网络管理员联系。
1641 要求的操作已成功结束。要使改动生效,必须重新启动系统。
1642 Windows 安装服务无法安装升级修补程序,因为被升级的程序丢失,或者升级修补程序将更新此程序的其他版本。请确认要被升级的程序在您的计算机上且您的升级修补程序是正确的。
1700 串绑定无效。

1701 绑定句柄的类型错误。
1702 绑定句柄无效。
1703 不支持 RPC 协议顺序。
1704 RPC 协议序列无效。
1705 字符串的全球唯一标识符(UUID)无效。
1706 终点的格式无效。
1707 网络地址无效。
1708 未找到终点。
1709 超时设置值无效。
1710 找不到该对象的全球唯一标识符(UUID)。

1711 该对象的全球唯一标识符(UUID)已经注册。
1712 这一类型的全球唯一标识符(UUID)已经注册。
1713 RPC 服务器正在监听。
1714 尚未注册协议顺序。
1715 RPC 服务器不处于监听状态。
1716 管理程序的类型未知。
1717 接口未知。
1718 没有绑定。
1719 没有协议序列。
1720 无法创建终点。

1721 资源不足,无法完成该操作。
1722 RPC 服务器无法使用。
1723 RPC 服务器太忙,无法完成此项操作。
1724 网络选项无效。
1725 该线程中不存在活动的远程过程调用。
1726 远程过程调用失败。
1727 远程过程调用失败并且无法执行。
1728 远程过程调用(RPC)协议出现错误。
1730 RPC 服务器不支持传输语法。

1732 不支持这种类型的全球唯一标识符。
1733 标识无效。
1734 数组边界无效。
1735 绑定类型中不包含项目名。
1736 名称语法无效。
1737 不支持这种命名语法。
1739 没有可用的网络地址,无法创建全球唯一标识符(UUID)。
1740 终结点重复。

1741 身份验证类型未知。
1742 调用次数的上限太小。
1743 字符串太长。
1744 找不到 RPC 协议序列。
1745 过程号超出范围。
1746 此次绑定不包含任何身份验证信息。
1747 身份验证服务未知。
1748 身份验证级别未知。
1749 安全描述符无效。
1750 身份验证服务未知。

1751 项目无效。
1752 服务器的终结点无法执行此项操作。
1753 终点的映射器没有更多的终点可用。
1754 没有导出任何接口。
1755 项目名不完整。
1756 版本选项无效。
1757 没有其他成员。
1758 可以导出全部内容。
1759 未找到接口。
1760 项目已经存在。

1761 项目找不到。
1762 名称服务不可用。
1763 网络地址集无效。
1764 不支持请求的操作。
1765 没有可供冒仿的安全性描述符。
1766 远程过程调用(RPC)出现内部错误。
1767 RPC 服务器企图进行整除零运算。
1768 RPC 服务器出现寻址错误。
1769 RPC 服务器中的浮点运算造成被零除。
1770 RPC 服务器产生了浮点下溢错误。

1771 RPC 服务器产生了浮点上溢错误。
1772 可用于自动句柄绑定的 RPC 服务器列表已经用完。
1773 无法打开字符转换表文件。
1774 包含字符转换表的文件小于 512 个字节。
1775 在远程过程调用中,客户机向主机传送了一个空的描述体句柄。
1777 远程过程调用中的描述体句柄发生变化。
1778 发送到远程过程调用的绑定句柄不匹配。
1779 占位程序无法获得远程过程调用的句柄。
1780 将空的参考指针发送给占位程序。

1781 列举值超出范围。
1782 字节数目太小。
1783 占位程序接收到错误数据。
1784 所提供的用户缓冲区对所申请的操作无效。
1785 无法识别磁盘媒体。它可能还未格式化。
1786 工作站没有信任密码。
1787 服务器上的安全数据库中没有该工作站信任关系的计算机帐户。
1788 建立主域和受托域间的信任关系失败。
1789 建立工作站和主域间的信任关系失败。
1790 网络登录失败。

1791 该线程执行过程中已经进行了远程过程调用。
1792 试图登录网络,但网络登录服务尚未启动。
1793 用户帐户已到期。
1794 重定向程序正在使用,无法卸载。
1795 已经安装所指定的打印机驱动程序。
1796 指定的端口未知。
1797 打印机驱动程序未知。
1798 打印处理程序未知。
1799 指定的分隔符文件无效。
1800 指定的优先级无效。

1801 打印机名无效。
1802 打印机已经存在。
1803 打印机命令无效。
1804 指定的数据类型无效。
1805 指定的环境无效。
1806 没有其他绑定。
1807 使用的帐户是跨网络的信任帐户。请使用全局用户帐户或本地用户帐户来访问此服务器。
1808 所使用的帐户是计算机帐户。请使用全局用户帐户或本地用户帐户来访问该服务器。
1809 使用的帐户是服务器信任帐户。请使用全局用户帐户或本地用户帐户来访问该服务器。
1810 指定的域名或安全标识符与域的信任信息不一致。

1811 服务器正在使用中,无法卸载。
1812 指定的映像文件不包含资源部分。
1813 在映像文件中找不到指定的资源类型。
1814 在映像文件中找不到指定的资源名称。
1815 在映像文件中找不到指定的资源语言 ID 。
1816 可用的配额不足,无法执行该命令。
1817 没有已注册的接口。
1818 远程过程调用被取消。
1819 绑定句柄不包含所有需要的信息。
1820 远程调用过程中发生通讯失败。

1821 所需的身份验证级别不被支持。
1822 主要的名称没有注册。
1823 指定的错误不是有效的 Windows RPC 错误代码。
1824 已分配仅在本机上有效的 UUID。
1825 产生了特定的安全包错误。
1826 没有取消线程。
1827 在编码/解码处理时的操作无效。
1828 序列化软件包的版本不兼容。
1829 RPC 占位程序的版本不兼容。
1830 RPC 管道对象无效或已损坏。

1831 试图在 RPC 管道对象上进行无效操作。
1832 不被支持的 RPC 管道版本。
1898 找不到组成员。
1899 无法创建终结点映射数据库条目。
1900 对象的全球标识符(UUID)为空。

1901 指定的时间无效。
1902 指定的表单名无效。
1903 指定的表单大小无效。
1904 指定的打印机句柄正在等候处理
1905 指定的打印机已经删除。
1906 打印机的状态无效。
1907 用户首次登录前,必须先更改其密码。
1908 找不到该域的域控制器。
1909 引用的帐户目前被锁定,可能无法登录。
1910 没有发现指定的此对象导出者。

1911 没有发现指定的对象。
1912 没有发现指定的对象解析器。
1913 一些待发数据仍停留在请求缓冲区内。
1914 无效的异步远程过程调用句柄。
1915 这个操作的异步 RPC 调用句柄不正确。
1916 RPC 管道对象已经关闭。
1917 RPC 调用在全部的管道都被处理之前完成。
1918 没有其他可用的数据来自 RPC 管道。
1919 这个机器没有可用的站点名。
1920 系统无法访问此文件。

1921 系统无法解析文件名。
1922 项目不是所要的类型。
1923 无法将所有对象的 UUID 导出到指定的项。
1924 无法将接口导出到指定的项。
1925 无法添加指定的配置文件项。
1926 无法添加指定的配置文件元素。
1927 无法删除指定的配置文件元素。
1928 无法添加组元素。
1929 无法删除组元素。
2000 像素格式无效。

2001 指定的驱动程序无效。
2002 该操作的窗口样式或类属性无效。
2003 不支持请求的图元文件操作。
2004 不支持肭蟮淖徊僮鳌?nbsp;
2005 不支持请求的剪辑操作。
2010 指定的颜色管理模块无效。

2011 指定的颜色文件配置无效。
2012 找不到指定的标识。
2013 所需的标识不存在。
2014 指定的标识已经存在。
2015 指定的颜色文件配置与任何设备都不相关。
2016 找不到该指定的颜色文件配置。
2017 指定的颜色空间无效。
2018 图像颜色管理没有启用。
2019 在删除该颜色转换时有一个错误。
2020 指定的颜色转换无效。

2021 指定的转换与位图的颜色空间不匹配。
2022 指定的命名颜色索引在配置文件中不存在。
2108 网络连接已成功,但需要提示用户输入一个不同于原始指定的密码。
2202 指定的用户名无效。
2250 网络连接不存在。

2401 在这个网络连接上已存在打开的文件或未处理的请求。
2402 活动的连接仍然存在。
2404 设备正由活动进程使用,无法断开连接。

3000 指定的打印监视程序未知。
3001 指定的打印机驱动程序正在使用中。
3002 找不到假脱机文件。
3003 没有发出 StartDocPrinter 调用。
3004 尚未发出 AddJob 调用。
3005 指定的打印处理程序已经安装。
3006 指定的打印监视程序已经安装。
3007 该指定的打印监视器不具备所要求的功能。
3008 指定的打印机监视器正在使用中。
3009 当打印机有作业排成队列时此操作请求是不允许的。
3010 请求的操作成功。只有重新启动系统,更改才会生效。

3011 请求的操作成功。只有重新启动服务,更改才会生效。
3012 找不到打印机。
4000 WINS 在处理命令时遇到执行错误。
4001 无法删除本地的 WINS。
4002 从文件引入失败。
4003 备份失败。以前执行过完整的备份吗?
4004 备份失败。请检查备份数据库的目标目录。
4005 名称在 WINS 数据库中不存在。
4006 不允许进行未配置部分的复制。
4100 DHCP 客户获得一个在网上已被使用的 IP 地址。直到 DHCP 客户可以获得新的地址前,本地接口将被禁用。
4200 WMI 数据提供程序不能识别传来的 GUID 是否有效。

4201 WMI 数据提供程序无法识别传来的实例名是否有效。
4202 WMI 数据提供程序无法识别传来的数据项目标识符是否有效。
4203 无法完成 WMI 请求,请重试一次。
4204 找不到 WMI 数据提供程序。
4205 WMI 数据提供程序引用到一个未注册的实例组。
4206 WMI 数据块或事件通知已启用。
4207 WMI 数据块不再可用。
4208 WMI 数据服务无法使用。
4209 WMI 数据提供程序无法完成请求。
4210 WMI MOF 信息无效。

4211 WMI 注册信息无效。
4212 WMI 数据块或事件通知已禁用。
4213 WMI 数据项目或数据块为只读。
4214 WMI 数据项目或数据块不能更改。
6118 该工作组的服务器列表当前不可用。
6200 要正常运行,任务计划程序服务的配置必须在系统帐户中运行。单独的任务可以被配置成在其他帐户中运行。

7001 指定的会话名无效。
7002 指定的协议驱动程序无效。
7003 在系统路径上找不到指定的协议驱动程序。
7004 在系统路径上找不到指定的终端连接驱动程序。
7005 不能为这个会话创建一个事件日志的注册键。
7006 同名的一个服务已经在系统中存在。
7007 在会话上一个关闭操作挂起。
7008 没有可用的输出缓冲器。
7009 找不到 MODEM.INF 文件。
7010 在 MODEM.INF 中没有找到调制解调器名称。

7011 调制解调器没有接受发送给它的指令。验证配置的调制解调器与连接的调制解调器是否匹配。
7012 调制解调器没有响应发送给它的指令。验证该调制解调器是否接线正确并且打开了电源开关。
7013 由于断开连接,载波检测失败或载波停止。
7014 在要求的时间内没有发现拨号音。确定电话线连接正确并可使用。
7015 在远程站点回叫时检测到了占线信号。
7016 在回叫时远程站点上检测到了声音。
7017 传输驱动程序错误

7022 找不到指定的会话。
7023 指定的会话名称已处于使用中。
7024 由于终端连接目前正在忙于处理一个连接、断开连接、复位或删除操作,无法完成该请求的操作。
7025 试图连接到其视频模式不受当前客户支持的会话。
7035 应用程序尝试启动 DOS 图形模式。不支持 DOS 图形模式。
7037 您的交互式登录权限已被禁用。请与您的管理员联系。
7038 该请求的操作只能在系统控制台上执行。这通常是一个驱动程序或系统 DLL 要求直接控制台访问的结果。
7040 客户未能对服务器连接消息作出响应。

7041 不支持断开控制台会话。
7042 不支持重新将一个断开的会话连接到控制台。
7044 远程控制另一个会话的请求被拒绝。
7045 拒绝请求的会话访问。
7049 指定的终端连接驱动程序无效。
7050 不能远程控制请求的会话。这也许是由于该会话被中断或目前没有一个用户登录。另外,您不能从该系统控制台远程控制一个会话或远程控制系统控制台。并且,您不能远程控制您自己的当前会话。

7051 该请求的会话没有配置成允许远程控制。
7052 连接到这个终端服务器的申请被拒绝。终端服务器客户许可证目前正在被另一个用户使用。请与系统管理员联系,获取一份新的终端服务器客户,其许可证号码必须是有效的、唯一的。
7053 连接到这个终端服务器的申请被拒绝。还没有为这份终端服务器客户输入您的终端服务器客户许可证号码。请与系统管理员联系,为该终端服务器客户输入一个有效的、唯一的许可证号码。
7054 系统已达到其授权的登录限制。请以后再试一次。
7055 您正在使用的客户没有使用该系统的授权。您的登录请求被拒绝。
7056 系统许可证已过期。您的登录请求被拒绝。