精华内容
下载资源
问答
  • ASP.NET MVC中有四种过滤器类型

    千次阅读 2019-03-07 13:58:50
    首先大家得了解下MVC中的Filter效果:Filter是指的是MVC支持的一系列过滤器,包含权限验证、异常处理和Action/Result的方法过滤器,能够在不修改Action方法的基础上,为Action提供权限验证、异常处理、Action执行...

    【MVCFilter介绍】

    首先大家得了解下MVC中的Filter效果:Filter是指的是MVC支持的一系列过滤器,包含权限验证、异常处理和Action/Result的方法过滤器,能够在不修改Action方法的基础上,为Action提供权限验证、异常处理、Action执行前后和Result执行前后,加入各种不同的功能,是MVC开发必备,同时也是相对于Webform最大的变革之一。

    MVC框架支持的Filter时序图,支持在这些环节做各种功能扩展,后续会有MVC的Filter专题文章,去完成花式的扩展,敬请关注!

    Filter是AOP思想实践,能完成系统的优雅扩展,然而这个又是怎么实现的呢?跟之前几篇文章中的AOP实现有什么差别呢?Let’s go!

     

    【Filter原理】

    介于篇幅限制,下文直接看重点。Asp.Net的请求最终都是由HttpHandler处理的,而MVC中默认的是MVCHandler的ProcessRequest来完成请求处理:

     

    在MVChandler中完成控制器的实例化,然后去Execute其Action(MVC的请求最终是Action响应的)。

     

    然后Controller里面是通过一个ActionInvoker来完成Action的调用。

     

     

    在ControllerActionInvoker里面,我们看到InvokeAction方法在完成简单参数校验后,先查找Action和Controller上面的Filter,然后就去调用权限认证的Filter(权限认证第一个完成),然后以Context的Result为标志决定是否继续流程,随后又进行了ActionFilter和ResultFilter的调用,而且这整个过程被包含在try-catch中,有异常的话就进入了异常处理的Filter。是的,一切如我们所想的一样,但是这源码的细节还是太复杂,没法一一展示,只能是明白了大体思路,下面Eleven老师将这个大体思路加以实践!

     

    【手写模拟Filter】

    首先我们需要定义一个Filter的父类,然后定义几个子类,并且标记到对应的方法:

     

    然后需要一个统一的入口来完成方法的调用,跟MVC的请求一样,需要类/方法/参数:

     

    这里还有个问题,类名称是怎么找到一个具体的类型的呢,还缺命名空间呀?这里按照MVC的模式模拟,直接反射遍历bin里面全部的dll,找出满足类型为BaseController的类,放入一个静态字典。

     

    然后我们就能做到,通过给方法添加特性标识,然后在方法执行时,自动的在方法前后增加对应的逻辑。Demo相对简陋,只是对MVC中Filter核心的一种模拟,核心思想为反射调用方法,支持特性检测,并增加对应的功能调用!

     

    【结语】

    本文揭示了MVC框架中,Filter的实现原理,以及通过手写一个简单的发射+特性+统一入口的形式完成AOP的效果,希望能丰富大家对AOP的认知,也让大家在使用Filter的时候能更清晰,能知道Filter的作业,也能知道Filter的局限,知其然还得知其所以然!欢迎关注公众号,欢迎讨论,欢迎转发,愿天下有需求的人都能看到!

    展开全文
  • tcpdump常用与高级过滤方法整理

    千次阅读 2019-05-06 11:27:46
    下面介绍两种过滤方法(第一方法比较操蛋,可忽略): a. 比较第一字节的值是否大于01000101 这可以判断IPv4带IP选项的数据和IPv6的数据。 01000101十进制等于69,计算方法如下(小提示:用计算器更方便) 0 ...

    1.命令格式

    tcpdump [ -adeflnNOpqStvx ] [ -c 数量 ] [ -F 文件名 ][ -i 网络接口 ] [ -r 文件名]
    [ -s snaplen ] [ -T 类型 ] [ -w 文件名 ] [表达式 ]

    2.选项介绍

    参数含义
    -a将网络地址和广播地址转变成名字
    -d将匹配信息包的代码以人们能够理解的汇编格式给出
    -dd将匹配信息包的代码以c语言程序段的格式给出
    -ddd将匹配信息包的代码以十进制的形式给出
    -e在输出行打印出数据链路层的头部信息,包括源mac和目的mac,以及网络层的协议
    -f将外部的Internet地址以数字的形式打印出来
    -l使标准输出变为缓冲行形式
    -n指定将每个监听到数据包中的域名转换成IP地址后显示,不把网络地址转换成名字
    -nn指定将每个监听到的数据包中的域名转换成IP、端口从应用名称转换成端口号后显示
    -t在输出的每一行不打印时间戳
    -v输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息
    -vv输出详细的报文信息
    -c在收到指定的包的数目后,tcpdump就会停止
    -F从指定的文件中读取表达式,忽略其它的表达式
    -i指定监听的网络接口,后面跟数组“any”表示针对所有接口
    -p将网卡设置为非混杂模式,不能与host或broadcast一起使用
    -r从指定的文件中读取包(这些包一般通过-w选项产生)
    -w直接将包写入文件中,并不分析和打印出来
    -s snaplen表示从一个包中截取的字节数。0表示包不截断,抓完整的数据包。默认的话 tcpdump 只显示68字节数据包
    -T将监听到的包直接解释为指定的类型的报文,常见的类型有rpc (远程过程调用)和snmp(简单网络管理协议
    -X告诉tcpdump命令,需要把协议头和包内容都原原本本的显示出来(tcpdump会以16进制和ASCII的形式显示),这在进行协议分析时是绝对的利器

    使用案例

    参数 -l

    -l选项的作用就是将tcpdump的输出变为“行缓冲”方式,这样可以确保tcpdump遇到的内容一旦是换行符即将缓冲的内容输出到标准输出,以便于利用管道或重定向方式来进行后续处理。

    Linux/UNIX的标准I/O提供了全缓冲、行缓冲和无缓冲三种缓冲方式。
    标准错误是不带缓冲的,终端设备常为行缓冲,而其他情况默认都是全缓冲的。
    例如我们只想提取包的每一行的第一个域(时间域),这种情况下我们就需要-l将默认的全缓冲变为行缓冲了。
    tcpdump -i eth0 port 1111 -l | awk ‘{print $1}’
    在这里插入图片描述
    参数–w -r

    -w 直接将包写入文件中(即原始包,如果使用 重定向 > 则只是保存显示的结果,而不是原始文件),即所谓的“流量保存”—就是把抓到的网络包能存储到磁盘上保存下来,为后续使用。参数-r 达到“流量回放”—就是把历史上的某一时间段的流量,重新模拟回放出来,用于流量分析。

    通过-w选项将流量都存储在cp.pcap(二进制格式)文件中了.可以通过 –r 读取raw packets文件 cp.pcap.
    如:sudo tcpdump i- eth0 ‘port 1111’ -c 3 -r cp.pcap 即可进行流量回放。

    3.常用过滤表达式

    tcpdump支持传入单个或多个过滤表达式,可以通过命令man pcap-filter 来参考过滤表达式的帮助文档
    过滤表达式大体可以分成三种过滤条件,“类型”“方向”“协议”逻辑运算其他关键字,这五种条件的搭配组合就构成了我们的过滤表达式

    3.1 “类型”关键字

    关于类型的关键字,主要包括hostnetport
    例如:
    host 210.45.114.211,指定主机 210.45.114.211
    net 210.11.0.0 指明210.11.0.0是一个网络地址
    port 21 指明端口号是21。如果没有指定类型,缺省的类型是host

    3.2 “方向”关键字

    关于传输方向的关键字,主要包括src,dst,dst or src,dst and src
    举例:
    src 210.45.114.211 ,指明ip包中源地址是210.45.114.211
    dst net 210.11.0.0 指明目的网络地址是210.11.0.0
    如果没有指明方向关键字,则缺省是src or dst关键字。

    3.3 “协议”关键字

    关于协议的关键字,主要包括 ether,ip,ip6,arp,rarp,tcp,udp等类型。
    如果没有指定任何协议,则tcpdump将会监听所有协议的信息包。

    3.4 逻辑运算

    tcpdump还支持三种逻辑运算:

    逻辑运算表示方法
    取与“and”或“&&”
    取或“or”或“ll“”
    取非“not”或“!”

    3.5 其他关键字

    tcpdump还在其他几种关键字:gateway、broadcast、less、greater

    3.6 使用案例

    可以利用这些关键字进行组合,从而组合为比较强大的过滤条件。下面举例说明

    (1)只想查目标机器端口是21或80的网络包,其他端口的我不关注:
    sudo tcpdump -i eth0 -c 10 ‘dst port 21 or dst port 80’

    (2) 想要截获主机172.16.0.11 和主机210.45.123.249或 210.45.123.248的通信,使用命令(注意括号的使用):
    sudo tcpdump -i eth0 -c 3 ‘host 172.16.0.11 and (210.45.123.249 or210.45.123.248)’

    (3)想获取使用ftp端口和ftp数据端口的网络包
    sudo tcpdump ‘port ftp or ftp-data’
    这里 ftp、ftp-data到底对应哪个端口? linux系统下 /etc/services这个文件里面,就存储着所有知名服务和传输层端口的对应关系。如果你直接把/etc/services里的ftp对应的端口值从21改为了3333,那么tcpdump就会去抓端口含有3333的网络包了。

    (4) 如果想要获取主机172.16.0.11除了和主机210.45.123.249之外所有主机通信的ip包,使用命令:
    sudo tcpdump ip ‘host 172.16.0.11 and ! 210.45.123.249’

    (5) 抓172.16.0.11的80端口和110和25以外的其他端口的包
    sudo tcpdump -i eth0 ‘host 172.16.0.11 and! port 80 and ! port 25 and ! port 110’

    4.高级包头过滤

    首先了解如何从包头过滤信息

    proto[x:y] : 过滤从x字节开始的y字节数。比如ip[2:2]过滤出3、4字节(第一字节从0开始排)
    proto[x:y] & z = 0 : proto[x:y]和z的与操作为0
    proto[x:y] & z !=0 : proto[x:y]和z的与操作不为0
    proto[x:y] & z = z : proto[x:y]和z的与操作为z
    proto[x:y] = z : proto[x:y]等于z

    操作符 : >, <, >=, <=, =, !=

    4.1、IP头

    在这里插入图片描述
    本文只针对IPv4。

    4.2、IP选项设置了吗?

    “一般”的IP头是20字节,但IP头有选项设置,不能直接从偏移21字节处读取数据。IP头有个长度字段可以知道头长度是否大于20字节。
    ±±±±±±±±+
    |Version| IHL |
    ±±±±±±±±+
    通常第一个字节的二进制值是:01000101,分成两个部分: 0100 = 4 表示IP版本 0101 = 5 表示IP头32 bit的块数,5 x 32 bits = 160 bits or 20 bytes
    如果第一字节第二部分的值大于5,那么表示头有IP选项。
    下面介绍两种过滤方法(第一种方法比较操蛋,可忽略):
    a. 比较第一字节的值是否大于01000101
    这可以判断IPv4带IP选项的数据和IPv6的数据。
    01000101十进制等于69,计算方法如下(小提示:用计算器更方便)
    0 : 0 \ 1 : 2^6 = 64 \ 第一部分 (IP版本)
    0 : 0 /
    0 : 0 /
    0 : 0
    1 : 2^2 = 4 \ 第二部分 (头长度)
    0 : 0 /
    1 : 2^0 = 1 /
    64 + 4 + 1 = 69

    如果设置了IP选项,那么第一自己是01000110(十进制70),过滤规则:
    tcpdump -i eth1 ‘ip[0] > 69’
    IPv6的数据也会匹配,看看第二种方法。
    b. 位操作

    0100 0101 : 第一字节的二进制
    0000 1111 : 与操作
    <=========
    0000 0101 : 结果
    正确的过滤方法
    tcpdump -i eth1 ‘ip[0] & 15 > 5’
    或者tcpdump -i eth1 ‘ip[0] & 0x0f > 5’

    4.3、分片标记

    当发送端的MTU大于到目的路径链路上的MTU时就会被分片,这段话有点拗口,权威的请参考《TCP/IP详解》。唉,32借我的书没还,只能凑合写,大家记得看书啊。

    分片信息在IP头的第七和第八字节:
    ±±±±±±±±±±±±±±±±+
    |Flags| Fragment Offset |
    ±±±±±±±±±±±±±±±±+
    Bit 0: 保留,必须是0
    Bit 1: (DF) 0 = 可能分片, 1 = 不分片
    Bit 2: (MF) 0 = 最后的分片, 1 = 还有分片
    Fragment Offset字段只有在分片的时候才使用。
    要抓带DF位标记的不分片的包,第七字节的值应该是:
    01000000 = 64
    tcpdump -i eth1 ‘ip[6] = 64’

    4.4、抓分片包

    匹配MF,分片包
    tcpdump -i eth1 ‘ip[6] = 32’
    最后分片包的开始3位是0,但是有Fragment Offset字段。
    匹配分片和最后分片
    tcpdump -i eth1 ‘((ip[6:2] > 0) and (not ip[6] = 64))’
    测试分片可以用下面的命令:
    ping -M want -s 3000 192.168.1.1

    4.5、匹配小TTL

    TTL字段在第九字节,并且正好是完整的一个字节,TTL最大值是255,二进制为11111111。
    可以用下面的命令验证一下:

    $ ping -M want -s 3000 -t 256 192.168.1.200
    ping: ttl 256 out of range
    ±±±±±±±±+
    | Time to Live |
    ±±±±±±±±+
    在网关可以用下面的命令看看网络中谁在使用traceroute
    tcpdump -i eth1 ‘ip[8] < 5’

    4.6、抓大于X字节的包

    大于600字节
    tcpdump -i eth1 ‘ip[2:2] > 600’

    4.7、更多的IP过滤

    首先还是需要知道TCP基本结构,再次推荐《TCP/IP详解》,卷一就够看的了,避免走火入魔。

    TCP头
    0 1 2 3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | Source Port | Destination Port |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | Sequence Number |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | Acknowledgment Number |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | Data | |C|E|U|A|P|R|S|F| |
    | Offset| Res. |W|C|R|C|S|S|Y|I| Window |
    | | |R|E|G|K|H|T|N|N| |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | Checksum | Urgent Pointer |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | Options | Padding |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    | data |
    ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
    抓取源端口大于1024的TCP数据包
    tcpdump -i eth1 ‘tcp[0:2] > 1024’
    匹配TCP数据包的特殊标记
    TCP标记定义在TCP头的第十四个字节

    ±±±±±±±±+
    |C|E|U|A|P|R|S|F|
    |W|C|R|C|S|S|Y|I|
    |R|E|G|K|H|T|N|N|
    ±±±±±±±±+
    重复一下TCP三次握手,两个主机是如何勾搭的:

    源发送SYN
    目标回答SYN, ACK
    源发送ACK
    没女朋友的童鞋要学习一下:

    1. MM,你的手有空吗?–
    2. 有空,你呢?~~
    3. 我也有空 _

    失败的loser是酱紫的:

    1. MM,这是你掉的板砖吗?(SYN)  ̄▽ ̄
    2. 不是,找拍啊?(RST-ACK) ˋ﹏ˊ

    只抓SYN包,第十四字节是二进制的00000010,也就是十进制的2
    tcpdump -i eth1 ‘tcp[13] = 2’
    抓SYN, ACK (00010010 or 18)
    tcpdump -i eth1 ‘tcp[13] = 18’
    抓SYN或者SYN-ACK
    tcpdump -i eth1 ‘tcp[13] & 2 = 2’
    用到了位操作,就是不管ACK位是啥。

    抓PSH-ACK
    tcpdump -i eth1 ‘tcp[13] = 24’
    抓所有包含FIN标记的包(FIN通常和ACK一起,表示幽会完了,回见)
    tcpdump -i eth1 ‘tcp[13] & 1 = 1’
    抓RST(勾搭没成功,伟大的greatwall对她认为有敏感信息的连接发RST包,典型的棒打鸳鸯)
    tcpdump -i eth1 ‘tcp[13] & 4 = 4’
    下图详细描述了TCP各种状态的标记,方便分析。

    tcp_state_machine.jpg

    4.8、大叔注

    tcpdump考虑了一些数字恐惧症者的需求,提供了部分常用的字段偏移名字:

    icmptype (ICMP类型字段)
    icmpcode (ICMP符号字段)
    tcpflags (TCP标记字段)

    ICMP类型值有:
    icmp-echoreply, icmp-unreach, icmp-sourcequench, icmp-redirect, icmp-echo, icmp-routeradvert, icmp-routersolicit, icmp-timxceed, icmp-paramprob, icmp-tstamp, icmp-tstampreply, icmp-ireq, icmp-ireqreply, icmp-maskreq, icmp-maskreply

    TCP标记值:
    tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-push, tcp-ack, tcp-urg
    这样上面按照TCP标记位抓包的就可以写直观的表达式了:

    只抓SYN包
    tcpdump -i eth1 ‘tcp[tcpflags] = tcp-syn’
    抓SYN, ACK
    tcpdump -i eth1 ‘tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack != 0’

    4.9、抓SMTP数据

    tcpdump -i eth1 ‘((port 25) and (tcp[(tcp[12]>>2):4] = 0x4d41494c))’
    抓取数据区开始为"MAIL"的包,"MAIL"的十六进制为0x4d41494c。

    4.10、抓HTTP GET数据

    tcpdump -i eth1 ‘tcp[(tcp[12]>>2):4] = 0x47455420’
    "GET "的十六进制是47455420

    4.11、抓SSH返回

    tcpdump -i eth1 ‘tcp[(tcp[12]>>2):4] = 0x5353482D’
    "SSH-"的十六进制是0x5353482D

    tcpdump -i eth1 ‘(tcp[(tcp[12]>>2):4] = 0x5353482D) and (tcp[((tcp[12]>>2)+4):2] = 0x312E)’
    抓老版本的SSH返回信息,如"SSH-1.99…"

    三、大叔注
    如果是为了查看数据内容,建议用tcpdump -s 0 -w filename把数据包都保存下来,然后用wireshark的Follow TCP Stream/Follow UDP Stream来查看整个会话的内容。

    -s 0是抓取完整数据包,否则默认只抓68字节。
    另外,用tcpflow也可以方便的获取TCP会话内容,支持tcpdump的各种表达式。

    3.1、UDP头
    0 7 8 15 16 23 24 31
    ±-------±-------±-------±-------+
    | Source | Destination |
    | Port | Port |
    ±-------±-------±-------±-------+
    | | |
    | Length | Checksum |
    ±-------±-------±-------±-------+
    | |
    | DATA … |
    ±----------------------------------+
    抓DNS请求数据
    tcpdump -i eth1 udp dst port 53
    3.2、其他
    -c参数对于运维人员来说也比较常用,因为流量比较大的服务器,靠人工CTRL+C还是抓的太多,甚至导致服务器宕机,于是可以用-c参数指定抓多少个包。

    time tcpdump -nn -i eth0 ‘tcp[tcpflags] = tcp-syn’ -c 10000 > /dev/null
    上面的命令计算抓10000个SYN包花费多少时间,可以判断访问量大概是多少。

    使用案例

    下面介绍一些tcpdump中过滤语句比较高级的用法
    想获取172.16.10.11和google.com之间建立TCP三次握手中带有SYN标记位的网络包.

    命令为:sudo tcpdump -i eth0 ‘host 172.16.0.11 andhost google.com and tcp[tcpflags]&tcp-syn!=0’ -c 3 -nn
    在这里插入图片描述
    上面的命令是不是看着有点晕的感觉。 是的。
    下面详细介相关知识。
    其实我们理解这种语法: proto [ expr : size] ,就不难理解上面的语句了。
    下面详细介绍proto [ expr : size]
    Proto即protocol的缩写,它表示这里要指定的是某种协议名称,如ip,tcp,udp等。总之可以指定的协议有十多种,如链路层协议 ether,fddi,tr,wlan,ppp,slip,link,
    网络层协议ip,ip6,arp,rarp,icmp传输层协议tcp,udp等。
    expr用来指定数据报字节单位的偏移量,该偏移量相对于指定的协议层,默认的起始位置是0;而size表示从偏移量的位置开始提取多少个字节,可以设置为1、2、4,默认为1字节。如果只设置了expr,而没有设置size,则默认提取1个字节。比如ip[2:2],就表示提取出第3、4个字节;而ip[0]则表示提取ip协议头的第一个字节。在我们提取了特定内容之后,我们就需要设置我们的过滤条件了,我们可用的“比较操作符”包括:>,<,>=,<=,=,!=,总共有6个。

    举例:想截取每个TCP会话的起始和结束报文(SYN 和 FIN 报文), 而且会话方中有一个远程主机.
    sudo tcpdump ‘tcp[13] & 3 != 0 and not(src and dst net 172.16.0.0)’ -nn
    如果熟悉tcp首部报文格式可以比较容易理解这句话,因为tcp便宜13字节的位置为2位保留位和6位标志位(URG,ACK,PSH,RST,SYN,FIN), 所以与3相与就可以得出SYN,FIN其中是否一个置位1.

    从上面可以看到在写过滤表达式时,需要我们对协议格式比较理解才能把表达式写对。这个比较有难度的…。为了让tcpdump工具更人性化一些,有一些常用的偏移量,可以通过一些名称来代替,比如icmptype表示ICMP协议的类型域、icmpcode表示ICMP的code域,tcpflags 则表示TCP协议的标志字段域。更进一步的,对于ICMP的类型域,可以用这些名称具体指代:icmp-echoreply, icmp-unreach, icmp-sourcequench, icmp-redirect,icmp-echo, icmp-routeradvert, icmp-routersolicit, icmp-timxceed, icmp-paramprob,icmp-tstamp, icmp-tstampreply, icmp-ireq, icmp-ireqreply, icmp-maskreq,icmp-maskreply。

    而对于TCP协议的标志字段域,则可以细分为tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-ack, tcp-urg。
    对于tcpdump 只能通过经常操作来熟练这些语句了。也可以把网络包用tcpdump截获保存到指定文件,然后用wireshark等可视化软件分析网络包。

    参考链接

    https://blog.csdn.net/hzhsan/article/details/43445787
    https://blog.csdn.net/wzx19840423/article/details/50836761

    展开全文
  • 创建JSONArray的常用四种方法

    万次阅读 2018-09-17 21:22:49
    创建JSONArray的常用四种方法  1.从头或者从零开始,创建一个JSONArray(Creating a JSONArray from scratch)  实例1:  Java代码  JSONArray jsonArray = new JSONArray().element("JSON").element(&...

    创建JSONArray的常用四种方法 

    1.从头或者从零开始,创建一个JSONArray(Creating a JSONArray from scratch) 
    实例1: 


    Java代码  
    JSONArray jsonArray = new JSONArray().element("JSON").element("1").element("2.0").element("true");  
    assertEquals("JSON", jsonArray.getString(0));   
    assertEquals(1, jsonArray.getInt(1));   
    assertEquals(2.0d, jsonArray.getDouble(2), 0d);   
    assertTrue(jsonArray.getBoolean(3));   


    3.使用一个Collection来创建一个JSONArray(Creating a JSONArray from a Collection) 
    实例1: 

    Java代码  
    List list = new ArrayList();  
    list.add( "JSON" );   
    list.add( "1" );   
    list.add( "2.0" );   
    list.add( "true" );   
    JSONArray jsonArray = (JSONArray) JSONSerializer.toJSON( list ); assertEquals( "JSON", jsonArray.getString(0) );  
    assertEquals( 1, jsonArray.getInt(1) );   
    assertEquals( 2.0d, jsonArray.getDouble(2), 0d );   
    assertTrue( jsonArray.getBoolean(3) );   


    4.使用一个Array来创建一个JSONArray(Creating a JSONArray from an array) 
    实例1: 

    Java代码  
    Object[] array = new Object[] { "JSON", 1, 2.0, true };   
    JSONArray jsonArray = (JSONArray) JSONSerializer.toJSON(array); assertEquals("JSON", jsonArray.getString(0)); 
    assertEquals(1, jsonArray.getInt(1));   
    assertEquals(2.0d, jsonArray.getDouble(2), 0d);   
    assertTrue(jsonArray.getBoolean(3));   
      
    //实例2:   
    Object[] array = new Object[] { "JSON", 1, 2.0, true };   
    JSONArray jsonArray = JSONArray.fromObject(array);   
    assertEquals("JSON", jsonArray.getString(0));   
    assertEquals(1, jsonArray.getInt(1));   
    assertEquals(2.0d, jsonArray.getDouble(2), 0d);   
    assertTrue(jsonArray.getBoolean(3));   


    由此可见,无论要转换的源是哪种类型,都可以使用(JSONArray) JSONSerializer.toJSON()或JSONArray.fromObject()来转换;

    常用的三种扩展功能 

    1.使用一个JSON格式化字符串来创建一个JSONFunction(JavaScript functions)  
    实例: 

    Java代码  
    String str = "{func: function( param ){ doSomethingWithParam(param); }}";   
    JSONObject jsonObject = (JSONObject) JSONSerializer.toJSON(str); JSONFunction func = (JSONFunction) jsonObject.get("func"); ArrayAssertions.assertEquals(new String[] { "param" }, func.getParams());  
    assertEquals("doSomethingWithParam(param);", func.getText());   

      
    注:函数的写法要注意function(){},参数param是可选的! 

    2.排除一个JSON格式化字符串的某些属性(Exclude properties) 
    实例: 

    Java代码  
    String str = "{'string':'JSON', 'integer': 1, 'double': 2.0, 'boolean': true}";  
    JsonConfig jsonConfig = new JsonConfig();   
    jsonConfig.setExcludes(new String[] { "double", "boolean" }); JSONObject jsonObject = (JSONObject) JSONSerializer.toJSON(str, jsonConfig);  
    assertEquals("JSON", jsonObject.getString("string"));   
    assertEquals(1, jsonObject.getInt("integer"));  
    assertFalse(jsonObject.has("double"));   
    assertFalse(jsonObject.has("boolean"));   


    3.排除一个JSON格式化字符串的某些属性,使用过滤器(Exclude properties (with filters) 
    实例: 
    Java代码  
    String str = "{'string':'JSON', 'integer': 1, 'double': 2.0, 'boolean': true}";  
    JsonConfig jsonConfig = new JsonConfig(); jsonConfig.setJsonPropertyFilter(new PropertyFilter() {  
       public boolean apply(Object source, String name, Object value) {  
             if ("double".equals(name) || "boolean".equals(name))   
              { return true; }  
                  return false; } });   
    JSONObject jsonObject = (JSONObject) JSONSerializer.toJSON(str, jsonConfig);   
    assertEquals("JSON", jsonObject.getString("string"));   
    assertEquals(1, jsonObject.getInt("integer"));   
    assertFalse(jsonObject.has("double"));   
    assertFalse(jsonObject.has("boolean"));   


    JSONObject-Java常用的四种用法 
    1.JSONObject to DynaBean 

    Java代码  
    String json = "{name=\"json\",bool:true,int:1,double:2.2}"; JSONObject jsonObject = JSONObject.fromObject(json); //抽象的写法:DynaBean bean = (DynaBean) JSONSerializer.toJava( jsonObject ); Object bean = JSONObject.toBean(jsonObject);  
    //Object bean1 = JSONSerializer.toJava(jsonObject);   
    assertEquals(jsonObject.get("name"), PropertyUtils.getProperty(bean, "name"));  
    assertEquals(jsonObject.get("bool"), PropertyUtils.getProperty(bean, "bool"));   
    assertEquals(jsonObject.get("int"), PropertyUtils.getProperty(bean, "int"));   
    assertEquals(jsonObject.get("double"), PropertyUtils.getProperty(bean, "double"));  


    2.JSONObject to JavaBean 

    Java代码  
    String json = "{name:\"zhangsan\",age:25,hight:1.72,sex:true}"; JSONObject jsonObject = JSONObject.fromObject(json);  
    UserBean bean = (UserBean) JSONObject.toBean(jsonObject, UserBean.class);   
    System.out.println(jsonObject);   


    3.JSONArray to List 

    Java代码  
    String json = "[\"first\",\"second\"]";   
    JSONArray jsonArray = (JSONArray) JSONSerializer.toJSON(json);  
    List output = (List) JSONSerializer.toJava(jsonArray);   


    4.JSONArray to array 

    Java代码  
    String json = "[\"first\",\"second\"]";  
    JSONArray jsonArray = (JSONArray) JSONSerializer.toJSON(json); JsonConfig jsonConfig = new JsonConfig();  
    jsonConfig.setArrayMode(JsonConfig.MODE_OBJECT_ARRAY);   
    Object[] output = (Object[]) JSONSerializer.toJava(jsonArray, jsonConfig);   
    Object[] expected = new Object[] { "first", "second" }; ArrayAssertions.assertEquals(expected, output);   


    理论上,这样就可以了,但时,有异常Caused by: java.lang.NoSuchMethodException: com.json.Json$UserBean.<init>()
       
    2.使用一个JSON格式化字符串来创建一个JSONArray(Creating a JSONArray from a JSON formatted string) 
    实例1: 

    Java代码  
    String str = "['JSON', 1, 2.0, true]"; //注意该字符串的格式"[ , ]" JSONArray jsonArray = (JSONArray) JSONSerializer.toJSON( str ); assertEquals( "JSON", jsonArray.getString(0) );  
    assertEquals( 1, jsonArray.getInt(1) );   
    assertEquals( 2.0d, jsonArray.getDouble(2), 0d );   
    assertTrue( jsonArray.getBoolean(3) );   


    Java代码  
    List<String> list = new ArryList<String>(); list.add("a"); list.add("b"); Map<String,List<String>> map = new HashMap<String,List<String>>(); map.put("list",list); MessageUtils.outputJSONResult(JSONObject.fromObject(map).toString(), response); public class MessageUtils { public static void outputJSONResult(String result, HttpServletResponse response) { try { response.setHeader("ContentType", "text/json"); response.setCharacterEncoding("utf-8"); PrintWriter pw = response.getWriter(); pw.write(result); pw.flush(); pw.close(); } catch (IOException e) { e.printStackTrace(); } }

    展开全文
  • 文章目录FilterMapMapPartitionsInner Join总结 在实际工作中,根据某个字段,对一个Spark数据集进行过滤,是一个很常见的场景,举个例子: 一个存储公司员工信息的数据...有四种方法可以实现,分别为: Filter Map Ma


    在实际工作中,根据某个字段,对一个Spark数据集进行过滤,是一个很常见的场景,举个例子:

    一个存储公司员工信息的数据集A,有以下三个字段:

    id: Integer
    name: String
    age: Integer
    

    现在要过滤出某些员工的id,这些id在B集合(B可能是哈希表,也可能是Spark数据集)中,过滤逻辑为:

    C = A.filter(A.id in B)
    

    有四种方法可以实现,分别为:

    • Filter
    • Map
    • MapPartition
    • Inner Join

    下面详细介绍。

    Filter

    Spark的Filter变换,可以根据条件表达式、返回布尔值的过滤函数、条件字符串,对数据集进行过滤,使用方法如下:

    // 1. 条件表达式
    A1 = A.filter(Column condition)
    // 2. 自定义过滤函数
    A1 = A.filter(FilterFunction<T> func)
    // 3. 条件字符串
    A1 = A.filter(String condition)
    

    Filter 变换比较简单,逐条处理记录不论数据集大小,效率都很高,但需要能够将用来过滤的数据集B广播到所有的executor上。

    Map

    Map变换,对数据集中每条记录调用一个函数,返回值可以是null,也可以是相同类型或不同类型的新记录,使用方法如下:

    // encoder参数用来指定输出类型
    A2 = A.map(MapFunction<T,U> func, Encoder<U> encoder)
    

    通过Map变换实现过滤的话,只需要在Map变换中,将符合条件的记录原样返回,不符合条件的记录返回null即可。

    可以看到,Map变换的语义和Filter变换的语义相似,都是逐条处理记录,但Map需要提供一个额外的Encoder,故没有Filter简单和优雅,且因为输出要过滤null值,所以效率不如Filter。

    MapPartitions

    MapPartitions变换,与Map变换类似,但映射函数不是在每条记录上调用,而是在分区级别调用,使用方法如下:

    // func的输入和输出都是Iterator类型
    A3 = A.map(MapPartitionsFunction<T,U> func, Encoder<U> encoder)
    

    MapPartitions在分区级别进行操作,而不是记录级别,因此比Filter和Map效率更高。缺点的话,首先和Map一样,需要提供一个额外的Encoder,此外,当分区过大,超过executor所能提供的内存时,任务会失败,因此可靠性不如Map和Filter。

    Inner Join

    以员工id相等为Inner Join的条件,然后只要A集合中的字段,同样可以实现过滤,使用方法:

    // join表达式可能为 A("id") === B("id")
    A4 = A.join(Dataset<?> B, Column joinExprs)
    

    Inner Join和Filter一样,效率和可靠性都有保证,且对B集合的类型和大小都没有偏好。

    总结

    在本文描述的过滤场景中,综合考虑效率和可靠性,如果用来过滤的集合比较小,可以广播到所有的executor中,那么选择Filter变换为佳,如果B集合很大,则Inner Join更合适。

    参考链接:

    1. https://towardsdatascience.com/four-ways-to-filter-a-spark-dataset-against-a-collection-of-data-values-7d52625bcf20
    2. https://spark.apache.org/docs/latest/api/java/index.html
    3. https://spark.apache.org/docs/latest/api/scala/org/apache/spark/sql/Dataset.html

    公众号:大数志
    传递最新、最有价值的大数据技术干货和资讯。

    展开全文
  • 简单介绍AngularJS过滤器filter用法,每个都将列出用法代码以便加深了解; 内置过滤器: currency(货币)、date(日期)、filter(子串匹配)、json(格式化json对象)、limitTo(限制个数)、lowercase(小写)、...
  • 常用四种大数据分析方法

    万次阅读 多人点赞 2017-09-19 09:32:13
    本文主要讲述数据挖掘分析领域中,最常用四种数据分析方法:描述型分析、诊断型分析、预测型分析和指令型分析。
  • 过滤器的四种拦截方式

    千次阅读 2019-12-10 19:57:52
    四种拦截方式 引言 我们先做一个小测试,新建一个b.jsp: <body> <h1>b.jsp</h1> </body> 再新建一个a.jsp,在里面转发到b.jsp: <body> <h1>a.jsp</h1> <% ...
  • 常用四种大数据分析方法

    千次阅读 2017-12-18 20:50:05
    本文主要讲述数据挖掘分析领域中,最常用四种数据分析方法:描述型分析、诊断型分析、预测型分析和指令型分析。 当刚涉足数据挖掘分析领域的分析师被问及,数据挖掘分析人员最重要的能力是什么时,他们给出了...
  • 在推荐系统中常用的技术可大致分为四类:基于内容的过滤、协同过滤、基于规则的方法和混合方法。 一、基于内容过滤  基于内容过滤推荐系统思路如下:  (1)通过在抓取每个商品的一系列特征来构建商品档案;  ...
  • //方法一 var newphone=phone.substr(0, 3) + '****' + phone.substr(phone.length - 4); //方法二 var newphone= phone.replace(phone.substr(3, 4),"****") //方法三 var newphone=pho...
  • 过滤 filter 定义 方法签名 方法解析 案例 参考代码 过滤 filter 过滤符合一定条件的元素 定义 方法签名 deffilter(p:(A)⇒ Boolean):TraversableOnce[A] 方法解析 filter方法 API ...
  • wireshark精确到字节的过滤方法

    千次阅读 2015-03-05 15:16:03
    wireshark精确到字节的过滤方法
  • web前端开发常见的安全问题就是会遭遇...这是最常见的一,主要入口为表单项(一般就是正则过滤不周全)、内联样式表(exploer) 正则过滤的解决办法,php一般会使用htmlspecialchars或者htmlentities函数进行
  • 26_ElasticSearch 四种常见的相关度分数优化方法更多干货分布式实战(干货)spring cloud 实战(干货)mybatis 实战(干货)spring boot 实战(干货)React 入门实战(干货)构建中小型互联网企业架构(干货)python...
  • 在开发中经常遇到要对表情字符处理,如果前端和后端都未做过滤就会...,分析了原因并研究了下对服务端做处理的几方式原因UTF-8编码有可能是两个、三个、个字节。Emoji表情是4个字节,而Mysql的utf8编码最多3个字节
  • 过滤是数据提取的一个很重要的功能,以下对一些常用过滤条件进行解释,并且这些过滤条件都是只能通过filter方法实现的。 equals not equals like in not in is null is not null and or # -*- encoding: utf-8 -*-...
  • springmvc配置过滤器的作用和方法

    千次阅读 2019-04-05 15:36:56
    http协议里常见的请求方式有四种:post delete put get 分别对应增删改查个操作 普通浏览器一般只支持get和post,其他两个方式是通过过滤器支持的。 过滤器支持要求: 1、方法有隐藏域且name是_method 如: <...
  • 常用Servlet过滤

    千次阅读 2017-03-12 11:04:05
    过滤器应用案例一:解决POST请求参数中文和输出中文的乱码过滤过滤器代码package com.study.java.filter;import java.io.IOException;import javax.servlet.Filter; import javax.servlet.FilterChain; import ...
  • Zuul过滤

    千次阅读 2018-07-27 16:20:49
    在zuul的世界里定义了四种标准过滤器类型,这四种过滤器分别对应着请求的生命周期: pre:此种过滤器在请求被路由之前执行,显然这种过滤器可以用来过滤请求(白黑名单)、安全验证等; routing:此种过滤器...
  • .Net 过滤

    千次阅读 2019-07-14 13:32:57
    .Net MVC 常用的4种过滤器:Action过滤器,Result过滤器, Exception过滤器,Authorization过滤器。本篇文章将详细介绍着四种过滤器,并用代码实现演示。
  • Pandas提供了多种API函数用于支持多种类型数据(如CSV、Excel、SQL等)的读写,其中常用的函数如下表所示。 文件类型 读取函数 写入函数 xls/xlsx read_excel to_excel CSV read_csv to_csv SQL read_...
  • 目录 目录 前文列表 Jinja 中常用过滤器 default float int lenght title round join tojson truncate escape safe 自定义过滤器 Flask 的特殊变量和方法 config 对象 request 对象 se...
  •  一种常用的攻击手段是“钓鱼”。钓鱼攻击者,通常会发送给受害者一个合法链接,当链接被点击时,用户被导向一个似是而非的非法网站,从而达到骗取用户信任、窃取用户资料的目的。为防止这种行为,我们必须对所有的...
  • 协同过滤是用来做推荐的算法 1. 基于用户的协同过滤(UserCF) 2. 基于物品的协同过滤(ItemCF) 3. 四种求相似度的方法 4.基于物品的协同过滤的计算步骤以及利用mahout调用协同过滤方法

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 178,456
精华内容 71,382
关键字:

常用的四种过滤方法