导航:首页 > 净水问答 > local过滤

local过滤

发布时间:2022-02-06 15:06:21

⑴ html5 localstorage 怎么取存储条数

1在HTML5本地存储出现以前,WEB数据存储的方法已经有很多,比如HTTP Cookie,IE userData,Flash Cookie,Google Gears。其实再说细点,浏览WEB的历史记录也算是本地存储的一种方式。到目前为止,HTML5本地存储方式已经获得了广泛的支持,其中支持的浏览器包括:IE 8+、FF 3.5+、Safari 4+、Chrome 4+、Opera 10.5+,手机平台包括iPhone 2+和Android 2+。最新的HTML5本地存储规范文档,可以在线查看
2http://dev.w3.org/html5/webstorage/
3 HTML5本地存储的前身就是Cookie,通过使用localStorage对象将WEB数据持久留存在本地。相比较而言,HTML5本地存储中每个域的存储大小默认是5M,比起Cookie的4K要大的多。而且存储和读取数据的代码极为简练:
那么现在我们是否可以简单的认为,HTML5存储已经可以代替Cookie存储了呢?还有这种新的存储方式在实际应用中带来了哪些新的安全风险呢?带着这些疑问我们来进行下面的讨论。
(1) 是否可以代替Cookie
浏览器使用Cookie进行身份验证已经好多年,既然现在localStorage存储空间那么大,是否可以把身份验证的数据直接移植过来呢?目前来看,把身份验证数据使用localStorage进行存储还不太成熟。我们知道,通常可以使用XSS漏洞来获取到Cookie,然后用这个Cookie进行身份验证登录。后来为了防止通过XSS获取Cookie数据,浏览器支持了使用HTTPONLY来保护Cookie不被XSS攻击获取到。而目前localStorage存储没有对XSS攻击有任何抵御机制,一旦出现XSS漏洞,那么存储在localStorage里的数据就极易被获取到。
如果一个网站存在XSS漏洞,那么攻击者注入如下代码,就可以获取使用localStorage存储在本地的所有信息。

攻击者也可以简单的使用localStorage.removeItem(key)和localStorage.clear()对存储数据进行清空。
(2) 不要存储敏感信息
从(1)中知道,从远程攻击角度来看,localStorage存储的数据容易被XSS攻击获取,所以不宜把身份验证信息或敏感信息用localStorage存储。而从本地攻击角度来看, localStorage自身的存储方式和存储时效并不宜存储敏感信息。
五大浏览器现在都已经支持以localStorage方式进行存储,其中Chrome,Opera,Safari这三款浏览器中都有了查看本地存储的功能模块。但是不同浏览器对localStorage存储方式还是略有不同的。以下是五大浏览器localStorage存储方式:

通过上面的描述可以看出,除了Opera浏览器采用BASE64加密外(BASE64也是可以轻松解密的),其他浏览器均采用明文存储数据。
另一方面,在数据存储的时效上,localStorage并不会像Cookie那样可以设置数据存活的时限,只要用户不主动删除,localStorage存储的数据将会永久存在。
根据以上对存储方式和存储时效的分析,建议不要使用localStorage方式存储敏感信息,那怕这些信息进行过加密。
(3) 严格过滤输入输出
对于本地存储,为了方便加载数据,常常会把数据存储在本地,等再次加载时,直接从本地读取数据显示在网页上。在某些情况下,在localStorage存储中写入或读取数据的时候,如果数据没有经过输入输出严格过滤,那么这些数据极可能被作为HTML代码进行解析,从而产生XSS攻击。
Twitter就发生过localStorage XSS漏洞。此漏洞触发的条件是,在Twitter的个人主页上执行以下存储代码后,每次再打开个人主页时就会弹出/xss/框。
从这段代码可以看出,Twitter会使用localStorage方法把一些个人数据存储到本地,每次加载个人主页面的时候就会从本地存储获取数据,然后由于Twitter忽略了对去除数据的严格过滤,导致存储的代码会被当作HMTL编码执行,进而发生跨站攻击。

