当前位置: 首页 > news >正文

烤羊肉串引来的思考--命令模式

1.1 吃羊肉串!

        烧烤摊旁边等着拿肉串的人七嘴八舌地叫开了。场面有些混乱,由于人实在太多,烤羊肉串的老板已经分不清谁是谁,造成分发错误,收钱错误,烤肉质量不过关等。

        外面打游击烤羊肉串和这种开门店做烤肉,哪个更赚钱?

        这很难讲,毕竟各有各的好,在外面打游击,好处是不用租房,不用上税,最多就是交点'保护费',但下雨天不行、大白天不行、太晚也不行,一般都是傍晚做几个钟头,顾客也不固定,像刚才那个,由于人多造成混乱,于是就放跑了我们这两条大鱼,其实他的生意是不稳定的。大白天,城管没下班呢,怎能容忍他如此安逸。超过晚上11点,夜深人静,谁还愿意站在路边吃烤肉。但开门店就不一样了,不管什么时间都可以做生意,由于环境相对好,所以固定客户就多,看似好像房租交出去了,但其实由于顾客多,而且是正经做生意,所以最终可以赚到大钱。

1.2 烧烤摊vs.烧烤店

        "因为要吃烤肉的人太多,都希望能最快吃到肉串,烤肉老板一个人,所以有些混乱。"
        "还不止这些,老板一个人,来的人一多,他就未必记得住谁交没交过钱,要几串,需不需要放辣等。"
        "是呀,大家都站在那里,没什么事,于是都盯着烤肉去了,哪一串多、哪一串少、哪一串烤得好、哪一串烤得焦看得清清楚楚,于是'挑剔'也就接踵而至。"
        "这其实就是我们在编程中常说的什么?"
        "我想想,你是想说'紧耦合'?"
        "哈,不错,不枉我的精心栽培。"
        "由于客户和烤羊肉串老板的'紧耦合',所以容易出错,也容易产生挑剔。"
        "说得对,这其实就是'行为请求者'与'行为实现者'的紧耦合。我们需要记录哪个人要几串羊肉串,有没有特殊要求(放辣不放辣),付没付过钱,谁先谁后,这其实都相当于对请求做什么?"
        "对请求做记录,啊,应该是做日志。"
        "很好,那么如果有人需要退回请求,或者要求烤肉重烤,这其实就是?"
        "就相当于撤销和重做吧。"
        "OK,所以对请求排队或记录请求日志,以及支持可撤销的操作等行为时,'行为请求者'与'行为实现者'的紧耦合是不太适合的。你说怎么办?"
        "哈,这是最终结果,不是这个意思,我们是烤肉请求者,烤肉的师傅是烤肉的实现者,对于开门店来说,我们用得着去看着烤肉的实现过程吗?现实是怎么做的呢?"
        "哦,我明白你的意思了,我们不用去认识烤肉者是谁,连他的面都不用见到,我们只需要给接待我们的服务员说我们要什么就可以了。他可以记录我们的请求,然后再由他去通知烤肉师傅做。"

        "而且,由于我们所做的请求,其实也就是我们点肉的订单,上面有很详细的我们的要求,所有的客户都有这一份订单,烤肉师傅可以按先后顺序操作,不会混乱,也不会遗忘了。"
        "收钱的时候,也不会多收或少收。"
        "优点还不止这里,比如说,""服务员,我们那十串羊肉串太多了,改成六串就可以了。"
        "好的!"服务员答道。
        "你注意看他接着做了什么?"
        "他好像在一个小本子上划了一下,然后去通知烤肉师傅了。"
        "这其实是在做撤销行为的操作。由于有了记录,所以最终算账是不会错的。"
        "对对对,这种利用一个服务员来解耦客户和烤肉师傅的处理好处真的很多。"

1.3 紧耦合设计

代码结构图

