• 设计配置选项等级系统


    - 什么是“配置选项等级”呢?

    举个例子,PHP设置报错级别(来源PHP官网示例:https://www.php.net/manual/zh/function.error-reporting.php):

     1 <?php
     2 
     3 // 关闭所有PHP错误报告
     4 error_reporting(0);
     5 
     6 // Report simple running errors
     7 error_reporting(E_ERROR | E_WARNING | E_PARSE);
     8 
     9 // 报告 E_NOTICE也挺好 (报告未初始化的变量
    10 // 或者捕获变量名的错误拼写)
    11 error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
    12 
    13 // 除了 E_NOTICE,报告其他所有错误
    14 error_reporting(E_ALL ^ E_NOTICE);
    15 
    16 // 报告所有 PHP 错误 (参见 changelog)
    17 error_reporting(E_ALL);
    18 
    19 // 报告所有 PHP 错误
    20 error_reporting(-1);
    21 
    22 // 和 error_reporting(E_ALL); 一样
    23 ini_set('error_reporting', E_ALL);
    24 
    25 ?>

    可以看到我们设置错误级别非常方便,想要哪些错误级别直接用 “|” 链接即可;

    Java中网络编程,使用的 java.nio.channels.SelectionKey 中设置 Interest Option 也是类似操作:

    tmpKey.interestOps(tmpKey.interestOps() | SelectionKey.OP_READ);

    打开 java.nio.channels.SelectionKey 源码发现定义了 

      OP_READ = 1
      OP_WRITE = 4
      OP_CONNECT = 8

      ……

    等类常量;

    再向下翻,发现一段代码:

    public final boolean isReadable() {
            return (this.readyOps() & 1) != 0;
        }

    原来前面通过设置interestOps后,判断channel是否可读就是判断:(this.readyOps() & 1) != 0;

    原理也很简单,二进制操作 | 相当于加,即对应的二进制位变更为1,&操作即为 判断是否有相同位置均为1;

    例如:

    1 |  2 得 3,

    1二进制  0001

    2 二进制 0010

    或之后,只要对应位置任意一位为 1, 即将该位置变更为1;

    3 二进制 0011

    得到3后,判断用户是否设置了  常量值为1对应的选项,即为: 

    3 & 1 

    3 二进制 0011

    1 二进制 0001

    与之后,对应位置均为1得1否则得0:

    0001 十进制(1), 1!= 0 成立,返回true,说明用户设置了 常量值为1对应的选项!

    那么如何选择 选项常量值呢?可以看到Java SelectionKey 设置的是依次是 1、4、 8 ...

    实际上因为十进制数二进制或操作可以看做是 两个数之间 的加和!

    如 1 | 2 == 3, 2 | 4 == 6

    所以选取选项的值,原则遵循 下一个选项值比前面所有选项值加和大即可;

    例如可以这样设计:

    0 E_NONE
    
    1 E_NOTICE
    
    2 E_WARN
    
    4 E_ERROR
    
    8 E_ALL

    0 < 1

    0 + 1 <  2;

     0 + 1 + 2 = 3 < 4

     0 + 1 + 2 + 4 = 7 < 8

    以此类推

    设置选项时,比如想要E_ALL登记,却要排除E_NOTICE, 直接 E_ALL & ~E_NOTICE 即可! 

    用Java编写一个简单的错误信息上报功能组件:

     1 public class ReportLevel {
     2     public static final int E_NONE = 0;
     3     public static final int E_NOTICE = 1;
     4     public static final int E_WARNING = 2;
     5     public static final int E_ERROR = 4;
     6 
     7     // all notice/warning/error exception or error
     8     public static final int E_ALL = 7;
     9 
    10     public static int REPORT_LEVEL;
    11 
    12     public static void setReportLevel(int reportLevel) {
    13         REPORT_LEVEL = reportLevel;
    14     }
    15 
    16     public static boolean shouldReportNotice() {
    17         return (REPORT_LEVEL & E_NOTICE) != 0;
    18     }
    19 
    20     public static boolean shouldReportWarning() {
    21         return (REPORT_LEVEL & E_WARNING) != 0;
    22     }
    23 
    24     public static boolean shouldReportError() {
    25         return (REPORT_LEVEL & E_ERROR) != 0;
    26     }
    27 }

    测试使用:

     1 public class ReportLevelTest {
     2 
     3     @Test
     4     public void testAddLevel() {
     5         ReportLevel.setReportLevel(ReportLevel.E_WARNING | ReportLevel.E_ERROR);
     6 
     7         Assert.assertTrue(ReportLevel.shouldReportWarning());
     8         Assert.assertTrue(ReportLevel.shouldReportError());
     9 
    10         Assert.assertFalse(ReportLevel.shouldReportNotice());
    11     }
    12 
    13     @Test
    14     public void testExcludeLevel() {
    15 //        写为 ReportLevel.E_ALL ^ ReportLevel.E_NOTICE 也可以
    16 //        ReportLevel.setReportLevel(ReportLevel.E_ALL & ~ReportLevel.E_NOTICE);
    17         ReportLevel.setReportLevel(ReportLevel.E_ALL ^ ReportLevel.E_NOTICE);
    18 
    19         Assert.assertTrue(ReportLevel.shouldReportWarning());
    20         Assert.assertTrue(ReportLevel.shouldReportError());
    21 
    22         Assert.assertFalse(ReportLevel.shouldReportNotice());
    23     }
    24 
    25     @Test
    26     public void testNone() {
    27         ReportLevel.setReportLevel(ReportLevel.E_NONE);
    28 
    29         Assert.assertFalse(ReportLevel.shouldReportWarning());
    30         Assert.assertFalse(ReportLevel.shouldReportError());
    31         Assert.assertFalse(ReportLevel.shouldReportNotice());
    32     }
    33 }
    
    
    
  • 相关阅读:
    @configuration 和 @bean
    js中关键字 const , let , var 的用法区别
    springboot+vue项目demo地址
    快速开发框架下载地址(github)
    搭建vue项目并启动vue项目
    export default{} 和 new Vue()都是什么意思
    反向代理
    [转]python类方法
    linux中waitpid及wait的用法
    mount
  • 原文地址:https://www.cnblogs.com/Joynic/p/11679206.html
Copyright © 2020-2023  润新知