有关Twitter localStorage XSS 漏洞详的细信息可以查看:http://www.wooyun.org/bugs/ wooyun-2010-03075。虽然Twitter这个漏洞利用起来非常困难,但它再一次告诉我们:本着一切输入输出都是有害的原则,要对数据进行严格的输入输出过滤。
(4) 容易遭受跨目录攻击
localStroage存储方式不会像Cookie存储一样可以指定域中的路径,在localStroage存储方式中没有域路径的概念。也就是说,如果同一个域下的任意路径存在XSS漏洞,整个域下存储的数据在知道存储名称的情况下都可以被获取到。
假设下面两个链接是使用localStorage来存储数据:

用户xisigr和xhack各自的blog链接虽然属于同一个域,但却有不同的路径,一个路径为xisigr,另一个路径为xhack。假设xisigr用户发现自己的路径下存在存储型XSS漏洞,那么就可以在自己的blog中加入获取数据代码,其中核心代码为localStorage.getItem(“name”)。xhack用户并不需要登录blog,他只要访问http://h.example.com/xisigr,本地存储数据就会被获取到。
(5) 容易遭受DNS欺骗攻击
Google在没有使用HTML5本地存储前,是使用Google Gears方式来进行本地存储的。那时Google Gears就遭到过DNS欺骗攻击。Google Gears支持离线存储,可以把Gmail,WordPresss这样的网站数据以SQLite数据库的形式存储下来,以后用户就可以对存储的网站数据进行离线读取或删除操作。如果攻击者发动DNS欺骗攻击,那么就可以注入本地数据库,获取数据或者留下永久的后门,造成对用户持久的危害。Google Gears所遭受的DNS欺骗攻击方式在HTML5本地存储上也是同样有效的。
(6) 恶意代码栖息的温床
在第六点中给出“恶意代码栖息的温床”这个小标题有些夸大的效果。其实这里想说的是,HTML5本地存储在空间上和时间上都将成为今后存储的趋势,料想“恶意代码们”自然会大雁南飞转移栖息到这张温床上。

那么,何为HTML5本地存储的空间和时间呢?空间这里指的是存储空间,比起Cookie 4K空间的微小来说,HTML5的localStroage方法默认就可以使浏览器存储5M空间可以说是博大,而Safari浏览器可以支持到500M更加让HTML5存储霸气外露。时间上,随着HTML5技术日渐成熟,除了各大浏览器厂商争先在自己的产品中支持HTML5外,一些大应用软件厂商也对其信赖有加。比如2011年11月Adobe宣布放弃手机上的FLASH, 而由HTML5全面取而代之。随着时间的推移,HTML5大步流星的前行速度也会越来越快,也会使得用到HTML5本地存储的应用会越来越多。
上面从理论上分析了 “恶意代码栖息的温床”的可能性。而从实际技术上的可行性也非常简单。下面是在本地留后门的核心代码:
以上分析,均出自天融信TopLAB前沿安全实验室的研究,希望借此文让HTML5的本地存储安全问题得到大家的广泛重视。HTML5非常精彩,但也存在风险,我们要做的工作还很多。

⑵ MAC地址被过滤怎么办

一般MAC地址在网卡中是固定的,当然也有网络高手会想办法去修改自己的MAC地址。修改自己的MAC地址有两种方法,一种是硬件修改,另外一种是软件修改。
硬件的方法就是直接对网卡进行操作,修改保存在网卡的EPROM里面的MAC地址,通过网卡生产厂家提供的修改程序可以更改存储器里的地址。那么什么叫做EPROM呢?EPROM是电子学中一种存储器的专业术语,它是可擦写的,也就是说一张白纸你用钢笔写了一遍以后就不能再用橡皮擦去了,而EPROM这张白纸用铅笔写后可以再擦去,可以反复改变其中数据的存储器。
当然软件修改的方法就相对来说要简单得多了,在Windows中,网卡的MAC保存在注册表中,实际使用也是从注册表中提取的,所以只要修改注册表就可以改变MAC。Windows 9x中修改:打开注册表编辑器,在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\
Service\Class\Net\下的0000,0001,0002。

Windows 2000/XP中的修改:同样打开注册表编辑器,HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\
Class\4D36E970-E325-11CE-BFC1-08002BE10318 中的0000,0001,0002中的DriverDesc,如果在0000找到,就在0000下面添加字符串变量,命名为“NetworkAddress”,值为要设置的MAC地址,例如:000102030405