package code.chapter23.command1;public class Test {public static void main(String[] args) {System.out.println("**********************************************");       System.out.println("《大话设计模式》代码样例");System.out.println();       Barbecuer boy = new Barbecuer();boy.bakeMutton();boy.bakeMutton();boy.bakeMutton();boy.bakeChickenWing();boy.bakeMutton();boy.bakeMutton();boy.bakeChickenWing();System.out.println();System.out.println("**********************************************");}
}//烤肉串者
class Barbecuer{//烤羊肉public void bakeMutton(){System.out.println("烤羊肉串!");}//烤鸡翅public void bakeChickenWing(){System.out.println("烤鸡翅!");}
}

        "很好,这就是路边烤肉的对应,如果用户多了,请求多了,就容易乱了。那你再尝试用门店的方式来实现它。"
        "我知道一定需要增加服务员类,但怎么做有些不明白。"
        "嗯,这里的确是难点,要知道,不管是烤羊肉串,还是烤鸡翅,还是其他烧烤,这些都是'烤肉串者类'的行为,也就是他的方法,具体怎么做都是由方法内部来实现,我们不用去管它。但是对于'服务员'类来说,他其实就是根据用户的需要,发个命令,说:'有人要十个羊肉串,有人要两个鸡翅',这些都是命令……"
        "我明白了,你的意思是,把'烤肉串者'类当中的方法,分别写成多个命令类,那么它们就可以被'服务员'来请求了?"
        "是的,说得没错,这些命令其实差不多都是同一个样式,于是你就可以泛化出一个抽象类,让'服务员'只管对抽象的'命令'发号施令就可以了。具体是什么命令,即烤什么,由客户来决定吧。"

1.4 命令模式

        命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。[DP]
命令模式(Command)结构图

package code.chapter23.command0;import java.util.ArrayList;
import java.util.Date;
import java.text.SimpleDateFormat;public class Test {public static void main(String[] args) {System.out.println("**********************************************");       System.out.println("《大话设计模式》代码样例");System.out.println(); Receiver receiver = new Receiver();Command command = new ConcreteCommand(receiver);Invoker invoker = new Invoker();invoker.setCommand(command);invoker.executeCommand();System.out.println();System.out.println("**********************************************");}
}//抽象命令类
abstract class Command {protected Receiver receiver;public Command(Receiver receiver){this.receiver = receiver;}//执行命令public abstract void excuteCommand();
}//具体命令类
class ConcreteCommand extends Command{public ConcreteCommand(Receiver receiver){super(receiver);}public void excuteCommand(){receiver.action();}
}class Invoker{private Command command;public void setCommand(Command command){this.command = command;}public void executeCommand(){command.excuteCommand();}}class Receiver{public void action(){System.out.println("执行请求!");}
}


Command类,用来声明执行操作的接口。
ConcreteCommand类,将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现executeCommand。
Invoker类,要求该命令执行这个请求。
Receiver类,知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者。
客户端代码,创建一个具体命令对象并设定它的接收者。

1.5 松耦合设计

代码结构图

