6、spring的五种类型通知

2023-05-16

spring共提供了五种类型的通知:

通知类型接口描述
Around 环绕通知org.aopalliance.intercept.MethodInterceptor拦截对目标方法调用
Before 前置通知org.springframework.aop.MethodBeforeAdvice 在目标方法调用前调用
After  后置通知org.springframework.aop.AfterReturningAdvice在目标方法调用后调用
Throws 异常通知org.springframework.aop.ThrowsAdvice当目标方法抛出异常时调用
还有一类是引入通知,用来定义切入点的。

上一篇里面已经介绍了前置通知,就是在方法被调用前先执行前置通知

现在介绍一下其他的通知:

1、后置通知:

后置通知类的写法:

package com.cdtax.aop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class MyAfterReturningAdvice implements AfterReturningAdvice
{

	@Override
	public void afterReturning(Object returnValue, Method method,
			Object[] args, Object target) throws Throwable
	{
		System.out.println("后置通知被:关闭资源,");
	}

}
在beans.xml中的配置:

<?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:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
				http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<!-- 配置被代理的对象 -->
<bean id="test1Service" class="com.cdtax.aop.Test1Service">
	<property name="name" value="小明"></property>
</bean>

<!-- 配置前置通知 -->
<bean id="myMethodBeforeAdvice" class="com.cdtax.aop.MyMethodBeforeAdvice"></bean>

<!-- 配置后置通知 -->
<bean id="myAfterReturningAdvice" class="com.cdtax.aop.MyAfterReturningAdvice"></bean>

<!-- 配置代理对象 -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"> 
<!-- 代理接口集 -->
	<property name="proxyInterfaces">
		<list>
			<value>com.cdtax.aop.TestServiceInter</value>
			<value>com.cdtax.aop.TestServiceInter2</value>
		</list>
	</property>
	
	<!-- 把通知织入到代理对象  | 拦截器名集-->
	<property name="interceptorNames">
		<list>
		<!-- 相当于把 MyMethodBeforeAdvice前置通知和代理对象关联起来,我们也可以把通知看成拦截器,struts2核心就是拦截器 -->
		 <value>myMethodBeforeAdvice</value> 
				
		<!-- 织入后置通知 -->
		<value>myAfterReturningAdvice</value>
				
		</list>
	</property>
	
	<!-- 配置被代理对象,可以指定 -->
	<property name="target" ref="test1Service">
		
	</property>
</bean>
</beans>

测试类:

package com.cdtax.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App1
{
	public static void main(String[] args)
	{
		ApplicationContext ac = new ClassPathXmlApplicationContext("com/cdtax/aop/beans.xml");
		
//		Test1Service ts = (Test1Service) ac.getBean("test1Service");
//		ts.sayHello();
		
		TestServiceInter ts1 =  (TestServiceInter) ac.getBean("proxyFactoryBean");
		ts1.sayHello();
		((TestServiceInter2)ts1).sayBye();
	}
}

执行结果:

-----------------------------
前置通知  :记录日志...sayHello
hai 小明
后置通知被调用:关闭资源,
-----------------------------
前置通知  :记录日志...sayBye
bye 小明
后置通知被调用:关闭资源,

2、环绕通知

package com.cdtax.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyMethodInterceptor implements MethodInterceptor
{

	@Override
	public Object invoke(MethodInvocation arg0) throws Throwable
	{
		System.out.println("环绕通知被调用:调用方法前执行  ");
		Object obj = arg0.proceed();
		System.out.println("环绕通知被调用:调用方法后执行   ");
		return obj;
	}
}

配置beans.xml

<?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:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
				http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<!-- 配置被代理的对象 -->
<bean id="test1Service" class="com.cdtax.aop.Test1Service">
	<property name="name" value="小明"></property>
</bean>

<!-- 配置前置通知 -->
<bean id="myMethodBeforeAdvice" class="com.cdtax.aop.MyMethodBeforeAdvice"></bean>

<!-- 配置后置通知 -->
<bean id="myAfterReturningAdvice" class="com.cdtax.aop.MyAfterReturningAdvice"></bean>

<!-- 配置环绕通知 -->
<bean id="myMethodInterceptor" class="com.cdtax.aop.MyMethodInterceptor"></bean>


