Spring框架学习笔记(三):AOP编程

1 动态代理

1.1 通过案例理解动态代理

(1)需求说明:
1. 有 Vehicle接口(交通工具接口, 有一个 run 方法), 下面有两个实现类 Car 和 Ship
2. 当运行 Car 对象 的 run 方法和 Ship 对象的 run 方法时,输入如下内容, 注意观察前后
有统一的输出

(2)准备代码: Vehicle.java,Car.java,Ship.java

public interface Vehicle {public void run();public String fly(int height);
}
public class Car implements Vehicle{@Overridepublic void run(){System.out.println("小汽车在水上running...");}@Overridepublic String fly(int height) {return "小汽车飞到了" + height + "米";}
}
public class Ship implements Vehicle{@Overridepublic void run() {System.out.println("大轮船在水上running...");}@Overridepublic String fly(int height) {return "大轮船飞到了" + height + "米";}
}

(3)动态代理实现:创建代理类VehicleProxyProvider.java(该类中有详细注释,演示了动态代理的实现过程)

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 该类返回一个代理对象*/
public class VehicleProxyProvider {//该属性表示真正要执行的对象(实现了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 h = new InvocationHandler(){/*** invoke方法在将来调用target_vehicle的方法时,会使用到* @param proxy 表示代理对象* @param method 就是想要通过代理对象调用的那个方法* @param args 表示要调用的方法需要传入的参数* @return 表示target_vehicle的方法执行后的结果* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//这里可以写调用方法前要进行的操作System.out.println("交通工具开始运行了...");//通过反射调用该方法Object result = method.invoke(target_vehicle, args);//这里可以写调用方法后要进行的操作System.out.println("交通工具停止运行了...");return result;}};//java.lang.reflect中的Proxy类有动态代理的相关方法,静态方法newProxyInstance()可以创建一个代理对象/*ClassLoader loader:类的加载器Class<?>[] interfaces:要代理对象的接口的信息InvocationHandler h:调用处理器/对象,InvocationHandler是一个接口,里面有一个方法public Object invoke(Object proxy, Method method, Object[] args)public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)*/Vehicle proxy = (Vehicle)Proxy.newProxyInstance(classLoader, interfaces, h);return proxy;}
}

(4)测试代码:

@Test
public void proxyRun(){//创建代理类对象,传入要代理的对象VehicleProxyProvider vehicleProxyProvider = new VehicleProxyProvider(new Ship());//获取到代理对象,该对象可以代理执行方法//1.proxy编译类型是Vehicle//2.运行类型是代理类型class com.sun.proxy.$Proxy8Vehicle proxy = vehicleProxyProvider.getProxy();System.out.println(proxy.getClass());//所以这里调用的不是ship中的run方法,而是代理对象的invokeproxy.run();String fly = proxy.fly(100);System.out.println(fly);
}

(5)运行结果:

1.2 通过案例理解横切关注点

(1)需求说明:

有一个 SmartAnimal 接口,可以完成简单的加减法, 要求在执行 getSum()getSub()时,输出执行前,执行过程,执行后的日志输出

(2)准备代码:SmartAnimalable.java,SmartDog.java

public interface SmartAnimalable {//求和float getSum(float i, float j);//求差float getSub(float i, float j);
}
public class SmartDog implements SmartAnimalable {@Overridepublic float getSum(float i, float j) {float result = i + j;System.out.println("方法内部打印result = " + result);return result;}@Overridepublic float getSub(float i, float j) {float result = i - j;System.out.println("方法内部打印result = " + result);return result;}
}

(3)动态代理实现:创建MyProxyProvider.java,加入横切关注点(该类中有详细注释,介绍了几个横切关注点包括 前置通知、返回通知、异常通知、最终通知)

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;public class MyProxyProvider {//定义我们要执行的目标对象, 该对象需要实现SmartAnimalableprivate SmartAnimalable target_obj;//构造器public MyProxyProvider(SmartAnimalable target_obj) {this.target_obj = target_obj;}//方法, 可以返回代理对象,该代理对象可以执行目标对象public SmartAnimalable getProxy() {//1. 先到的类加载器/对象ClassLoader classLoader = target_obj.getClass().getClassLoader();//2. 得到要执行的目标对象的接口信息Class<?>[] interfaces = target_obj.getClass().getInterfaces();//3. 创建InvocationHandlerInvocationHandler invocationHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = null;try {System.out.println("方法执行前-日志-方法名-" + method.getName() + "-参数 "+ Arrays.asList(args)); //这里从AOP看,就是一个横切关注点-前置通知//使用反射调用方法result = method.invoke(target_obj, args);System.out.println("方法执行正常结束-日志-方法名-" + method.getName() + "-结果result= "+ result);//从AOP看, 也是一个横切关注点-返回通知} catch (Exception e) {e.printStackTrace();//如果反射执行方法时,出现异常,就会进入到catch{}System.out.println("方法执行异常-日志-方法名-" + method.getName()+ "-异常类型=" + e.getClass().getName());//从AOP看, 也是一个横切关注点-异常通知} finally {//不管你是否出现异常,最终都会执行到finally{}//从AOP的角度看, 也是一个横切关注点-最终通知System.out.println("方法最终结束-日志-方法名-" + method.getName());}return result;}};//创建代理对象SmartAnimalable proxy =(SmartAnimalable)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);return proxy;}
}

