Spring2~~~

news2024/11/11 3:20:02

注解配置Bean

Spring的 IOC 容器检查到注解就会生成对象,但这个注解的具体含义不会识别 

  配置自动扫描的包

    <!--配置容器要扫描的包
    1. component-scan 要对指定包下的类进行扫描, 并创建对象到容器
    2. base-package 指定要扫描的包
    3. 含义是当spring容器创建/初始化时,就会扫描com.hspedu.spring.component包
       下的所有的 有注解 @Controller / @Service / @Respository / @Component类
       将其实例化,生成对象,放入到ioc容器
    -->
    <context:component-scan base-package="com.hspedu.spring.component"/>

Map里的默认id是类名开头小写
com.hspedu.spring.component会扫描comonent及其子包
如果要扫描spring下的包,写成com.hspedu.spring.* 

只扫描包下的哪些类

在xml中加上 resource-pattern="User*.class" 表示只扫描spring.component 和它的子包下的User打头的类,用的比较少

<context:component-scan base-package="com.hspedu.spring.component" 
resource-pattern="User*.class" />

排除包下某种类型的注解(注解方式)

    <!--
        需求:如果我们希望排除某个包/子包下的某种类型的注解,可以通过exclude-filter来指定
        1. context:exclude-filter 指定要排除哪些类
        2. type 指定排除方式 annotation表示按照注解来排除
        3. expression="org.springframework.stereotype.Service" 指定要排除的注解的全路径
    -->

    <context:component-scan base-package="com.hspedu.spring.component">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>

指定自动扫描哪些注解类(注解方式)

    <!--
        需求:如果我们希望按照自己的规则,来扫描包/子包下的某些注解, 可以通过 include-filter
        1. use-default-filters="false" 表示不使用默认的过滤机制/扫描机制
        2. context:include-filter 表示要去扫描哪些类
        3. type="annotation" 按照注解方式来扫描/过滤
        4. expression="org.springframework.stereotype.Service" 指定要扫描的注解的全路径
    -->

    <context:component-scan base-package="com.hspedu.spring.component" use-default-filters="false">
       <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
       <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
       <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>


使用 value 指定 id 值

        覆盖默认的id值
        注解默认 类名首字母小写 作为id值

@Service(value = "sss")
public class Student {
}

自动装配

@AutoWired

IOC容器中有多个对象,要进行查找
1、是否有唯一bean
2、根据id查找

根据id查找没找到,报错原因:按id找不到,按类型有多个,类型匹配不上

根据唯一性查找,属性名无所谓,直接按照类型找到
IOC容器中的对象和装配的对象哈希值不一定一样

    <!--自动扫描的id就是类名首字母小写或者指定value的id值-->
    <context:component-scan
            base-package="com.hspedu.spring.component"/>
    <!--配置两个UserService对象-->
    <bean class="com.hspedu.spring.component.UserService" id="userService200"/>
    <bean class="com.hspedu.spring.component.UserService" id="userService300"/>
@Controller
public class UserAction {
    @Autowired
    private UserService userService200;
    public void sayOk() {
        System.out.println("userAction 装配的 userService属性=" + userService);
        userService200.hi();
    }
}

@Qualifier与@AutoWired

必须搭配使用,相当于@Resource

@Resource

 按照name的值在容器中查找,属性名没有作用了

按照type类型查找,属性名没有作用了,要求在容器里只能有一个这样类型的对象 

  

如果没有指定name和type,则先试用byName注入策略,如果匹配不上,再使用byType策略

泛型依赖装配

        使用Autowired
        把PhoneDao对象装配到PhoneService,
通过泛型传入BaseDao,再把指定的泛型对象装配到PhoneService

动态代理 

不改变原有代码的情况下进行对象功能增强,使用代理对象拓展功能