完成上述操作后重启就好了。一般网卡发出的包的源MAC地址并不是网卡本身写上去的,而是应用程序提供的,只是在通常的实现中,应用程序先从网卡上得到MAC地址,每次发送的时候都用这个MAC作为源MAC而已,而注册表中的MAC地址是在Windows安装的时候从网卡中读入的,只要你的操作系统不重新安装应该问题不大。

有些人说可以有些人尝试过没用,超级兔子据说可以更改这个,你可以试下.

不过目前还没碰到过这么缺德的人,交钱还来这套,大可以跟房东说.人多的话,交的钱比房东宽带的月租还多呢

⑶ 求个文本过滤方面的批处理。

@echooff&
for/f"tokens=*"%%iin('ipconfig/all')do(
set"h=%%i"
ifdefinednset/an+=1
ifnot"!h:本地连接:=!"=="!h!"set/an=-2
if"!n!"gtr"0"if"!n!"lss"8"(
set"h=!h:.=!"
set"h=!h::=:!"
set"h=!h::=:!"
for/f"tokens=1,2delims=:"%%jin("!h!")do(
set"#!n!=%%j=%%k"))
if"!n!"=="8"(
if"!h:adapter=!"=="!h!"set#8=DNS_2=!h!
set"n="))
for/L%%iin(1,1,8)doifdefined#%%iecho!#%%i!&set"!#%%i!"
echo/&echo使用时以上面显示的等号左边为变量即可,例如IPAddress
echo%ipaddress%
pause

⑷ windows下如何过滤CMD的命令结果(按行号过滤)

@专echo off
setlocal enabledelayedexpansion
set n=&set stop=
for /f "tokens=*" %%a in ('ipconfig') do (
set /a n+=1
if !属n! equ 5 set stop=1
if !n! gtr 10 set stop=
if !n! equ 12 set stop=1
if !n! gtr 17 set stop=
if not defined stop echo %%a
)
pause

⑸ 如果我的MAC地址被过滤了怎么办!

不能通过路由器去另外一个网络,但有办法能修改你的MAC地址:
1 、在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0000 、 0001 、 0002 等主键下,查找 DriverDesc ,内容为你要修改的网卡的描述,如“ Realtek RTL8029(AS)-based PCI Ethernet Adapter ”。

2 、在其下,添加一个字符串,命名为 NetworkAddress ,其值设为你要的 MAC 地址(注意地址还是连续写)。如: 00E0DDE0E0E0 。

3 、然后到其下 Ndi\params 中添加一项名为 NetworkAddress 的主键,在该主键下添加名为 default 的字符串,其值是你要设的 MAC 地址,要连续写,如: 000000000000 。(实际上这只是设置在后面提到的高级属性中的“初始值”,实际使用的 MAC 地址还是取决于在第 2 点中提到的 NetworkAddress 参数,这个参数一旦设置后,以后高级属性中的值就是 NetworkAddress 给出的值而非 default 给出的了。)

4 、在 NetworkAddress 的主键下继续添加名为 ParamDesc 的字符串,其作用为指定 NetworkAddress 主键的描述,其值可自己命名,如“ Network Address ”,这样在网卡的高级属性中就会出现 Network Address 选项,就是你刚在注册表中加的新项 NetworkAddress ,以后只要在此修改 MAC 地址就可以了。继续添加名为 Optional 的字符串,其值设为“ 1 ”,则以后当你在网卡的高级属性中选择 Network Address 项时,右边会出现“不存在”选项。

5 、重新启动你的计算机,打开网络邻居的属性,双击相应网卡项会发现有一个 Network Address 的高级设置项,可以用来直接修改 MAC 地址或恢复原来的地址。

⑹ 陆游器配置中的login local是什么意思

好好看看吧 不多说了

路由器在计算机网络中有着举足轻重的地位,是计算机网络的桥梁。通过它不仅可以连通不同的网络,还能选择数据传送的路径,并能阻隔非法的访问。

路由器的配置对初学者来说,并不是件十分容易的事。现将路由器的一般配置和简单调试介绍给大家,供朋友们在配置路由器时参考,本文以Cisco2501为例。

Cisco2501有一个以太网口(AUI)、一个Console口(RJ45)、一个AUX口(RJ45)和两个同步串口,支持DTE和DCE设备,支持 EIA/TIA-232、 EIA/TIA-449、 V.35 、X.25和EIA-530接口。

一.配置