<!-- 配置代理对象 -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"> 
<!-- 代理接口集 -->
	<property name="proxyInterfaces">
		<list>
			<value>com.cdtax.aop.TestServiceInter</value>
			<value>com.cdtax.aop.TestServiceInter2</value>
		</list>
	</property>
	
	<!-- 把通知织入到代理对象  | 拦截器名集-->
	<property name="interceptorNames">
		<list>
		<!-- 相当于把 MyMethodBeforeAdvice前置通知和代理对象关联起来,我们也可以把通知看成拦截器,struts2核心就是拦截器 -->
		 <value>myMethodBeforeAdvice</value> 
				
		<!-- 织入后置通知 -->
		<value>myAfterReturningAdvice</value>
		
		<!-- 织入环绕通知 -->
		<value>myMethodInterceptor</value>
				
		</list>
	</property>
	
	<!-- 配置被代理对象,可以指定 -->
	<property name="target" ref="test1Service">
		
	</property>
</bean>
</beans>

执行App1测试类,执行结果:

-----------------------------
前置通知  :记录日志...sayHello
环绕通知被调用:调用方法前执行  
hai 小明
环绕通知被调用:调用方法后执行   
后置通知被调用:关闭资源,
-----------------------------
前置通知  :记录日志...sayBye
环绕通知被调用:调用方法前执行  
bye 小明
环绕通知被调用:调用方法后执行   
后置通知被调用:关闭资源,

3、异常通知:

修改Test1Service类,

package com.cdtax.aop;

public class Test1Service implements TestServiceInter,TestServiceInter2
{

	private String name;
	
	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	@Override
	public void sayHello()
	{
		System.out.println("hai " + name);
	}

	@Override
	public void sayBye()
	{
		System.out.println("bye " + name);
		int i = 9 / 0;
	}
}

在sayBye()方法中增加一个除零异常

编写异常通知:

package com.cdtax.aop;

import java.lang.reflect.Method;

import org.springframework.aop.ThrowsAdvice;

public class MyThrowsAdvice implements ThrowsAdvice
{
	public void afterThrowing(Method m,Object[] os,Object target,Exception throwable)
	{
		System.out.println("异常通知:出大事了" + throwable.getMessage());
	}
}

在beans.xml中配置:

<?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:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
				http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<!-- 配置被代理的对象 -->
<bean id="test1Service" class="com.cdtax.aop.Test1Service">
	<property name="name" value="小明"></property>
</bean>

<!-- 配置前置通知 -->
<bean id="myMethodBeforeAdvice" class="com.cdtax.aop.MyMethodBeforeAdvice"></bean>

<!-- 配置后置通知 -->
<bean id="myAfterReturningAdvice" class="com.cdtax.aop.MyAfterReturningAdvice"></bean>

<!-- 配置环绕通知 -->
<bean id="myMethodInterceptor" class="com.cdtax.aop.MyMethodInterceptor"></bean>

<!-- 配置异常通知 -->
<bean id="myThrowsAdvice" class="com.cdtax.aop.MyThrowsAdvice"></bean>

<!-- 配置代理对象 -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"> 
<!-- 代理接口集 -->
	<property name="proxyInterfaces">
		<list>
			<value>com.cdtax.aop.TestServiceInter</value>
			<value>com.cdtax.aop.TestServiceInter2</value>
		</list>
	</property>
	
	<!-- 把通知织入到代理对象  | 拦截器名集-->
	<property name="interceptorNames">
		<list>
		<!-- 相当于把 MyMethodBeforeAdvice前置通知和代理对象关联起来,我们也可以把通知看成拦截器,struts2核心就是拦截器 -->
		 <!-- 织入前置通知 -->
		 <value>myMethodBeforeAdvice</value> 
				
		<!-- 织入后置通知 -->
		<value>myAfterReturningAdvice</value>
		
		<!-- 织入环绕通知 -->
		<value>myMethodInterceptor</value>
		
		<!-- 织入异常通知 -->
		<value>myThrowsAdvice</value>
				
		</list>
	</property>
	
	<!-- 配置被代理对象,可以指定 -->
	<property name="target" ref="test1Service">
		
	</property>
</bean>
</beans>

运行App1测试类结果:

-----------------------------
前置通知  :记录日志...sayHello
环绕通知被调用:调用方法前执行  
hai 小明
环绕通知被调用:调用方法后执行   
后置通知被调用:关闭资源,
-----------------------------
前置通知  :记录日志...sayBye
环绕通知被调用:调用方法前执行  
bye 小明
异常通知:出大事了/ by zero
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.cdtax.aop.Test1Service.sayBye(Test1Service.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:126)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at com.cdtax.aop.MyMethodInterceptor.invoke(MyMethodInterceptor.java:13)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:50)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:50)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy0.sayBye(Unknown Source)
at com.cdtax.aop.App1.main(App1.java:17)

4、最后一个是引入通知,引入通知不需要编写相应的类,只需要进行配置,目的是用来指定哪些方法需要执行相应的通知,如,我们想指定只有sayHello()方法执行前置通知,

在beans.xml中如下配置:

<?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:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
				http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<!-- 配置被代理的对象 -->
<bean id="test1Service" class="com.cdtax.aop.Test1Service">
	<property name="name" value="小明"></property>
</bean>

<!-- 配置前置通知 -->
<bean id="myMethodBeforeAdvice" class="com.cdtax.aop.MyMethodBeforeAdvice"></bean>

<!-- 配置后置通知 -->
<bean id="myAfterReturningAdvice" class="com.cdtax.aop.MyAfterReturningAdvice"></bean>

<!-- 配置环绕通知 -->
<bean id="myMethodInterceptor" class="com.cdtax.aop.MyMethodInterceptor"></bean>

<!-- 配置异常通知 -->
<bean id="myThrowsAdvice" class="com.cdtax.aop.MyThrowsAdvice"></bean>

<!-- 定义前置通知的切入点 (引用通知) -->
<bean id="myMethodBeforeAdviceFilter" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
	<property name="advice" ref="myMethodBeforeAdvice"></property>
	<property name="mappedNames">
		<list>
			<value>sayHello</value>
		</list>
	</property>
</bean>

<!-- 配置代理对象 -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"> 
<!-- 代理接口集 -->
	<property name="proxyInterfaces">
		<list>
			<value>com.cdtax.aop.TestServiceInter</value>
			<value>com.cdtax.aop.TestServiceInter2</value>
		</list>
	</property>
	
	<!-- 把通知织入到代理对象  | 拦截器名集-->
	<property name="interceptorNames">
		<list>
		<!-- 相当于把 MyMethodBeforeAdvice前置通知和代理对象关联起来,我们也可以把通知看成拦截器,struts2核心就是拦截器 -->
		<!-- <value>myMethodBeforeAdvice</value>   -->
		
		<!-- 使用自定义切入点的前置通知 -->
		<value>myMethodBeforeAdviceFilter</value>
				
		<!-- 织入后置通知 -->
		<value>myAfterReturningAdvice</value>
		
		<!-- 织入环绕通知 -->
		<value>myMethodInterceptor</value>
		
		<!-- 织入异常通知 -->
		<value>myThrowsAdvice</value>
				
		</list>
	</property>
	
	<!-- 配置被代理对象,可以指定 -->
	<property name="target" ref="test1Service">
		
	</property>
</bean>
</beans>
更改Test1Service的sayBye()方法,去掉除零异常这一步,执行App1测试类结果:

-----------------------------
前置通知  :记录日志...sayHello
环绕通知被调用:调用方法前执行  
hai 小明
环绕通知被调用:调用方法后执行   
后置通知被调用:关闭资源,
环绕通知被调用:调用方法前执行  
bye 小明
环绕通知被调用:调用方法后执行   
后置通知被调用:关闭资源,

可以看到,只有sayHello()方法执行了前置通知,sayBye()方法没有执行

这就是引用通知,用来定义切入点的。

5、关于ts1的类型,

package com.cdtax.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App1
{
	public static void main(String[] args)
	{
		ApplicationContext ac = new ClassPathXmlApplicationContext("com/cdtax/aop/beans.xml");
		
//		Test1Service ts = (Test1Service) ac.getBean("test1Service");
//		ts.sayHello();
		
		TestServiceInter ts1 =  (TestServiceInter) ac.getBean("proxyFactoryBean");
		ts1.sayHello();
		System.out.println("ts1的类型:" + ts1);
		((TestServiceInter2)ts1).sayBye();
	}
}
我们获得ts1是通过getBean("proxyFactoryBean");获得的,proxyFactoryBean的class是org.springframework.aop.framework.ProxyFactoryBean,那么ts1的类型是不是也是它呢?运行上述程序,结果:

-----------------------------
前置通知  :记录日志...sayHello
环绕通知被调用:调用方法前执行  
hai 小明
环绕通知被调用:调用方法后执行   
后置通知被调用:关闭资源,
环绕通知被调用:调用方法前执行  
环绕通知被调用:调用方法后执行   
后置通知被调用:关闭资源,
ts1的类型:com.cdtax.aop.Test1Service@1982fc1
环绕通知被调用:调用方法前执行  
bye 小明
环绕通知被调用:调用方法后执行   
后置通知被调用:关闭资源,

可以看出,ts1的类型是com.cdtax.aop.Test1Service,它是proxyFactoryBean动态代理生成的。org.springframework.aop.framework.ProxyFactoryBean内部实现了动态代理方式。

spring在运行期创建代理,不需要特殊的编译器,spring有两种代理方式:

(1)若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理该类让spring动态产生一个新类,他实现了所需的接口,织入了通知,并且代理对目标对象的所有请求。
(2)若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。使用该方式时需要注意:
        1)对接口创建代理优先于对类创建代理,因为会产生更加松耦合的系统。对类代理是让遗留系统或无法实现接口的第三方类库同样可以得到通知,这种方式应该是beiyongfang'an。
        2)标记为final的方法不能够被通知。spring是为目标类产生子类。任何需要被通知的方法都被复写。将通知织入。final方法是不允许重写的。

spring实现了aop联盟接口。

spring只支持方法连接点:不提供属性接入点,spring的观点是属性拦截破坏了封装。面向对象的概念是对象自己处理工作,其他对象只能通过方法调用来得到结果。

6、对于引入通知,定义切面时可以使用正则表达式,如在定义切入点时使用say*,表示以say开头的所有方法。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

6、spring的五种类型通知 的相关文章