public interface Vehicle {
    public void run();
    public String fly(int height);
}
public class Car implements Vehicle{
    @Override
    public void run() {
        //System.out.println("交通工具开始运行了....");
        System.out.println("小汽车在路上 running....");
        //System.out.println("交通工具停止运行了....");
    }

    @Override
    public String fly(int height) {
        System.out.println("小汽车可以飞翔 高度=" + height);
        return "小汽车可以飞翔 高度=" + height;
    }
}

 类似切面类

public class VehicleProxyProvider {
    
    //target_vehicle 表示真正要执行的对象
    //该对象的类实现了Vehicle接口
    private Vehicle target_vehicle;
    
    public VehicleProxyProvider(Vehicle target_vehicle) {
        this.target_vehicle = target_vehicle;
    }

    //编写一个方法,可以返回一个代理对象, 该代理对象可以通过反射机制调用到被代理对象的方法
    public Vehicle getProxy() {
        
        ClassLoader classLoader =
                target_vehicle.getClass().getClassLoader();

        //得到对象的接口信息
        Class<?>[] interfaces = target_vehicle.getClass().getInterfaces();


        //创建InvocationHandler 对象
        //因为 InvocationHandler 是接口,所以我们可以通过匿名对象的方式来创建该对象
        /**
         *
         * public interface InvocationHandler {
         *  public Object invoke(Object proxy, Method method, Object[] args)
         *         throws Throwable;
         * }
         * invoke 方法是将来执行我们的target_vehicle的方法时,会调用到
         *
         */

        InvocationHandler invocationHandler = new InvocationHandler() {
            /**
             * invoke 方法是将来执行我们的target_vehicle的方法时,会调用到
             * @param o 表示代理对象
             * @param method 就是通过代理对象调用方法时,的哪个方法 代理对象.run()
             * @param args : 表示调用 代理对象.run(xx) 传入的参数
             * @return 表示 代理对象.run(xx) 执行后的结果.
             * @throws Throwable
             */
            @Override
            public Object invoke(Object o, Method method, Object[] args)
                    throws Throwable {

                System.out.println("交通工具开始运行了....");
                //method 是?: public abstract void com.hspedu.spring.proxy2.Vehicle.run()
                //target_vehicle 是? Ship对象
                //args 是null
                //这里通过反射+动态绑定机制,就会执行到被代理对象的方法
                Object result = method.invoke(target_vehicle, args);
                System.out.println("交通工具停止运行了....");
                return result;
            }
        };

        /*
          public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
          1. Proxy.newProxyInstance() 可以返回一个代理对象
          2. ClassLoader loader: 类的加载器.
          3. Class<?>[] interfaces 就是将来要代理的对象的接口信息
          4. InvocationHandler h 调用处理器/对象 有一个非常重要的方法invoke
         */
        Vehicle proxy =
                (Vehicle)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);

        return proxy;
    }
}

Test类 

    @Test
    public void proxyRun() {
        //创建VehicleProxyProvider对象, 并且我们传入的要代理的对象
        VehicleProxyProvider vehicleProxyProvider =
                new VehicleProxyProvider(new Car());
        //获取代理对象, 该对象可以代理执行方法
        //proxy的编译类型是 Vehicle, 运行类型是 class com.sun.proxy.$Proxy9
        Vehicle proxy = vehicleProxyProvider.getProxy();
        //当执行run方法时,会执行到 代理对象的invoke
        proxy.run();
        String result = proxy.fly(10000);
        System.out.println("result=" + result);
    }

getProxy()的缺点

硬编码,功能不强,希望以方法的形式来执行一段业务

写成方法,耦合度高

    //在目标对象执行前执行
    public void before(Method method, Object[] args) {
        System.out.println("before-方法执行前-日志-方法名-" + method.getName() + "-参数 "
                + Arrays.asList(args)); //这里从AOP看,就是一个横切关注点-前置通知
    }

    //在目标对象执行后执行
    public void after(Method method, Object result) {
        System.out.println("after-方法执行正常结束-日志-方法名-" + method.getName() + "-结果result= "
                + result);//从AOP看, 也是一个横切关注点-返回通知
    }