1.配置以太网端口

# conf t(从终端配置路由器)

# int e0(指定E0口)

# ip addr ABCD XXXX(ABCD 为以太网地址,XXXX为子网掩码)

# ip addr ABCD XXXX secondary(E0口同时支持两个地址类型。如果第一个为 A类地址,则第二个为B或C类地址)

# no shutdown(激活E0口)

# exit

完成以上配置后,用ping命令检查E0口是否正常。如果不正常,一般是因为没有激活该端口,初学者往往容易忽视。用no shutdown命令激活E0口即可。

2.X.25的配置

# conf t

# int S0(指定S0口)

# ip addr ABCD XXXX(ABCD 为以太网S0 的IP地址,XXXX为子网掩码)

# encap X25-ABC(封装X.25协议。ABC指定X.25为DTE或DCE操作,缺省为DTE)

# x25 addr ABCD(ABCD为S0的X.25端口地址,由邮电局提供)

# x25 map ip ABCD XXXX br(映射的X.25地址。ABCD为对方路由器(如:S0)的IP 地址,XXXX为对方路由器(如:S0)的X.25端口地址)

# x25 htc X(配置最高双向通道数。X的取值范围1-4095,要根据 邮电局实际提供的数字配置)

# x25 nvc X(配置虚电路数,X不可超过邮电局实际提供的数否则将影响数据的正常传输)

# exit

S0端口配置完成后,用no shutdown命令激活E0口。如果ping S0端口正常,ping 映射的X.25 IP地址即对方路由器端口IP地址不通,则可能是以下几种情况引起的:1)本机X.25地址配置错误,重新与邮局核对(X.25地址长度为13位);2)本机映射IP地址或X.25地址配置错误,重新配置正确;3)对方IP地址或X.25地址配置错误;4)本机或对方路由配置错误。

能够与对方通讯,但有丢包现象。出现这种情况,一般有以下几种可能:1)线路情况不好,或网卡、RJ45插头接触不良;2)x25 htc最高双向通道数X的取值范围和x25nvc 虚电路数X超出邮电局实际提供的数字。最高双向通道数和虚电路数这两个值越大越好,但绝对不能超出邮电局实际提供的数字,否则就会出现丢包现象。

3.专线的配置

# conf t

# intS2(指定S2口)

# ip addr ABCD XXXX(ABCD 为S2 的IP地址,XXXX为子网掩码)

# exit

专线口配置完成后,用no shutdown命令激活S2口即可。

4.帧中继的配置

# conf t

# int s0

# ip addr ABCD XXXX (ABCD 为S0 的IP地址,XXXX为子网掩码)

# encap frante_relay (封装frante_relay 协议)

# no nrzi_encoding (NRZI=NO)

# frame_relay lmi_type q933a (LMI使用Q933A标准.LMI(Local management Interface) 有3种:ANSI:T1.617、CCITTY:Q933A和Cisco特有的标准)

# fram-relay intf-typ ABC(ABC为帧中继设备类型,它们分别是DTE设备、DCE交换机或NNI(网络接点接口)支持)

# frame_relay interface_dlci 110 br(配置DLCI(数据链路连接标识符))

# frame-relay map ip ABCD XXXX broadcast (建立帧中继映射。ABCD为对方IP地址,XXXX为本地DLCI号,broadcast允许广播向前转发或更新路由)

# no shutdown (激活本端口)

# exit

帧中继S0端口配置完成后,用ping命令检查S0口。如果不正常,通常是因为没有激活该端口,用no shutdown命令激活S0口即可。如果ping S0端口正常,ping 映射的IP地址不正常,则可能是帧中继交换机或对方配置错误,需要综合排查。

5.配置同步/异步口(适用于2522)

# conf t

# int s2

# ph asyn (配置S2为异步口)

# ph sync (配置S2为同步口)

6.动态路由的配置

# conf t

# router eigrp 20 (使用EIGRP路由协议。常用的路由协议有RIP、IGRP、IS-IS等)

# passive-interface serial0 (若S0与X.25相连,则输入本条指令)

# passive-interface serial1 (若S1与X.25相连,则输入本条指令)

# network ABCD (ABCD为本机的以太网地址)

# network XXXX (XXXX为S0的IP地址)

# no auto-summary

# exit

7.静态路由的配置