随机推荐

  • Python 机器学习8:sklearn 聚类算法

    1 K Means算法是一种广泛使用的聚类算法 from sklearn cluster import KMeans K Means是聚焦于相似的无监督的算法 xff0c 以距离作为数据对象间相似性度量的标准 xff0c 即数据对象间的距离
  • 什么是微服务——微服务架构体系介绍

    Why Microservices 回答这个问题前 xff0c 我们先看下之前大行其道的单体架构 Monolithic Architecture xff0c 对于非专业人士来讲 xff0c 所谓的单体架构 xff0c 其就像一个超大容器 x
  • 微服务架构特征

    一个典型的微服务架构 xff08 MSA xff09 通常包含以下组件 xff1a 客户端 xff1a 微服务架构着眼于识别各种不同的类型的设备 xff0c 以及在此设备上进行的各种管理操作 xff1a 搜索 构建 配置等等身份标识提供者
  • 微服务架构系列——API服务网关

    本章我们简单介绍微服务架构下的API服务网关 xff0c 本章我们将讨论以下话题 xff1a 什么是API服务网关为什么需要API服务网关API服务网关的工作机制 处理横切关注点 当我们在开发设计大型软件应用时 xff0c 我们一般都会采用
  • Java之keytool命令学习

    Java Keytool is a key and certificate management utility It allows users to manage their own public private key pairs an
  • HashMap 与 HashTable的区别

    HashMap 实现了Map接口非线程同步 xff0c 非线程安全不允许重复键键和值均允许为null HashMap lt Interger String gt employeeHashmap 61 new HashMap lt Integ
  • 如何避免敏捷失败?

    很多人都听说敏捷 xff0c 有些人知道敏捷是什么 xff0c 有些人也尝试过敏捷 xff0c 本章中将列举出一些常见的错误敏捷实践 xff0c 如果想要避免敏捷失败 xff0c 建议还是要对照下你所在的敏捷团队中有没有类似的敏捷实践 xf
  • 一个人有文化,到底有多重要?

    关于什么是文化 xff0c 我最最欣赏的回答 xff0c 是作家梁晓声的四句概括 xff1a 根植于内心的修养 xff0c 无需提醒的自觉 xff0c 以约束为前提的自由 xff0c 为别人着想的善良 01 一位叫做 Judy 的空姐 xf
  • MyBatis动态SQL中Map参数处理

    在MyBatis中 xff0c 如果我们需要传递两个参数 xff0c 有一种方式是通过Map作为传入参数 xff0c 在动态SQL中 xff0c 我们需要对传入的Map参数中的值进行判断 xff0c 然后进行动态SQL的条件拼接处理 假设我
  • MyBatis框架下防止SQL注入

    与传统的ORM框架不同 xff0c MyBatis使用XML描述符将对象映射到SQL语句或者存储过程中 xff0c 这种机制可以让我们更大的灵活度通过SQL来操作数据库对象 xff0c 因此 xff0c 我们必须小心这种便利下SQL注入的可
  • 使用android 视频解码mediaCodec碰到的几个问题

    问题1 mediaCodec dequeueInputBuffer一直返回 1 xff0c APP现象 xff1a 视屏卡屏 原因 xff1a 这是因为inputbuffer的内容有误 xff0c 导致无法解码 可通过设延时时间解决 xff
  • 云计算思维导图

    根据近期的云计算学习心得 xff0c 将云计算部分内容制作成思维导图 xff0c 方便于广大云计算学习者作为辅导讲义 xff01 思维导图内容主要包含 xff1a 1 云计算概述 2 云体系结构 3 网络资源 4 存储资源 5 硬件介绍 6
  • 路由器重温——串行链路链路层协议积累

    对于广域网接口来说 xff0c 主要的不同或者说主要的复杂性在于理解不同接口的物理特性以及链路层协议 xff0c 再上层基本都是 IP 协议 xff0c 基本上都是相同的 WAN口中的serial接口主要使用点对点的链路层协议有 xff0c
  • 路由器重温——PPPoE配置管理-2

    四 配置设备作为PPPoE服务器 路由器的PPPoE服务器功能可以配置在物理以太网接口或 PON 接口上 xff0c 也可配置在由 ADSL 接口生成的虚拟以太网接口上 1 配置虚拟模板接口 虚拟模板接口VT和以太网接口或PON接口绑定后
  • Python入门自学进阶——1--装饰器

    理解装饰器 xff0c 先要理解函数和高阶函数 首先要明白 xff0c 函数名就是一个变量 xff0c 如下图 xff0c 定义一个变量名和定义一个函数 xff0c 函数名与变量名是等价的 既然函数名就是一个变量名 xff0c 那么在定义函
  • Python入门自学进阶-Web框架——21、DjangoAdmin项目应用

    客户关系管理 以admin项目为基础 xff0c 扩展自己的项目 一 创建项目 二 配置数据库 xff0c 使用mysql数据库 xff1a 需要安全mysqlclient模块 xff1a pip install mysqlclient D
  • Python入门自学进阶-Web框架——33、瀑布流布局与组合查询

    一 瀑布流 xff0c 是指页面布局中 xff0c 在显示很多图片时 xff0c 图片及文字大小不相同 xff0c 导致页面排版不美观 如上图 xff0c 右边的布局 xff0c 因为第一行第一张图片过长 xff0c 第二行的第一张被挤到第
  • Python入门自学进阶-Web框架——34、富文本编辑器KindEditor、爬虫初步

    KindEditor 是一个轻量级的富文本编辑器 xff0c 应用于浏览器客户端 一 首先是下载 xff1a http kindeditor net down php xff0c 如下图 下载后是 解压缩后 xff1a 红框选中的都可以删除
  • Python入门自学进阶-Web框架——35、网络爬虫使用

    自动从网上抓取信息 xff0c 就是获取相应的网页 xff0c 对网页内容进行抽取整理 xff0c 获取有用的信息 xff0c 保存下来 要实现网上爬取信息 xff0c 关键是模拟浏览器动作 xff0c 实现自动向网址发送请求 xff0c
  • 6、spring的五种类型通知

    spring共提供了五种类型的通知 xff1a 通知类型接口描述Around 环绕通知org aopalliance intercept MethodInterceptor拦截对目标方法调用Before 前置通知org springfram