进行解耦,写成AOP类,复用性差,不灵活,硬编码

public class HspAOP {
    public static void before(Method method, Object[] args) {}
    public static void after(Method method, Object result) {}
}

AOP

面向切面编程

快速入门

 

环绕通知可以将四个通知合并管理

public interface SmartAnimalable {
    //求和
    float getSum(float i, float j);
    //求差
    float getSub(float i, float j);
}
@Component //使用@Component 当spring容器启动时,将 SmartDog注入到容器
public class SmartDog implements SmartAnimalable {
    @Override
    public float getSum(float i, float j) {
        float result = i + j;
        System.out.println("方法内部打印result = " + result);
        return result;
    }

    @Override
    public float getSub(float i, float j) {
        float result = i - j;
        System.out.println("方法内部打印result = " + result);
        return result;
    }
}

切面类 

  • @Before(value = "") 表示前置通知        
    value = "execution(public float spring.aop.aspectj.SmartDog.getSum(float, float)       
    指定切入到哪个类的哪个方法  形式是: 访问修饰符 返回类型 全类名.方法名(形参列表)
  • showBeginLog方法可以理解成就是一个切入方法
  • JoinPoint joinPoint 在底层执行时,由AspectJ切面框架, 会给该切入方法传入 joinPoint对象,通过该方法,程序员可以获取到 相关信息
@Aspect //表示是一个切面类
@Component //会注入SmartAnimalAspect到容器
public class SmartAnimalAspect {
    @Before(value = "execution(public float spring.aspectj.SmartDog.getSum(float, float))")
    public void showBeginLog(JoinPoint joinPoint) {
        //通过连接点对象joinPoint 可以获取方法签名
        //invoke(Object proxy, Method method, Object[] args)整合到joinPoint
        Signature signature = joinPoint.getSignature();
        System.out.println(signature.getName() + "-参数 "
                + Arrays.asList(joinPoint.getArgs()));
    }
}

XML开启AOP功能

    <context:component-scan
            base-package="com.hspedu.spring.aop.aspectj"/>
    <!-- 开启基于注解的AOP功能 -->
    <aop:aspectj-autoproxy/>

如果不开启,.getClass()不会得到代理对象,只会得到当前运行的对象(相当于new)

Test类

    @Test
    public void smartDogTestByProxy() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans08.xml");
        //需要通过接口类型来获取到注入的SmartDog对象-就是代理对象
        SmartAnimalable smartAnimalable =
                ioc.getBean(SmartAnimalable.class);
        //SmartAnimalable smartAnimalable =
        //        (SmartAnimalable)ioc.getBean("smartDog");
        smartAnimalable.getSum(10, 2);
    }

以前是new一个对象,获得这个类的的代理对象

动态代理返回的对象是个代理对象,强转成接口的形式返回

Animal proxy =

        (Animal)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);

return proxy;
(xml中开启AOP)现在通过接口类型获取的对象就是这个类的代理对象

细节

按接口来获取,多个类实现了接口会报错
UsbInterface interface = ioc.getBean(UsbInterface.class);

interface是代理对象,获取Phone类的代理对象,getBean()就相当于之前的getPorxy()
UsbInterface interface = (UsbInterface)ioc.getBean(Phone.class);
UsbInterface interface = (UsbInterface)ioc.getBean("phone");

切入表达式

重用

    //定义一个切入点, 在后面使用时可以直接引用, 提高了复用性
    @Pointcut(value = "execution(public float spring.aspectj.SmartDog.getSum(float, float)))")
    public void myPointCut() {}

    @Before(value = "myPointCut()")
    public void showBeginLog(JoinPoint joinPoint) {}

    @AfterReturning(value = "myPointCut()", returning = "res")
    public void showSuccessEndLog(JoinPoint joinPoint, Object res) {}

    @AfterThrowing(value = "myPointCut()", throwing = "throwable")
    public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {}


 