package code.chapter23.command2;public class Test {public static void main(String[] args) {System.out.println("**********************************************");       System.out.println("《大话设计模式》代码样例");System.out.println();       //开店前的准备Barbecuer boy = new Barbecuer();//烤肉厨师Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);            //烤羊肉串Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);  //烤鸡翅Waiter girl = new Waiter();     //服务员//开门营业girl.setOrder(bakeMuttonCommand1);      //下单烤羊肉串girl.notifyCommand();                   //通知厨师烤肉girl.setOrder(bakeMuttonCommand1);      //下单烤羊肉串girl.notifyCommand();                   //通知厨师烤肉girl.setOrder(bakeChickenWingCommand1); //下单烤鸡翅girl.notifyCommand();                   //通知厨师烤肉System.out.println();System.out.println("**********************************************");}
}//抽象命令类
abstract class Command {protected Barbecuer receiver;public Command(Barbecuer receiver){this.receiver = receiver;}//执行命令public abstract void excuteCommand();
}//烤羊肉命令类
class BakeMuttonCommand extends Command{public BakeMuttonCommand(Barbecuer receiver){super(receiver);}public void excuteCommand(){receiver.bakeMutton();}
}//烤鸡翅命令类
class BakeChickenWingCommand extends Command{public BakeChickenWingCommand(Barbecuer receiver){super(receiver);}public void excuteCommand(){receiver.bakeChickenWing();}
}//服务员类
class Waiter{private Command command;//设置订单public void setOrder(Command command){this.command = command;}//通知执行public void notifyCommand(){command.excuteCommand();}
}//烤肉串者
class Barbecuer{//烤羊肉public void bakeMutton(){System.out.println("烤羊肉串!");}//烤鸡翅public void bakeChickenWing(){System.out.println("烤鸡翅!");}
}

        "很好很好,基本都把代码实现了。但没有体现出命令模式的作用。比如下面几个问题:第一,真实的情况其实并不是用户点一个菜,服务员就通知厨房去做一个,那样不科学,应该是点完烧烤后,服务员一次通知制作;第二,如果此时鸡翅没了,不应该是客户来判断是否还有,客户哪知道有没有呀,应该是服务员或烤肉串者来否决这个请求;第三,客户到底点了哪些烧烤或饮料,这是需要记录日志的,以备收费,也包括后期的统计;第四,客户完全有可能因为点的肉串太多而考虑取消一些还没有制作的肉串。这些问题都需要得到解决。"
        "这,这怎么办到呀?"
        "重构一下服务员Waiter类,尝试改一下。将private Command command;改成一个ArrayList,就能解决了。"

1.6 进一步改进命令模式

package code.chapter23.command3;import java.util.ArrayList;
import java.util.Date;
import java.text.SimpleDateFormat;public class Test {public static void main(String[] args) {System.out.println("**********************************************");       System.out.println("《大话设计模式》代码样例");System.out.println();       //开店前的准备Barbecuer boy = new Barbecuer();//烤肉厨师Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);            //烤羊肉串Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);  //烤鸡翅Waiter girl = new Waiter();     //服务员System.out.println("开门营业,顾客点菜");girl.setOrder(bakeMuttonCommand1);      //下单烤羊肉串girl.setOrder(bakeMuttonCommand1);      //下单烤羊肉串girl.setOrder(bakeMuttonCommand1);      //下单烤羊肉串girl.setOrder(bakeMuttonCommand1);      //下单烤羊肉串girl.setOrder(bakeMuttonCommand1);      //下单烤羊肉串girl.cancelOrder(bakeMuttonCommand1);   //取消一串羊肉串订单girl.setOrder(bakeChickenWingCommand1); //下单烤鸡翅System.out.println("点菜完毕,通知厨房烧菜");girl.notifyCommand();                   //通知厨师System.out.println();System.out.println("**********************************************");}
}//抽象命令类
abstract class Command {protected Barbecuer receiver;public Command(Barbecuer receiver){this.receiver = receiver;}//执行命令public abstract void excuteCommand();
}//烤羊肉命令类
class BakeMuttonCommand extends Command{public BakeMuttonCommand(Barbecuer receiver){super(receiver);}public void excuteCommand(){receiver.bakeMutton();}
}//烤鸡翅命令类
class BakeChickenWingCommand extends Command{public BakeChickenWingCommand(Barbecuer receiver){super(receiver);}public void excuteCommand(){receiver.bakeChickenWing();}
}//服务员类
class Waiter{private ArrayList<Command> orders = new ArrayList<Command>();//设置订单public void setOrder(Command command){String className=command.getClass().getSimpleName();if (className.equals("BakeChickenWingCommand")){System.out.println("服务员:鸡翅没有了,请点别的烧烤。");}else{this.orders.add(command);System.out.println("增加订单:"+className+" 时间:"+getNowTime());}}//取消订单public void cancelOrder(Command command){String className=command.getClass().getSimpleName();orders.remove(command);System.out.println("取消订单:"+className+" 时间:"+getNowTime());}//通知执行public void notifyCommand(){for(Command command : orders)command.excuteCommand();}private String getNowTime(){SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");return formatter.format(new Date()).toString();}
}//烤肉串者
class Barbecuer{//烤羊肉public void bakeMutton(){System.out.println("烤羊肉串!");}//烤鸡翅public void bakeChickenWing(){System.out.println("烤鸡翅!");}
}

1.7 命令模式的作用

        "我觉得第一,它能较容易地设计一个命令队列;第二,在需要的情况下,可以较容易地将命令记入日志;第三,允许接收请求的一方决定是否要否决请求。"
"还有就是第四,可以容易地实现对请求的撤销和重做;第五,由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。其实还有最关键的优点就是命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。[DP]
        "但是否是碰到类似情况就一定要实现命令模式呢?"
        "这就不一定了,比如命令模式支持撤销/恢复操作功能,但你还不清楚是否需要这个功能时,你要不要实现命令模式?"
        "要,万一以后需要就不好办了。"
        "其实应该是不要实现。敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。[R2P]"

相关文章:

烤羊肉串引来的思考--命令模式

1.1 吃羊肉串&#xff01; 烧烤摊旁边等着拿肉串的人七嘴八舌地叫开了。场面有些混乱&#xff0c;由于人实在太多&#xff0c;烤羊肉串的老板已经分不清谁是谁&#xff0c;造成分发错误&#xff0c;收钱错误&#xff0c;烤肉质量不过关等。 外面打游击烤羊肉串和这种开门店做烤…...

Python 描述符

文章目录 类型&#xff1a;数据描述符&#xff1a;方法描述符&#xff1a;描述符的要包括以下几点:方法描述符实现缓存 描述符(Descriptor)是 Python 中一个非常强大的特性,它允许我们自定义属性的访问行为。使用描述符,我们可以创建一些特殊的属性,在访问这些属性时执行自定义…...

Go语言创建HTTP服务器

Web服务器可提供网页、Web服务和文件,而Go语言为创建Web服务器提供了强大的支持。 1.通过Hello World Web 服务器宣告您的存在 标准库中的net/http包提供了多种创建HTTP服务器的方法,它还提供了一个基本的路由器。 package mainimport ("net/http" )func helloWo…...

【LeetCode热题100】【栈】柱状图中最大的矩形

题目链接&#xff1a;84. 柱状图中最大的矩形 - 力扣&#xff08;LeetCode&#xff09; 要找最大的矩形就是要找以每根柱子为高度往两边延申的边界&#xff0c;要作为柱子的边界就必须高度不能低于该柱子&#xff0c;否则矩形无法同高&#xff0c;也就是需要找出以每根柱子为高…...

谷歌浏览器插件开发速成指南:弹窗

诸神缄默不语-个人CSDN博文目录 本文介绍谷歌浏览器插件开发的入门教程&#xff0c;阅读完本文后应该就能开发一个简单的“hello world”插件&#xff0c;效果是出现写有“Hello Extensions”的弹窗。 作为系列文章的第一篇&#xff0c;本文还希望读者阅读后能够简要了解在此基…...

Lakehouse 大数据概念

“Lakehouse” 是一个相对新的概念,是大数据理论中的一个重要发展方向。它试图结合传统的数据湖(Data Lake)和数据仓库(Data Warehouse)的优点,以创造一种更为灵活和强大的数据管理体系。 在传统的大数据架构中,数据湖用于存储原始、未加工的数据,而数据仓库则用于存储…...

MySQL学习笔记(二)

1、把查询结果中去除重复记录 2、连接查询 从一张表中单独查询&#xff0c;称为单表查询。emp表和dept表联合起来查询数据&#xff0c;从emp表中取员工名字&#xff0c;从dept表中取部门名字&#xff0c;这种跨表查询&#xff0c;多张表联合起来查询数据&#xff0c;被称为连…...

Verilog语法——按位取反“~“和位宽扩展的优先级

前言 先说结论&#xff0c;如下图所示&#xff0c;在Verilog中“~ ”按位取反的优先级是最高的&#xff0c;但是在等式计算时&#xff0c;有时候会遇到位宽扩展&#xff0c;此时需要注意的是位宽扩展的优先级高于“~”。 验证 仿真代码&#xff0c;下面代码验证的是“~”按位取…...

Navicat工具使用

Navicat的本质&#xff1a; 在创立连接时提前拥有了数据库用户名和密码 双击数据库时&#xff0c;相当于建立了一个链接关系 点击运行时&#xff0c;远程执行命令&#xff0c;就像在xshell上操作Linux服务器一样&#xff0c;将图像化操作转换成SQL语句去后台执行 一、打开Navi…...

linux常用指令(一)——mv、rm、which、find

mv命令&#xff1a; 用于查看文件内容 语法&#xff1a;mv 参数1 参数2 参数1&#xff0c;linux路径&#xff0c;表示被移动的文件或文件夹 参数2&#xff0c;linux路径&#xff0c;表示要移动去的地方&#xff0c;如果目标不存在&#xff0c;则进行改名 rm命令&#xff1a…...

lottery-攻防世界

题目 flag在这里要用钱买&#xff0c;这是个赌博网站。注册个账号&#xff0c;然后输入七位数字&#xff0c;中奖会得到相应奖励。 githacker获取网站源码 &#xff0c;但是找到了flag文件但是没用。 bp 抓包发现api.php&#xff0c;并且出现我们的输入数字。 根据题目给的附…...

深入理解指针2:数组名理解、一维数组传参本质、二级指针、指针数组和数组指针、函数中指针变量

目录 1、数组名理解 2、一维数组传参本质 3、二级指针 4、指针数组和数组指针 5、函数指针变量 1、数组名理解 首先来看一段代码&#xff1a; int main() {int arr[10] { 1,2,3,4,5,6,7,8,9,10 };printf("%d\n", sizeof(arr));return 0; } 输出的结果是&…...

【C/C++】C语言实现单链表

C语言实现单链表 简单描述代码运行结果 简单描述 用codeblocks编译通过 源码参考连接 https://gitee.com/IUuaena/data-structures-c.git 代码 common.h #ifndef COMMON_H_INCLUDED #define COMMON_H_INCLUDED#define ELEM_TYPE int //!< 链表元素类型/*! brief 返回值类…...

VBA数据库解决方案第九讲:把数据库的内容在工作表中显示

《VBA数据库解决方案》教程&#xff08;版权10090845&#xff09;是我推出的第二套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;是学完字典后的另一个专题讲解。数据库是数据处理的利器&#xff0c;教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…...

蓝桥杯刷题-12-公因数匹配-数论(分解质因数)不是很理解❓❓

蓝桥杯2023年第十四届省赛真题-公因数匹配 给定 n 个正整数 Ai&#xff0c;请找出两个数 i, j 使得 i < j 且 Ai 和 Aj 存在大于 1 的公因数。 如果存在多组 i, j&#xff0c;请输出 i 最小的那组。如果仍然存在多组 i, j&#xff0c;请输出 i 最小的所有方案中 j 最小的那…...

机器视觉学习(十二)—— 绘制图形

目录 一、绘制函数参数说明 1.1 cv2.line(&#xff09;绘制直线 1.2 cv2.rectangle&#xff08;&#xff09;绘制矩形 1.3 cv2.circle&#xff08;&#xff09; 绘制圆形 1.4 cv2.ellipse&#xff08;&#xff09;绘制椭圆 1.5 cv2.polylines&#xff08;&#xff09;绘制…...

软考信息处理技术员2024年5月报名流程及注意事项

2024年5月软考信息处理技术员报名入口&#xff1a; 中国计算机技术职业资格网&#xff08;http://www.ruankao.org.cn/&#xff09; 2024年软考报名时间暂未公布&#xff0c;考试时间上半年为5月25日到28日&#xff0c;下半年考试时间为11月9日到12日。不想错过考试最新消息的…...

linux:du和df区别

文章目录 1. 概述2. du 命令2. df 命令3. 区别总结 1. 概述 du 和 df 都是 Linux 系统中用于查看磁盘空间使用情况的命令&#xff0c;但它们的功能和用法有所不同。 2. du 命令 du 是 “disk usage” 的缩写&#xff0c;用于显示文件或目录的磁盘使用情况。du 命令用于查看指…...

MacOS Docker 部署 Redis 数据库

一、简介 Redis是一个开源的、使用C语言编写的、基于内存亦可持久化的Key-Value数据库&#xff0c;它提供了多种语言的API&#xff0c;并支持网络交互。Redis的数据存储在内存中&#xff0c;因此其读写速度非常快&#xff0c;每秒可以处理超过10万次读写操作&#xff0c;是已知…...

个推助力小米汽车APP实现智能用户触达,打造智能出行新体验

4月3日&#xff0c;小米SU7首批交付仪式在北京亦庄的小米汽车工厂总装车间举行&#xff0c;全国28城交付中心也同步开启首批交付。随着小米SU7系列汽车的正式发售和交付&#xff0c;小米汽车APP迎来了用户体量的爆发式增长。 小米汽车APP是小米汽车官方推出的手机应用&#xff…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...