(4)测试代码:

@Test
public void smartDogTestByProxy() {SmartAnimalable smartAnimalable = new SmartDog();MyProxyProvider myProxyProvider =new MyProxyProvider(smartAnimalable);//我们返回了代理对象SmartAnimalable proxy =myProxyProvider.getProxy();proxy.getSum(10, 2);System.out.println("====================");proxy.getSub(10, 2);}

(5)运行结果:

2 AOP 的基本介绍

概念:AOP 的全称(aspect oriented programming) ,面向切面编程

AOP 相关概念示意图

 AOP 实现方式

(1)基于动态代理的方式 [ 内置 aop 实现 ],即前面动态代理案例所使用的方式
(2)使用框架 aspectj 来实现

3 AOP 编程快速入门

3.1 基本说明

(1)需要引入核心的 aspect 包(如果是maven项目,第一篇文章导入的依赖包含了该依赖项,这步可以省略)

(2)在切面类中声明通知方法

  • 前置通知:@Before
  • 返回通知:@AfterReturning
  • 异常通知:@AfterThrowing
  • 后置通知:@After
  • 环绕通知:@Around
五种通知和前面写的动态代理类方法的对应关系

3.2 快速入门案例

使用 aop 编程的方式,来实现手写的动态代理案例效果,就以上一个案例为例

(1)准备代码  SmartAnimalable.java,SmartDog.java
public interface SmartAnimalable {//求和float getSum(float i, float j);//求差float getSub(float i, float j);
}
@Component
public class SmartDog implements SmartAnimalable {@Overridepublic float getSum(float i, float j) {//System.out.println("日志-方法名-getSum-参数 " + i + " " + j);float result = i + j;System.out.println("方法内部打印result = " + result);//System.out.println("日志-方法名-getSum-结果result= " + result);return result;}@Overridepublic float getSub(float i, float j) {//System.out.println("日志-方法名-getSub-参数 " + i + " " + j);float result = i - j;System.out.println("方法内部打印result = " + result);//System.out.println("日志-方法名-getSub-结果result= " + result);return result;}
}

(2)SmartAnimalAspect.java(该类有详细注释,介绍了AOP编程的详细步骤)

/*** 切面类 , 类似于我们以前自己写的MyProxyProvider,但是功能强大很多*/
@Aspect //表示是一个切面类[底层切面编程的支撑(动态代理+反射+动态绑定...)]
@Component //会注入SmartAnimalAspect到容器
public class SmartAnimalAspect {//希望将showBeginLog方法切入到SmartDog-getSum前执行-前置通知/*** 1. @Before 表示前置通知:即在我们的目标对象执行方法前执行* 2. value = "execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float)* 指定切入到哪个类的哪个方法  形式是:访问修饰符 返回类型 全类名.方法名(形参列表)* 3. showBeginLog方法可以理解成就是一个切入方法, 这个方法名是可以程序员指定  比如:showBeginLog* 4. JoinPoint joinPoint 在底层执行时,由AspectJ切面框架, 会给该切入方法传入 joinPoint对象* , 通过该方法,程序员可以获取到 相关信息* @param joinPoint*/@Before(value = "execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float))")public void showBeginLog(JoinPoint joinPoint) {//通过连接点对象joinPoint 可以获取方法签名Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect3-切面类showBeginLog()-方法执行前-日志-方法名-" + signature.getName() + "-参数 "+ Arrays.asList(joinPoint.getArgs()));}//返回通知:即把showSuccessEndLog方法切入到目标对象方法正常执行完毕后的地方//1. 如果我们希望把目标方法执行的结果,返回给切入方法//2. 可以再 @AfterReturning 增加属性 , 比如 returning = "res",表示返回值//3. 同时在切入方法增加 Object res//4. 注意: returning = "res" 和 Object res 的 res名字一致@AfterReturning(value = "execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float))", returning = "res")public void showSuccessEndLog(JoinPoint joinPoint, Object res) {Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect3-切面类showSuccessEndLog()-方法执行正常结束-日志-方法名-" + signature.getName() + " 返回的结果是=" + res);}//异常通知:即把showExceptionLog方法切入到目标对象方法执行发生异常的的catch{}@AfterThrowing(value = "execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float))", throwing = "throwable")public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect3-切面类showExceptionLog()-方法执行异常-日志-方法名-" + signature.getName() + " 异常信息=" + throwable);}//最终通知:即把showFinallyEndLog方法切入到目标方法执行后(不管是否发生异常,都要执行 finally{})@After(value = "execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float))")public void showFinallyEndLog(JoinPoint joinPoint) {Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect3-切面类showFinallyEndLog()-方法最终执行完毕-日志-方法名-" + signature.getName());}
}

(3)创建 beans07.xml 并配置

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

(4)测试代码

@Test
public void smartDogTestByProxy(){ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans07.xml");SmartAnimalable bean = ioc.getBean(SmartAnimalable.class);System.out.println(bean.getClass());bean.getSum(1,2);
}

(5)运行结果

 3.3 细节说明

(1)切入表达式的更多配置,比如使用模糊配置,以下表示SmartDog类中的所有方法,都会被执行该前置通知方法

@Before(value="execution(* com.aop.proxy.SmartDog.*(..))")

(2)以下表示所有访问权限,所有包的下所有有类的所方法,都会被执行该前置通知方法

@Before(value="execution(* *.*(..))")

(3)当 spring 容器开启了 <!-- 开启基于注解的 AOP 功能 --> <aop:aspectj-autoproxy/> , 我们获 取注入的对象, 需要以接口的类型来获取, 因为你注入的对象.getClass() 已经是代理类型了

注意:如果不加该配置,AOP编程不会生效

(4)当 spring 容器开启了 <!-- 开启基于注解的 AOP 功能 --> <aop:aspectj-autoproxy/> , 我们获 取注入的对象, 也可以通过 id 来获取, 但是也要转成接口类型

AOP-切入表达式

4.1 具体使用

4.1.1 作用

通过表达式的方式定位一个或多个具体的连接点。

4.1.2 语法细节

(1)语法

value = "execution([权限修饰符] [返回值类型] [简单类名/全类名].[方法名]([参数列表]))"

(2)举例说明

表达式:

value = "execution(* com.spring.ArithmeticCalculator.*(..))"

含义:

  • ArithmeticCalculator接口中声明的所有方法。
  • 第一个“*”代表任意修饰符及任意返回值。
  • 第二个“*”代表任意方法。
  • “..”匹配任意数量、任意类型的参数。
  • 若目标类、接口与该切面类在同一个包中可以省略包名。

表达式:

value = "execution(public * ArithmeticCalculator.*(..))"

含义:ArithmeticCalculator接口的所有公有方法

表达式:

value = "execution(public double ArithmeticCalculator.*(..))"

含义:ArithmeticCalculator 接口中返回 double 类型数值的公有方法

表达式:

value = "execution(public double ArithmeticCalculator.*(double,..)"

含义:ArithmeticCalculator 接口中返回 double 类型数值,第一个参数为 double 类型的公有方法。“..” 匹配任意数量、任意类型的参数。

表达式:

value = "execution(public double ArithmeticCalculator.*(double, double))"

含义:ArithmeticCalculator 接口中返回 double 类型数值,参数类型为 double,double类型的公有方法

4.1.3 “&&”、“Ⅱ”、“!”的使用

在AspectJ中,切入点表达式可以通过“&&”、“Ⅱ”、“!”等操作符结合起来。

表达式:

value = "execution(* *.add(int,.)) || execution(* *.sub(int,…))"

含义:

任意类中第一个参数为int类型的add方法或sub方法

4.1.4 注意事项和细节

(1)切入表达式也可以指向类的方法, 这时切入表达式会对该类/对象生效

(2)切入表达式也可以指向接口的方法, 这时切入表达式会对实现了接口的类/对象生效

(3)切入表达式也可以对没有实现接口的类,进行切入

AOP-JoinPoint

通过 JoinPoint 可以获取到调用方法的签名

JoinPoint对象常用方法:

joinPoint.getSignature().getName():获取目标方法名
joinPoint.getSignature().getDeclaringType().getSimpleName():获取目标方法所属类的简单类名
joinPoint.getSignature().getDeclaringTypeName():获取目标方法所属类的类名
joinPoint.getSignature().getModifiers():获取目标方法声明类型(public、private、protected)
Object[] args = joinPoint.getArgs():获取传入目标方法的参数,返回一个数组
joinPoint.getTarget():获取被代理的对象
joinPoint.getThis():获取代理对象自己

AOP-返回通知获取结果

在返回通知方法获取返回结果

/*** returning = "res", Object res 名称保持一致* @param joinPoint* @param res 调用 getSum() 返回的结果*/
@AfterReturning(value = "execution(public float com.spring.aop.joinpoint.SmartDog.getSum(float, float))", returning = "res")
public void showSuccessEndLog(JoinPoint joinPoint, Object res) {System.out.println("返回通知" + "--结果是--" + res );
}

AOP-异常通知中获取异常

如何在异常通知方法中获取异常信息。

@AfterThrowing(value = "execution(public float com.spring.aop.joinpoint.SmartDog.getSum(float, float))", throwing = "throwable")
public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {System.out.println("异常通知 -- 异常信息--" + throwable);
}

AOP-环绕通知

环绕通知可以完成其它四个通知要做的事情

注意:在环绕通知中一定要调用 joinPoint.proceed()来执行目标方法

@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;
}

AOP-切入点表达式重用

为了统一管理切入点表达式,可以使用切入点表达式重用技术。

/** 这样定义的一个切入点表达式,就可以在其它地方直接使用*/
@Pointcut(value = "execution(public float com.spring.aop.joinpoint.SmartDog.getSum(float, float))")
public void myPointCut() {
}@Before(value = "myPointCut()")
public void showBeginLog(JoinPoint joinPoint) { //前置方法//得到方法的签名Signature signature = joinPoint.getSignature();//得到方法名. String method_name = signature.getName();//得到参数Object[] args = joinPoint.getArgs();System.out.println("前置通知" + "--调用的方法是 " + method_name + "--参数是--" + Arrays.asList(args));
}@After(value = "myPointCut()")
public void showFinallyEndLog() {System.out.println("最终通知 -- AOP-切入点表达式重用");
}/*** returning = "res", Object res 名称保持一致* @param joinPoint* @param res 调用 getSum() 返回的结果*/
@AfterReturning(value = "myPointCut()", returning = "res")
public void showSuccessEndLog(JoinPoint joinPoint, Object res) {System.out.println("返回通知" + "--结果是--" + res);
}
@AfterThrowing(value = "myPointCut()", throwing = "throwable")
public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {System.out.println("异常通知 -- 异常信息--" + throwable);
}

10 AOP-切面优先级问题

如果同一个方法,有多个切面在同一个切入点切入,那么执行的优先级如何控制.

基本语法:@order(value=n) 来控制 n 值越小,优先级越高(默认值很大,优先级很低)

@Aspect //表示这个类是一个切面类
@Order(value = 2)
@Component //需要加入 IOC 容器
public class SmartAnimalAspect2 {}

细节说明:

  • 不能理解成:优先级高的每个消息通知都先执行,这个和方法调用机制(Filter 过滤器链式调用类似)

11 AOP-基于 XML 配置 AOP

前面我们是通过注解来配置 aop 的,在 spring 中,我们也可以通过 xml 的方式来配置 AOP

案例:

在xml配置 SmartAnimalAspect.java 类为 SmartDog.java 的切入类

(1)准备代码martAnimalAspect.java、SmartDog.java,把注解全部去掉

public class SmartAnimalAspect {public void showBeginLog(JoinPoint joinPoint) {//通过连接点对象joinPoint 可以获取方法签名Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect3-切面类showBeginLog()-方法执行前-日志-方法名-" + signature.getName() + "-参数 "+ Arrays.asList(joinPoint.getArgs()));}public void showSuccessEndLog(JoinPoint joinPoint, Object res) {Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect3-切面类showSuccessEndLog()-方法执行正常结束-日志-方法名-" + signature.getName() + " 返回的结果是=" + res);}public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect3-切面类showExceptionLog()-方法执行异常-日志-方法名-" + signature.getName() + " 异常信息=" + throwable);}public void showFinallyEndLog(JoinPoint joinPoint) {Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect3-切面类showFinallyEndLog()-方法最终执行完毕-日志-方法名-" + signature.getName());}
}
public class SmartDog implements SmartAnimalable {@Overridepublic float getSum(float i, float j) {//System.out.println("日志-方法名-getSum-参数 " + i + " " + j);float result = i + j;System.out.println("方法内部打印result = " + result);//System.out.println("日志-方法名-getSum-结果result= " + result);return result;}@Overridepublic float getSub(float i, float j) {//System.out.println("日志-方法名-getSub-参数 " + i + " " + j);float result = i - j;System.out.println("方法内部打印result = " + result);//System.out.println("日志-方法名-getSub-结果result= " + result);return result;}
}

(2)配置xml文件

<!-- 配置 SmartAnimalAspect bean -->
<bean id="smartAnimalAspect" class="com.spring.aop.xml.SmartAnimalAspect"/>
<!--配置 SmartDog-->
<bean class="com.spring.aop.xml.SmartDog" id="smartDog"/>
<aop:config><!-- 配置统一切入点 --><aop:pointcut expression="execution(public float com.spring.aop.xml.SmartDog.getSum(float, float))"id="myPointCut"/><aop:aspect ref="smartAnimalAspect" order="1"><!-- 配置各个通知对应的切入点 --><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>

(3)测试代码

@Test
public void test1(){ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("beans08.xml");SmartAnimalable smartDog = ioc.getBean(SmartAnimalable.class);smartDog.getSum(1,1);
}

(4)运行结果

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

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

相关文章

HTML静态网页成品作业(HTML+CSS+JS)——在线购物商城网页设计制作(4个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;使用Javacsript代码实现图片轮播切换&#xff0c;共有4个页面。 二、…

手机图片恢复不求人:手动找回丢失的照片!

无论是外出旅行、聚会还是日常点滴&#xff0c;我们总是习惯用手机记录下来&#xff0c;让美好的瞬间定格在一张张照片中。然而&#xff0c;有时因为误删、清空缓存或是更换手机&#xff0c;那些珍贵的照片突然消失了。手机图片恢复有什么简单易行、容易上手的方法吗&#xff1…

容器组件:角标组件,纵向拖动组件(HarmonyOS学习第四课【4.2】)

Badge&#xff08;角标组件&#xff09; 可以附加在单个组件上用于信息标记的容器组件。 说明 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 支持单个子组件。 说明 子组件类型&#xff1a;系统组件…

Online RL + IL : Active Policy Improvement from Multiple Black-box Oracles

ICML 2023 paper code 紧接上一篇MAMBA&#xff0c;本文在同种问题设定下的在线模仿学习方法。 Intro 文章提出了一种新的模仿学习算法&#xff0c;名为 MAPS&#xff08;Max-aggregation Active Policy Selection&#xff09;和其变体 MAPS-SE&#xff08;Max-aggregation A…

SSL证书对于网络安全的重要作用

SSL证书是一种数字证书&#xff0c;它通过加密技术确保了客户端&#xff08;如浏览器&#xff09;与服务器之间的数据传输安全。当一个网站安装了SSL证书后&#xff0c;用户在浏览器地址栏中可以观察到HTTPS&#xff08;超文本传输安全协议&#xff09;前缀和挂锁图标&#xff…

点量云流分享:关于实时渲染云推流技术

提到云串流或者云推流很多人可能和游戏关联起来&#xff0c;其实这个技术的应用领域不仅仅是游戏&#xff0c;还有云上旅游、考古、智慧园区、智慧城市、虚拟仿真等等行业。其解决的问题是将一些大型的3D应用程序放在云端&#xff0c;程序在运行的时候也是在云端&#xff0c;这…

可视化大屏C位图:生产线,状态一目了然。

在可视化大屏中&#xff0c;将生产线作为C位图&#xff08;核心位图&#xff09;具有以下价值&#xff1a; 实时监控 生产线作为C位图可以实时展示生产线上的各个环节和工艺的运行状态。通过C位图&#xff0c;操作员可以直观地了解生产线的整体运行情况&#xff0c;及时发现异…

数仓建模理论 之 维度建模

说起维度建模&#xff0c;你不得不知道以下几个概念&#xff1a;事实表、维度表、星型模型、雪花模型、星座模型 维度建模 Ralph Kimball推崇数据集市的集合为数据仓库&#xff0c;同时也提出了对数据集市的维度建模&#xff0c;将数据仓库中的表划分为事实表、维度表两种类型…

uniapp微信小程序使用vscode代替HBuilderX开发uniapp微信小程序并且vscode改动代码微信开发者工具能实时更新

前言 最近公司开发新的小程序项目&#xff0c;经调研综合所有人员考虑&#xff0c;用uni-app Vue3tsvite技术栈开发&#xff1b;而官方推荐使用HBuilderX开发&#xff0c;而考虑到目前公司所有前端人员对VsCode更熟悉&#xff0c;故此总结了一下uniapp项目使用vscode代替HBuild…

网站开发初学者指南:2024年最新解读

在信息交流迅速的时代&#xff0c;网页承载着大量的信息&#xff0c;无论你知道还是不知道&#xff0c;所以你知道什么是网站开发吗&#xff1f;学习网站开发需要什么基本技能&#xff1f;本文将从网站开发阶段、网站开发技能、网站开发类型等角度进行分析&#xff0c;帮助您更…

Java 自动生成数据库设计文档

背景&#xff1a;有时候急需要数据库设计文档&#xff0c;手写太麻烦&#xff0c;这里介绍一款开源组件&#xff0c;可以自动根据数据库连接生成数据库设计文档 废话不多说&#xff0c;直接上代码 导入maven包 <dependency><groupId>org.freemarker</groupId>…

数据分析案例-印度美食数据可视化分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

“安”网守护,“乐享”服务——革新教育行业运维与安全体验,锐捷发布两大创新方案

5月11日,锐捷网络举办以“’安‘网联动, ’乐享‘运维”为主题的线上发布会,正式发布了锐捷乐享教育订阅服务方案,以及以新一代智能安全网关为核心的安全防护解决方案。 锐捷网络教育系统部总经理马雪峰为发布会致开场辞,他指出,在数字化浪潮席卷全球的今天,教育行业正进来前所…

未来已来:Spring Cloud引领微服务新纪元

文章目录 1. 引言1.1 微服务架构的兴起与挑战1.2 引入Spring Cloud作为微服务解决方案的重要性 2. 背景介绍2.1 微服务架构概述2.2 Spring Cloud的定位2.3 Spring Cloud特性概览 3. Spring Cloud核心组件3.1 Eureka - 服务发现3.2 Hystrix - 断路器3.3 Ribbon - 客户端负载均衡…

Vue框架—快速入门

目录 &#x1f516; 认识VUE &#x1f516; 第一个Vue程序 &#x1f516; Vue指令 &#x1f3f7;️v-text &#x1f3f7;️v-html &#x1f3f7;️v-model &#x1f3f7;️v-bind &#x1f3f7;️v-on &#x1f3f7;️v-if / v-show &#x1f516; 认识VUE ▐ 在学习…

Spring Security实现用户认证一:简单示例

Spring Security实现用户认证一&#xff1a;简单示例 1 原理1.1 用户认证怎么进行和保存的&#xff1f;认证流程SecurityContext保存 2 创建简单的登录认证示例2.1 pom.xml依赖添加2.2 application.yaml配置2.3 创建WebSecurityConfig配置类2.4 测试 1 原理 Spring Security是…

【AI绘画】Stable diffusion初级教程08——提示词(prompt)该如何写

今天是一篇干货&#xff0c;干的喝水的那种…… 写之前呢&#xff0c;先给大家打个比方&#xff1a;现在刚入门学习SD的相当于刚上学的小学生&#xff0c;提示词就相当于作文&#xff0c;还是英语作文&#xff0c;如果你总是抄抄抄&#xff0c;不知道作文的要点&#xff0c;语法…

全球知名哲学家思想家颜廷利:将人生黑暗视为一种机遇

在时间的长河中&#xff0c;我们短暂的人生不过是眨眼间的光景。然而&#xff0c;正是这短暂的旅程给予了我们无限的可能性和转变的契机。我们应该勇敢地面对生活中的暗夜&#xff0c;将其视作成长的土壤&#xff0c;让自我在其中焕发出独特的光辉。 当我们在生命的历程中暂停脚…

React 状态管理库深度对比:在做技术选型的时候如何选择合适的状态库,nolan出品

掘金链接&#xff1a;https://juejin.cn/post/7368288987642232872 1,简介 在状态共享这方面&#xff0c;不像 Vuex&#xff0c;React 的官方并没有强力推荐某种封装方案&#xff0c;所以 React 的状态管理工具五花八门&#xff0c;百花齐放&#xff0c; react-redux、dva、C…

【Python】语句与众所周知【自我维护版】

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 本篇博客是在之前的基础上进行的维护 目录 条…