两种动态代理

jdk的Proxy

面向接口,只能增强实现类中接口中存在的方法
得到的对象是JDK代理对象的实例

生成的代理对象只能转换成接口不能转换成被代理类

 

Spring的CGlib

面向父类,可以增强父类的所有方法
得到的对象是被代理对象的子类

JoinPoint常用方法

返回通知中获取结果

在@AfterReturning 增加属性 , 比如 returning = "res",同时在切入方法增加 Object res
注意: returning = "res" 和 Object res 的 res名字一致

 异常通知中获取异常

环绕通知 

@Aspect
@Component
public class SmartAnimalAspect {
    //演示环绕通知的使用-了解
    //1. @Around: 表示这是一个环绕通知[完成其它四个通知的功能]
    //2. value = "execution(public float com.hspedu.spring.aop.aspectj.SmartDog.getSum(float, float)) 切入点表达式
    //3. doAround 表示要切入的方法 - 调用结构 try-catch-finally
    @Around(value = "execution(public float com.hspedu.spring.aop.aspectj.SmartDog.getSum(float, float))")
    public Object doAround(ProceedingJoinPoint joinPoint) {
        Object result = null;
        String methodName = joinPoint.getSignature().getName();
        try {
            //1.相当于前置通知完成的事情
            Object[] args = joinPoint.getArgs();
            List<Object> argList = Arrays.asList(args);
            System.out.println("AOP环绕通知[-前置通知]" + methodName + "方法开始了--参数有:" + argList);
            //在环绕通知中一定要调用joinPoint.proceed()来执行目标方法
            result = joinPoint.proceed();
            //2.相当于返回通知完成的事情
            System.out.println("AOP环绕通知[-返回通知]" + methodName + "方法结束了--结果是:" + result);
        } catch (Throwable throwable) {
            //3.相当于异常通知完成的事情
            System.out.println("AOP环绕通知[-异常通知]" + methodName + "方法抛异常了--异常对象:" + throwable);
        } finally {
            //4.相当于最终通知完成的事情
            System.out.println("AOP环绕通知[-后置通知]" + methodName + "方法最终结束了...");
        }
        return result;
    }
}

切面优先级

如果同一个方法,有多个切面在同一个切入点切入,优先级如何控制

@order(value = n) 来控制,n 越小,优先级越高

前置通知通过@order来判断顺序

基于XML配置AOP 

public interface SmartAnimalable {
    float getSum(float i, float j);
    float getSub(float i, float j);
}
public class SmartDog implements SmartAnimalable {
    @Override
    public float getSum(float i, float j) {return result;}
    @Override
    public float getSub(float i, float j) {return result;}
}

切面类将注解全部去掉 

public class SmartAnimalAspect {
    public void showBeginLog(JoinPoint joinPoint) {}
    public void showSuccessEndLog(JoinPoint joinPoint, Object res) {}
    public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {}
    public void showFinallyEndLog(JoinPoint joinPoint) {}
}

测试类 

    @Test
    public void testAspectByXML() {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans09.xml");
        SmartAnimalable smartAnimalable =
                ioc.getBean(SmartAnimalable.class);
        smartAnimalable.getSum(10, 2);
    }
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--使用XML配置,完成AOP编程-->
    <!--配置一个切面类对象-bean-->
    <bean class="com.hspedu.spring.aop.xml.SmartAnimalAspect" id="smartAnimalAspect"/>
    <!--配置一个SmartDog对象-bean-->
    <bean class="com.hspedu.spring.aop.xml.SmartDog" id="smartDog"/>
    <!--配置切面类, 细节一定要引入 xmlns:aop-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="myPointCut" expression="execution(public float com.hspedu.spring.aop.xml.SmartDog.getSum(float, float)))"/>
        <!--配置切面的前置,返回, 异常, 最终通知-->
        <aop:aspect ref="smartAnimalAspect" order="10">
            <!--配置前置通知-->
            <aop:before method="showBeginLog" pointcut-ref="myPointCut"/>
            <!--返回通知-->
            <aop:after-returning method="showSuccessEndLog" pointcut-ref="myPointCut" returning="res"/>
            <!--异常通知-->
            <aop:after-throwing method="showExceptionLog" pointcut-ref="myPointCut" throwing="throwable"/>
            <!--最终通知-->
            <aop:after method="showFinallyEndLog" pointcut-ref="myPointCut"/>
            <!--配置环绕通知-->
            <!--<aop:around method=""/>-->
        </aop:aspect>
    </aop:config>