# ip router ABCD XXXX YYYY 90 (ABCD为对方路由器的以太网地址,XXXX 为子网掩码,YYYY为对方对应的广域网端口地址)

# dialer-list 1 protocol ip permail

二. 综合调试

当路由器全部配置完毕后,可进行一次综合调试。

1.首先将路由器的以太网口和所有要使用的串口都激活。方法是进入该口,执行no shutdown。

2.将和路由器相连的主机加上缺省路由(中心路由器的以太地址)。方法是在Unix系统的超级用户下执行:router add default XXXX 1(XXXX为路由器的E0口地址)。每台主机都要加缺省路由,否则,将不能正常通讯。

3.ping本机的路由器以太网口,若不通,可能以太网口没有激活或不在一个网段上。ping广域网口,若不通,则没有加缺省路由。ping对方广域网口,若不通,路由器配置错误。ping主机以太网口,若不通,对方主机没有加缺省路由。

4.在专线卡X.25主机上加网关(静态路由)。方法是在Unix系统的超级用户下执行:router add X.X.X.X Y.Y.Y.Y 1(X.X.X.X为对方以太网地址,Y.Y.Y.Y为对方广域网地址)。

5.使用Tracert对路由进行跟踪,以确定不通网段。

⑺ 锐捷校园网认证 IE代理过滤显示*.local,电脑不能上网。

我也碰到这种情况了,你后来解决了吗?

⑻ winpcap怎么设置过滤一个网段

设置过滤器要用到两个函数,一个是pcap_compile(),另一个是pcao_setfilter()。他们的函数原型如下所示:
int pcap_compile (pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask)

1、p是一个打开的网络设备的描述符。
2、fp是一个指针,用来存储一个编译好的过滤码。我们需要提前设置 struct bpf_program fcode 在这里使用。
3、str是字符串(以\0结尾),它指定一个字符串性质的过滤描述,通过这个函数把这个描述转换成可供内部使用的过滤码。
4、optimize设置是否要进行优化。一般为1。
5、netmask就是我们所打开的设备的netmask,不知道这个怎么用。一般用d->addresses->netmask这个就可以了。
return: 如果出错的话,就会返回一个小于0的值。

然后就是设置这个过滤器:
int pcap_setfilter (pcap_t *p, struct bpf_program *fp)

1、p就是一个已经打开的设备的描述符。
2、fp是用上面的函数编译好的过滤码,现在把这个过滤码设置到系统中去。

附上一个代码:
#define _CRT_SECURE_NO_WARNINGS

#include "pcap.h"

void packet_handler(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);