</beans>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2115786.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

类和对象(中)- C++

个人主页点这里~ 1. 类的默认成员函数 在C中&#xff0c;当你定义一个类时&#xff0c;即使没有显式地声明它们&#xff0c;编译器也会为该类生成一些默认成员函数。这些默认成员函数在特定情况下非常有用&#xff0c;尤其是当你进行对象拷贝、赋值、销毁或动态内存管理时。 …

BatchUpdateException 问题

我们在使用 statement 的 batch api 时、每 20 条数据作为一个事务提交、如果其中一条数据有问题 我们想知道哪一条数据有问题、那么我们可以通过捕获的 BatchUpdatedException 获取到 我们插入 100 条数据、第 21 条和第 41 条是非法数据、会插入失败的 看看日志打印 看看…

函数指针学习

认识函数指针&#xff1a; 函数指针的用处&#xff1a; 回调函数&#xff08;以函数指针为参数的参数&#xff09; 定义带标签的结构体 typedef struct mode { int data; } Node; 标签&#xff08;mode&#xff09;: mode 是结构体的标签名。在这种定义中&#xff0c;mo…

前端:Vue3学习-2

前端:Vue3学习-2 1. vue3 新特性-defineOptions2. vue3 新特性-defineModel3. vue3 Pinia-状态管理工具4. Pinia 持久化插件 -> pinia-plugin-persistedstate 1. vue3 新特性-defineOptions 如果要定义组件的name或其他自定义的属性&#xff0c;还是得回归原始得方法----再…

Codigger 携手 Jupyter:革新数据科学与编程体验

在现今的数字化时代&#xff0c;数据科学正在多个领域内如日中天地发展。数据分析和数据挖掘需求无处不在&#xff0c;对数据的理解与运用&#xff0c;成为许多企业及科研团队取得成功的重要因素。在这个大背景下&#xff0c;Jupyter 项目以其独特的设计理念和强大功能&#xf…

k8s API资源对象ingress

有了Service之后&#xff0c;我们可以访问这个Service的IP&#xff08;clusterIP&#xff09;来请求对应的Pod&#xff0c;但是这只能是在集群内部访问。 要想让外部用户访问此资源&#xff0c;可以使用NodePort&#xff0c;即在node节点上暴漏一个端口出来&#xff0c;但是这…

UNITY UI简易反向遮罩

附带示例资源文件&#xff1a;https://download.csdn.net/download/qq_55895529/89726994?spm1001.2014.3001.5503 大致效果&#xff1a; 实现思路:通过ui shader的模板测试功能实现 通过让想要被突出显示的物体优先渲染并写入模板值,而后再让黑色遮罩渲染并判断模板值进行渲…

机试算法模拟题 服务中心选址

题目描述 一个快递公司希望在一条街道建立新的服务中心。公司统计了该街道中所有区域在地图上的位置&#xff0c;并希望能够以此为依据为新的服务中心选址&#xff1a;使服务中心到所有区域的距离的总和最小。 给你一个数组positions&#xff0c;其中positions[i] [left, ri…

单项链表的原地反转

逻辑图如下所示&#xff1a; 只需要将需要反转的节点放到头节点位置即可&#xff0c; 使用两个指针一个指针指向需要反转的节点&#xff0c;另一个指针指向需要反转的指针的前驱节点&#xff08;其实也就是元链表的头节点&#xff09; 操作过程&#xff1a; 1 2 3 4 5 2 1 …

零基础国产GD32单片机编程入门(十五)CAN通讯详解及实战含源码

文章目录 一.概要二.CAN网络基本组成三.GD32单片机CAN结构与特点1.GD32F103单片机CAN基本结构图2.GD32F103单片机CAN基本特点 四.CAN协议帧格式五.GD32F103C8T6的CAN通讯波特率六.GDF103C8T6的CAN接收过滤器配置七.配置一个CAN通讯数据收发例程八.工程源代码下载九.小结 一.概要…

机器之心 | 挑战Transformer的Mamba是什么来头?作者博士论文理清SSM进化路径

本文来源公众号“机器之心”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;挑战Transformer的Mamba是什么来头&#xff1f;作者博士论文理清SSM进化路径 对 SSM 感兴趣的研究者不妨读一下这篇博士论文。 在大模型领域&#xff0c;…

仕考网:2025年公务员国考备考技巧

公务员考试掌握好备考技巧非常重要&#xff0c;尤其是国考这种竞争比较激烈的考试&#xff0c;仕考网为大家分享一些备考技巧&#xff0c;希望能对大家有所帮助。 1. 在提升行测分数时&#xff0c;可以采用大量的练习题、整理题以及关注往年核心考点的方式。无论处于准备过程的…

JsonPath全英文文档学习

JsonPath全英文文档学习 1、文档地址2、引入依赖3、浏览翻译问题修复4、文档学习4.1、Operator4.2、Functions4.3、Filter 运算符4.4、json示例 5、实战5.1、获取json数组下的多个元素5.2、获取json数组下的多个元素&#xff08;循环遍历时无元素自动占位&#xff09;5.3、获取…

面了阿里大模型算法岗,出门秒挂。。。

最近这一两周看到不少互联网公司都已经开始秋招提前批面试了。 不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c;帮助一些…

基于springboot+enum配置化实践

前言 Springboot/Springcloud作为微服务开发的经典框架&#xff0c;我想任何一个developer不会排斥。同时&#xff0c;市场越来越多的业务开发均围绕Springboot/Springcloud而展开&#xff0c;也让它成为Java开发的“硬通货”。 基于Spring&#xff0c;诸多低代码的平台的活跃…

基于SpringBoot的校园跑腿系统+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

spring项目整合log4j2日志框架(含log4j无法打印出日志的情况,含解决办法)

Spring整合Log4j2的整体流程 1&#xff09;导入log4j-core依赖 <!--导入日志框架--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.20.0</version></dependenc…

Linux中的gdb调试器

目录 一、程序的两种模式 二、gdb的常用调试命令 一、程序的两种模式 程序通常有两种模式&#xff0c;分别是debug模式和release模式 debug模式可以调试&#xff0c;但是release模式不支持调试&#xff0c;因为debug模式添加了调试信息&#xff0c;因此debug的程序大小比rel…

[苍穹外卖]-05Redis快速入门

Redis入门 Redis是一个基于内存的key-value结构数据库 基于内存存储, 读写性能高适合存储热点数据(热点商品,咨询,新闻)企业应用广泛中文官网: Redis中文网英文网: https://rsdis.io 下载安装: Redis安装包分为Windows版本和Linux版本, Redis的windows版属于绿色软件, 解压后…

sqlmap简介及安装

sqlmap简介及安装 sqlmap 介绍 sqlmap 是一个开源的渗透测试工具&#xff0c;可以用来进行自动化检测&#xff0c;利用SQL注入漏洞&#xff0c;获取数据库服务器的权限。它具有功能强大的检测引擎&#xff0c;针对各种不同类型数据库的渗透测试的功能选项&#xff0c;包括获取…