int main()
{
pcap_t *cap_ins_des;
pcap_if_t *alldevs;
pcap_if_t *d;
char source[PCAP_BUF_SIZE];
char errbuf[PCAP_ERRBUF_SIZE];
int i;
u_int netmask;
char packet_filter[] = "ip and udp"; // the filter
struct bpf_program fcode; // used in pcap_compile()

/* set the source */
if (pcap_createsrcstr(source, PCAP_SRC_IFLOCAL, NULL, NULL, NULL, errbuf) == -1) {
printf("%s\n", errbuf);
exit(-1);
}
printf("source: %s\n", source);

/* find all devices */
if (pcap_findalldevs_ex(source, NULL, &alldevs, errbuf) == -1) {
printf("%s\n", errbuf);
exit(-1);
}

/* choose one devices */
d = alldevs;
while (d != NULL) {
printf("%s, %s\n", d->name, d->description);
d = d->next;
}
scanf("%d", &i);
d = alldevs;
while (--i)
d = d->next;
printf("selected device: %s\n", d->name);

/* open one device */
cap_ins_des = pcap_open(d->name, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf);
if (cap_ins_des == NULL) {
printf("%s\n", errbuf);
pcap_freealldevs(alldevs);
exit(-1);
}

/* get the netmask, used at compiling the filter */
if (d->addresses != NULL)
netmask = ((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr; /*@#$%^&*!*/
else
netmask = 0xffffff; /* 255.25.255.0 */

// netmask = 0;

/* compile the filter */
if (pcap_compile(cap_ins_des, &fcode, packet_filter, 1, netmask) < 0) {
printf("Error\n");
pcap_freealldevs(alldevs);
exit(-1);
}

/* set the filter */
if (pcap_setfilter(cap_ins_des, &fcode) < 0) {
printf("Error\n");
pcap_freealldevs(alldevs);
exit(-1);
}

pcap_freealldevs(alldevs);

/* start the capture */
pcap_loop(cap_ins_des, 30, packet_handler, NULL);

return 0;
}

void packet_handler(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
{
printf("in packet handler\n");
return;
}

⑼ 如何在批处理中过滤包含特定名字的文件

这个方法很多, 简单点就比较下子串就专好




for/r.%%ain(*.js)do(
setFile=%%a
if"min"neq!属File:~-6,3!(
ug...
)
)

⑽ 如何快速过滤出一次请求的所有日志

如何快速过滤出一次请求的所有日志?
前言
在现网出现故障时,我们经常需要获取一次请求流程里的所有日志进行定位。如果请求只在一个线程里处理,则我们可以通过线程ID来过滤日志,但如果请求包含异步线程的处理,那么光靠线程ID就显得捉襟见肘了。
IoT平台,提供了接收设备上报数据的能力, 当数据到达平台后,平台会进行一些复杂的业务逻辑处理,如数据存储,规则引擎,数据推送,命令下发等等。由于这个逻辑之间没有强耦合的关系,所以通常是异步处理。如何将一次数据上报请求中包含的所有业务日志快速过滤出来,就是本文要介绍的。
正文
SLF4J日志框架提供了一个MDC(Mapped Diagnostic Contexts)工具类,谷歌翻译为映射的诊断上下文,从字面上很难理解,我们可以先实战一把。
public class Main {
private static final String KEY = "requestId";
private static final Logger logger = LoggerFactory.getLogger(Main.class);

public static void main(String[] args) {
// 入口传入请求ID
MDC.put(KEY, UUID.randomUUID().toString());

// 打印日志
logger.debug("log in main thread 1");
logger.debug("log in main thread 2");
logger.debug("log in main thread 3");
// 出口移除请求ID
MDC.remove(KEY);
}
}
我们在main函数的入口调用MDC.put()方法传入请求ID,在出口调用MDC.remove()方法移除请求ID。配置好log4j2.xml文件后,运行main函数,可以在控制台看到以下日志输出:
2018-02-17 13:19:52.606 {requestId=f97ea0fb-2a43-40f4-a3e8-711f776857d0} [main] DEBUG cn.wudashan.Main - log in main thread 1
2018-02-17 13:19:52.609 {requestId=f97ea0fb-2a43-40f4-a3e8-711f776857d0} [main] DEBUG cn.wudashan.Main - log in main thread 2
2018-02-17 13:19:52.609 {requestId=f97ea0fb-2a43-40f4-a3e8-711f776857d0} [main] DEBUG cn.wudashan.Main - log in main thread 3
从日志中可以明显地看到花括号中包含了(映射的)请求ID(requestId),这其实就是我们定位(诊断)问题的关键字(上下文)。有了MDC工具,只要在接口或切面植入put()和remove()代码,在现网定位问题时,我们就可以通过grep requestId=xxx *.log快速的过滤出某次请求的所有日志。
进阶
然而,MDC工具真的有我们所想的这么方便吗?回到我们开头,一次请求可能涉及多线程异步处理,那么在多线程异步的场景下,它是否还能正常运作呢?Talk is cheap, show me the code。
public class Main {
private static final String KEY = "requestId";
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
// 入口传入请求ID
MDC.put(KEY, UUID.randomUUID().toString());
// 主线程打印日志
logger.debug("log in main thread");
// 异步线程打印日志
new Thread(new Runnable() {
@Override
public void run() {
logger.debug("log in other thread");
}
}).start();
// 出口移除请求ID
MDC.remove(KEY);
}
}
代码里我们新起了一个异步线程,并在匿名对象Runnable的run()方法打印日志。运行main函数,可以在控制台看到以下日志输出:
2018-02-17 14:05:43.487 {requestId=e6099c85-72be-4986-8a28-de6bb2e52b01} [main] DEBUG cn.wudashan.Main - log in main thread
2018-02-17 14:05:43.490 {} [Thread-1] DEBUG cn.wudashan.Main - log in other thread
不幸的是,请求ID在异步线程里不打印了。这是怎么回事呢?要解决这个问题,我们就得知道MDC的实现原理。由于篇幅有限,这里就暂不详细介绍,MDC之所以在异步线程中不生效是因为底层采用ThreadLocal作为数据结构,我们调用MDC.put()方法传入的请求ID只在当前线程有效。感兴趣的小伙伴可以自己深入一下代码细节。
知道了原理那么解决这个问题就轻而易举了,我们可以使用装饰器模式,新写一个MDCRunnable类对Runnable接口进行一层装饰。在创建MDCRunnable类时保存当前线程的MDC值,在执行run()方法时再将保存的MDC值拷贝到异步线程中去。代码实现如下:
public class MDCRunnable implements Runnable {
private final Runnable runnable;
private final Map<String, String> map;
public MDCRunnable(Runnable runnable) {
this.runnable = runnable;
// 保存当前线程的MDC值
this.map = MDC.getCopyOfContextMap();
}
@Override
public void run() {
// 传入已保存的MDC值
for (Map.Entry<String, String> entry : map.entrySet()) {
MDC.put(entry.getKey(), entry.getValue());
}
// 装饰器模式,执行run方法
runnable.run();
// 移除已保存的MDC值
for (Map.Entry<String, String> entry : map.entrySet()) {
MDC.remove(entry.getKey());
}
}

}
接着,我们需要对main函数里创建的Runnable实现类进行装饰:
public class Main {
private static final String KEY = "requestId";
private static final Logger logger = LoggerFactory.getLogger(Main.class);
private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
// 入口传入请求ID
MDC.put(KEY, UUID.randomUUID().toString());
// 主线程打印日志
logger.debug("log in main thread");
// 异步线程打印日志,用MDCRunnable装饰Runnable
new Thread(new MDCRunnable(new Runnable() {
@Override
public void run() {
logger.debug("log in other thread");
}
})).start();
// 异步线程池打印日志,用MDCRunnable装饰Runnable
EXECUTOR.execute(new MDCRunnable(new Runnable() {
@Override
public void run() {
logger.debug("log in other thread pool");
}
}));
EXECUTOR.shutdown();
// 出口移除请求ID
MDC.remove(KEY);
}
}
执行main函数,将会输出以下日志:
2018-03-04 23:44:05.343 {requestId=5ee2a117-e090-41d8-977b-cef5dea09d34} [main] DEBUG cn.wudashan.Main - log in main thread
2018-03-04 23:44:05.346 {requestId=5ee2a117-e090-41d8-977b-cef5dea09d34} [Thread-1] DEBUG cn.wudashan.Main - log in other thread
2018-03-04 23:44:05.347 {requestId=5ee2a117-e090-41d8-977b-cef5dea09d34} [pool-2-thread-1] DEBUG cn.wudashan.Main - log in other thread pool
Congratulations!经过我们的努力,最终在异步线程和线程池中都有requestId打印了!
总结
本文讲述了如何使用MDC工具来快速过滤一次请求的所有日志,并通过装饰器模式使得MDC工具在异步线程里也能生效。有了MDC,再通过AOP技术对所有的切面植入requestId,就可以将整个系统的任意流程的日志过滤出来。使用MDC工具,在开发自测阶段,可以极大地节省定位问题的时间,提升开发效率;在运维维护阶段,可以快速地收集相关日志信息,加快分析速度。

阅读全文

与local过滤相关的资料

热点内容
反渗透膜处理后的废水 浏览:346
韩国电影主角白天瘫痪晚上正常行走 浏览:296
水宜生的过滤网能用多久 浏览:179
污水为什么只看总氮 浏览:347
外国影片有一个在马车偷情 浏览:951
有什么现在看电影的网址 浏览:177
反渗透出水率低怎么办 浏览:197
尺度大同志电影 浏览:647
污水处理两个水池是什么水池 浏览:284
李采谭2016作品 浏览:237
港台四级片在线观看 浏览:712
任达华温碧霞惊变电影未删减 浏览:691
重生中世纪贵族领主 浏览:522
梅花与达夫的印度电影 浏览:933
福州10吨反渗透设备 浏览:406
水咸用什么爱惠浦净水器 浏览:436
管线饮水机装修怎么预留接软管口 浏览:780
奴隶主与奴隶相关影视 浏览:547
树脂粉袋子拿什么来粘 浏览:698
超滤是比较好还是反渗透好 浏览:506