【JavaEE进阶】Spring AOP使用篇

目录

1.AOP概述

2.SpringAOP快速入门

2.1 引入AOP依赖

2.2 编写AOP程序

3. Spring AOP详解

3.1 Spring AOP 核心概念

3.1.1切点(Pointcut)

3.1.2 连接点 (Join Point)

3.1.3 通知(Advice)

3.1.4 切面(Aspect)

3.2 通知类型

3.3@PointCut

3.4 切面优先级

3.5 切点表达式

3.5.1 execution 表达式

3.5.2 @annotation

3.5.2.1 自定义注解 @MyAspect

3.5.2.2 切面类

3.5.2.3 添加自定义注解

4. Spring AOP的实现方式


1.AOP概述

AOP是Spring框架的一大核心(第一大核心是loC)

什么是AOP?

Aspect Oriented Programming(面向切面编程)

什么是面向切面编程呢?切面就是指某一类特定问题, 所以 AOP 也可以理解为面向特定方法编程.

什么是面向特定方法编程呢? 比如以前学习的"登录校验", 就是一类特定问题.  登录校验拦截器, 就
是对 "登录校验" 这类问题的统一处理. 所以,拦截器也是 AOP 的一种应用. AOP 是一种思想,拦截器是 AOP 思想的一种实现. Spring 框架实现了这种思想,  提供了拦截器技术的相关接口.

同样的, 统一数据返回格式和统一异常处理,也是AOP思想的一种实现.

简单来说:  AOP是一种思想,是对某一类事情的集中处理.
 

什么是 Spring AOP ?

AOP是一种思想,它的实现方法有很多,有Spring AOP, 也有AspectJ, CGLIB等.

Spring AOP是其中的一种实现方式.

学会了统一功能之后,是不是就学会了Spring AOP呢,当然不是.

截器作用的维度是URL(一次请求和响应), @ControllerAdvice 应用场景主要是全局异常处理
(配合自定义异常效果更佳), 数据绑定 , 数据预处理.  AOP 作用的维度更加细致(可以根据包、类、方法名、参数等进行拦截),  能够实现更加复杂的业务逻辑.

举个例子:

我们现在有一个项目, 项目中开发了很多的业务功能

现在有一些业务的执行效率比较低, 耗时较长, 我们需要对接口进行优化.

第一步就需要定位出执行耗时比较长的业务方法, 在针对该业务方法来进行优化

如何定位呢? 我们就需要统计当前项目中每一个业务方法的执行耗时.

如何统计呢? 可以在业务方法运行前和运行后,  记录下方法的开始时间和结束时间, 两者之差就是这个方法的耗时. 

这种方法是可以解决问题的,但一个项目中会包含很多业务模块,每个业务模块又有很多接口,一个接口又包含很多方法, 如果我们要在每个业务方法中都记录方法的耗时,对于程序员而言, 会增加很多的工作量.

AOP 就可以做到在不改动这些原始方法的基础上, 针对特定的方法进行功能的增强.

AOP 的作用: 在程序执行期间不修改源代码的基础上对已有方法的增强(无侵入性: 解耦)

接下来我们来看看 SpringAOP 如何来实现.

2.SpringAOP快速入门

学习完什么是 AOP 后, 我们先通过下面的程序体验下 AOP 的开发, 并掌握 Spring 中 AOP 的开发步骤.

需求: 统计图书系统中各个接口方法的执行时间.

2.1 引入AOP依赖

在 pom.xml 文件中添加配置

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.2 编写AOP程序

记录 Controller 中每个方法的执行时间

先看看传统的方法:

/*** 根据ID查询图书信息** @param bookId* @return*/@RequestMapping("/queryBookById")public BookInfo queryBookById(Integer bookId) {log.info("根据ID查询图书信息, id:{}", bookId);long start = System.currentTimeMillis();BookInfo bookInfo = bookService.queryBookById(bookId);long end = System.currentTimeMillis();log.info("[BookController] queryBookById 耗时: " + (end-start) + " ms");return bookInfo;}

使用这种方式, 当要测试多个接口的时候, 就需要对每个接口的代码进行修改 , 工作量比较复杂, 很影响我们的时间和效率.

下面来看看使用AOP的代码吧:

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;@Component
@Slf4j
@Aspect
public class TimeRecordAspect {/*** 记录耗时*/@Around("execution(* com.example.demo.controller.*.*(..))")public Object TimeRecord(ProceedingJoinPoint joinPoint) throws Throwable {//记录开始事件long start = System.currentTimeMillis();//执行目标方法Object proceed = joinPoint.proceed();//记录结束时间long end = System.currentTimeMillis();//日志打印耗时log.info(joinPoint.getSignature() + " 耗时时间: " + (end- start) + " ms");return proceed;}
}

运行程序, 观察日志

对程序进行简单的讲解:

1. @Aspect: 标识这是一个切面类

2. @Around: 环绕通知, 在目标方法的前后都会被执行. 后⾯的表达式表示对哪些方法进行增强.

3. ProceedingJoinPoint.proceed(): 让原始方法执行

整个代码划分为三部分

我们通过AOP入门程序完成了业务接口执行耗时的统计.

通过上面的程序,我们也可以感受到AOP面向切面编程的一些优势:

  • 代码无侵入: 不修改原始的业务方法, 就可以对原始的业务方法进行了功能的增强或者是功能的改变
  • 减少了重复代码
  • 提高开发效率
  • 维护方便
     

3. Spring AOP详解

下面我门再来详细学习AOP, 主要是一下几个部分

Spring AOP 中涉及的核心概念

Spring AOP 的通知类型

多个 AOP 的执行顺序

3.1 Spring AOP 核心概念

3.1.1切点(Pointcut)

切点(Pointcut), 也称之为 "切入点"

Pointcut 的作用就是提供一组规则(使用 AspectJ pointcut expression language 来描述), 告诉程序对哪些方法来进行功能增强.

上面的表达式  execution(* com.example.demo.controller.*.*(..)) 就是切点表达式.

3.1.2 连接点 (Join Point)

满足切点表达式规则的方法, 就是连接点, 也就是可以被 AOP 控制的方法

以如门程序举例, 所有 com.example.demo.controller 路径下的方法, 都是连接点

package com.example.demo.controller;@RequestMapping("/book")
@RestController
public class BookController {@RequestMapping("/addBook")public Result addBook(BookInfo bookInfo) {//...代码省略 }@RequestMapping("/queryBookById")public BookInfo queryBookById(Integer bookId) {//...代码省略 }@RequestMapping("/updateBook")public Result updateBook(BookInfo bookInfo) {//...代码省略 }
}

上述 BookController 中的方法都是连接点

切点和连接点的关系

连接点是满足切点表达式的元素, 切点可以看作是保存了众多连接点的一个集合.

比如:

切点表达式: 全体教师

连接点就是: 张三, 李四等各个教室

3.1.3 通知(Advice)

通知就是具体要做的事情, 指哪些重复的逻辑, 也就是共性功能(最终体现为一个方法)

比如上述程序中记录业务方法的耗时时间, 就是通知

在AOP面向切面编程当中, 我门把这部分重复的代码逻辑抽取出来单独定义, 这部分代码就是通知类容.

3.1.4 切面(Aspect)

切面(Aspect) = 切点(Pointcut) + 通知(Advice)

通过切面就能描述当前AOP程序需要针对于哪些方法, 在什么时候执行什么样的操作.

切面既包含了通知逻辑的定义, 也包括了连接点的定义.

切面所在的类, 我们一般称为切面类(被@Aspect注解标识的类)

3.2 通知类型

上面我们讲了什么是通知, 接下来学习通知的类型. @Around 就是其中的一种通知类型, 表示环绕通知.

Spring 中 AOP 的通知类型有一下几种:

@Around: 环绕通知, 次注解标注的通知方法在目标方法前, 后都被执行

@Before: 前置通知, 次注解表述的通知方法在目标方法前被执行

@After: 后置通知, 次注解标注的通知方法在目标方法后被执行, 无论是否有异常都会执行

@AfterReturning: 返回后通知, 次注解标注的通知方法在目标方法返回后被执行, 有异常不会执行

@AfterThrowing: 次注解标注的通知方法发生异常后执行

接下来我门通过代码来加深对这几个通知的理解:

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Component
@Slf4j
@Aspect
public class AspectDemo {//前置通知@Before("execution(* com.example.aop.controller.*.*(..))")public void doBefore() {log.info("AspectDemo do before...");}//后置通知@After("execution(* com.example.aop.controller.*.*(..))")public void doAfter() {log.info("AspectDemo do after...");}//环绕通知@Around("execution(* com.example.aop.controller.*.*(..))")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {log.info("AspectDemo do around before...");Object result = null;try {result = joinPoint.proceed();}catch (Exception e) {log.error("do around 执行目标函数, 内部发生异常");}log.info("AspectDemo do around after...");return result;}//返回后通知@AfterReturning("execution(* com.example.aop.controller.*.*(..))")public void doAfterReturning() {log.info("AspectDemo do AfterReturning...");}//抛出异常后通知@AfterThrowing("execution(* com.example.aop.controller.*.*(..))")public void doAfterThrowing() {log.info("AspectDemo do AfterThrowing...");}
}

写一些测试程序:

import com.example.aop.config.MyAspect;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/test")
@RestController
@Slf4j
public class TestController {@MyAspect@RequestMapping("/t1")public String t1() {log.info("执行t1方法....");return "t1";}@RequestMapping("/t2")public String t2() {log.info("执行t2方法....");int a = 10/0;return "t2";}
}

运行程序, 观察日志:

1.正常运行的情况

观察日志

程序正常运行的情况下, @AfterThrowing 标识的通知方法不会执行

从上图也可以看出来, @Around 标识的通知方法包含两个部分, 一个 "前置逻辑" , 一个 "后置逻辑" .其中 "前置逻辑" 会先于 @Before 标识的通知方法执行. "后置逻辑" 会晚于 @After 标识的通知方法执行

2. 异常时的情况

观察日志

程序发生异常的情况下:

@AfterReturning 标识的通知方法不会执行, @AfterThrowing 标识的通知方法执行了

@Around 环绕通知中原始方法调用时有异常, 通知中的环绕后的代码也不会在执行了(因为原始方法调用出异常了)

注意事项:

@Around 环绕通知需要调用 ProceedingJoinPoint.proceed() 来让原始方法执行, 其他通知不需要考虑目标方法执行.

@Around环绕通知方法的返回值, 必须指定为Object , 来接收原始方法的返回值, 否则原始方法执行完毕, 是获取不到返回值的.

一个切面类可以有多个切点

3.3@PointCut

上面代码存在一个问题, 就是存在大量重复的切点表达式 execution(* com.example.demo.controller.*.*(..)) , Spring 提供了 @Pointcut 注解, 把公共的切点表达式提取出来, 需要用到时引入该切点表达式即可.

上述代码就可以修改为:

@Component
@Slf4j
@Aspect
public class AspectDemo {@Pointcut("execution(* com.example.aop.controller.*.*(..))")public void pt(){};//前置通知@Before("pt()")public void doBefore() {//...代码省略}//后置通知@After("pt()")public void doAfter() {//...代码省略}//添加环绕通知@Around("pt()")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {//...代码省略}//返回后通知@AfterReturning("pt()")public void doAfterReturning() {//...代码省略}//抛出异常后通知@AfterThrowing("pt()")public void doAfterThrowing() {//...代码省略}
}

当请切点使用 private 修饰时, 仅能在当前切面类中使用, 当其他切面类也要使用当前切点定义时, 就需要把 private 改为 public, 引用方式为: 全限定类名.方法名()

@Component
@Slf4j
@Aspect
public class AspectDemo2 {@Before("com.example.aop.aspect.AspectDemo.pt()")public void doBefore() {log.info("AspectDemo2 do before...");}@After("com.example.aop.aspect.AspectDemo.pt()")public void doAfter() {log.info("AspectDemo2 do after...");}
}

3.4 切面优先级

当我们在一个项目中,定义了多个切面类时,并且这些切面类的多个切入点都匹配到了同一个目标方法. 当目标方法运行的时候,这些切面类中的通知方法都会执行,那么这几个通知方法的执行顺序是什么样的呢?

我们还是通过程序来验证:

定义多个切⾯类:

为了防止干扰, 我们把AspectDemo这个切面先去掉(把@Component注解去掉就可以)

为了简单化, 只写了@Before 和 @After 两个通知

@Component
@Slf4j
@Aspect
public class AspectDemo2 {@Before("com.example.aop.aspect.AspectDemo.pt()")public void doBefore() {log.info("AspectDemo2 do before...");}@After("com.example.aop.aspect.AspectDemo.pt()")public void doAfter() {log.info("AspectDemo2 do after...");}
}
@Component
@Slf4j
@Aspect
public class AspectDemo3 {@Before("com.example.aop.aspect.AspectDemo.pt()")public void doBefore() {log.info("AspectDemo3 do before...");}@After("com.example.aop.aspect.AspectDemo.pt()")public void doAfter() {log.info("AspectDemo3 do after...");}
}
@Component
@Slf4j
@Aspect
public class AspectDemo4 {@Before("com.example.aop.aspect.AspectDemo.pt()")public void doBefore() {log.info("AspectDemo4 do before...");}@After("com.example.aop.aspect.AspectDemo.pt()")public void doAfter() {log.info("AspectDemo4 do after...");}
}

运行程序, 访问接口:

 观察日志:

通过上述程序的运行结果, 可以看出:

存在多个切面类时, 默认按照切面类的名字母排序:

  • @Before 通知: 字母名字靠前的先执行
  • @After 通知: 字母排名靠前的后执行

但这种方式不方便管理,我们的类名更多还是具备一定含义的.

Spring给我们提供了一个新的注解,来控制这些切面通知的执行顺序: @Order

使用方式如下:

重新运行程序, 观察日志:

通过上述程序的运行结果, 得出结论:

@Order 注解标识的切面类, 执行顺序如下:

@Before 通知: 数字越小先执行

@After 通知: 数字越大先执行

@Order 控制切面的优先级, 先执行优先级高的切面, 在执行优先级较低的切面, 最终执行目标方法.

3.5 切点表达式

上面的代码中,我们一直在使用切点表达式来描述切点. 下面我们来介绍一下切点表达式的语法.

切点表达式常见有两种表达方式

1. execution(......): 根据方法的签名来匹配

2. @annotation(......): 根据注解匹配

3.5.1 execution 表达式

execution() 是最常用的切点表达式, 用来匹配方法, 语法为:

其中: 访问修饰符和异常可以省略

切点表达式支持通配符表达:

1.: 匹配任意字符, 只匹配一个元素(返回类型, 包, 类名, 方法或者方法参数)

a. 包名使用 表示任意包(一层包使用一个 * )

b. 类名使用 表示任意类

c. 返回值使用 表示任意返回值类型

d. 方法名使用 表示任意方法

e. 参数使用 表示一个任意类型的参数

2. .. : 匹配多个连续的任意符号, 可以通配任意层级的包, 或任意类型, 任意个数的参数

a. 使用 .. 配置包名, 标识次包以及此包下的所有子包

b. 可以使用 .. 配置参数, 任意个任意类型的参数

切点表达式示例

TestController 下的 public 修饰, 返回类型为 String 方法名为 t1, 无参方法

execution(public String com.example.demo.controller.TestController.t1())

省略访问修饰符

execution(String com.example.demo.controller.TestController.t1())

匹配所有返回类型

execution(* com.example.demo.controller.TestController.t1())

匹配 TestController 下的所有无参方法

execution(* com.example.demo.controller.TestController.*())

匹配 TestController 下的所有方法

execution(* com.example.demo.controller.TestController.*(..))

匹配 controller 包下所有的类的所有方法

execution(* com.example.demo.controller.*.*(..))

匹配所有包下面的 TestController

execution(* com..TestController.*(..))

匹配 com.example.demo 包下, 子孙包下的所有类的所有方法

execution(* com.example.demo..*(..))

匹配特定方法名且有特定参数的方法:

execution(* myMethod(String, int))

 匹配特定方法名且有特定参数, 并且抛出特定异常的方法

execution(* myMethod(String, int) throws IOExeception)

3.5.2 @annotation

execution 表达式更适合有规则的, 如果我门要匹配多个无规则的方法呢, 比如: TestController中的 t1() 和 UserController 中的 u1() 这两个方法.

这个时候我们使用 execution 这种切点表达式来描述就不是很方便了.

我们可以借助自定义注解的方法以及另一种切点表达式 @annotation 来描述这一类的切点

实现步骤:

1. 编写自定义注解

2. 使用 @annotation 表达式来描述切点

3. 在连接点的方法上添加自定义注解

准备测试代码

@RequestMapping("/test")
@RestController
@Slf4j
public class TestController {@RequestMapping("/t1")public String t1() {log.info("执行t1方法....");return "t1";}@RequestMapping("/t2")public String t2() {log.info("执行t2方法....");int a = 10/0;return "t2";}
}
@Slf4j
@RequestMapping("/user")
@RestController
public class UserController{@RequestMapping("/u1")public String u1() {log.info("执行u1方法...");return "u1";}@RequestMapping("/u2")public String u2() {log.info("执行u2方法...");return "u2";}
}
3.5.2.1 自定义注解 @MyAspect

创建一个注解类(和创建Class文件一样的流程, 选择Annotation就可以了)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAspect {}

代码简单说明, 了解即可, 不做过多的解释

1. @Target 标识了 Annotation 所修饰的对象范围, 及该注解可以用在什么地方.

常用取值: 

ElementType.TYPE: 用于描述类, 接口(包括注解类型)或 enum 声明

ElementType.METHOD: 描述方法

ElementType.PARAMETER: 描述参数

ElementType.TYPE_USE: 可以标注任意类型

2. @Retention 指 Annotation 被保留的时间长短, 标明注解的声明周期

@Retention的取值有三种

1. RetentionPolicy.SOURCE: 表示注解仅存在于源代码中,编译成字节码后会被丢弃. 这意味着在运行时无法获取到该注解的信息,  只能在编译时使用.  比如@SuppressWarnings,  以及lombok  提供的注解 @Data, @Slf4j

2. RetentionPolicy.CLASS: 编译时注解. 表示注解存在于源代码和字节码中,但在运行时会被丢弃. 这意味着在编译时和字节码中可以通过反射获取到该注解的信息,  但在实际运行时无法获取. 通常用于一些框架和工具的注解.

3. RetentionPolicy.RUNTIME: 运行时注解. 表示注解存在于源代码,字节码和运行时中. 这意味着在编译时,字节码中和实际运行时都可以通过反射获取到该注解的信息. 通常用于一些需要在运行时处理的注解,如Spring的 @Controller @ResponseBody

3.5.2.2 切面类

使用 @annotation 切点表达式定义切点, 只对 @MyAspect 生效

切面类代码如下:

@Component
@Slf4j
@Aspect
public class MyAspectDemo {//前置通知@Before("@annotation(com.example.aop.config.MyAspect)")public void before() {log.info("MyAspect -> before...");}//后置通知@After("@annotation(com.example.aop.config.MyAspect)")public void after() {log.info("MyAspect -> after...");}
}
3.5.2.3 添加自定义注解

在 TestController 中 t1() 和 UserController 中的 u1() 这两个方法上添加自定义注解 @MyAspect, 其他方法不加

运行程序, 测试接口:

观察日志:

继续测试 t2, 观察日志:

切面通知未执行

4. Spring AOP的实现方式

1.基于注解 @Aspect

2. 基于自定义注解(参考上面自定义注解 @annotation 部分的内容)

3. 基于Spring API (通过xml配置的方法, 自从SpringBoot广泛使用之后, 这种方法几乎看不到了, 稍作了解即可)

4. 基于代理来实现(更加久远的一种方式, 写法笨重, 不建议使用)

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

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

相关文章

「51媒体」政企活动媒体宣发如何做?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体宣传加速季&#xff0c;100万补贴享不停&#xff0c;一手媒体资源&#xff0c;全国100城线下落地执行。详情请联系胡老师。 政企活动媒体宣发是一个系统性的过程&#xff0c;需要明确…

使用Scala爬取安居客房产信息并存入CSV文件

使用Scala爬取安居客房产信息并存入CSV文件 本篇博客中&#xff0c;我们将介绍如何使用Scala语言编写一个简单的程序&#xff0c;来爬取安居客&#xff08;Anjuke&#xff09;网站上的房产信息&#xff0c;并将这些信息存储到CSV文件中。这个示例将涵盖HTTP请求、HTML解析、数…

麒麟系统安装MySQL

搞了一整天&#xff0c;终于搞定了&#xff0c;记录一下。 一、背景 项目的原因&#xff0c;基于JeecgBoot开发的系统需要国产化支持&#xff0c;这就需要在电脑上安装MySQL等支撑软件。 国产化项目的操作系统多是麒麟系统&#xff0c;我的系统如下&#xff1a; arm64架构。…

详细分析Oracle修改默认的时间格式(四种方式)

目录 前言1. 会话级别2. 系统级别3. 环境配置4. 函数格式化5. 总结 前言 默认的日期和时间格式由参数NLS_DATE_FORMAT控制 如果需要修改默认的时间格式&#xff0c;可以通过修改会话级别或系统级别的参数来实现 1. 会话级别 在当前会话中设置日期格式&#xff0c;这只会影响…

CCSP自考攻略+经验总结

备考攻略 备考攻略准备阶段通读阶段精度阶段总复习阶段刷题阶段命运审判 写到最后 备考攻略 趁着对ssp知识点的理解还在&#xff0c;开始ccsp的考证之路&#xff0c;文章结构还是按照cissp备考篇的结构梳理。本次备考和cissp的离职在家备考不同&#xff0c;ccsp是在职利用非工…

2018年全国大学生数学建模竞赛A题高温服装设计(含word论文和源代码资源)

文章目录 一、部分题目二、部分论文三、部分Matlab源代码问题11 求解h1h22 已知h1h2求解温度分布 问题21 求解第二层最佳厚度 四、完整word版论文和源代码&#xff08;两种获取方式&#xff09; 一、部分题目 2018 年高教社杯全国大学生数学建模竞赛题目 A 题 高温作业专用服…

【C语言】字符/字符串+内存函数

目录 Ⅰ、字符函数和字符串函数 1 .strlen 2.strcpy 3.strcat 4.strcmp 5.strncpy 6.strncat 7.strncmp 8.strstr 9.strtok 10.strerror 11.字符函数 12. 字符转换函数 Ⅱ、内存函数 1 .memcpy 2.memmove 3.memcmp 4.memset Ⅰ、字符函数和字符串函数 1 .strlen 函数原型&…

Vite: 关于Rollup打包

概述 Rollup 是一款基于 ES Module 模块规范实现的 JavaScript 打包工具&#xff0c;在前端社区中赫赫有名&#xff0c;同时也在 Vite 的架构体系中发挥着重要作用不仅是 Vite 生产环境下的打包工具&#xff0c;其插件机制也被 Vite 所兼容&#xff0c;可以说是 Vite 的构建基…

JavaScript--js基础(详细 全面)

目录 前言: JavaScript 是什么&#xff1f;JavaScript 简介 1.JavaScript历史 2.JavaScript 具有以下特点 第一个JavaScript程序 1.在脚本文件中编写JavaScript代码 2.JavaScript代码执行顺序 基本语法 1.变量 2.数据类型 3.算术运算符 4.赋值运算 5.字符串运算符 6…

微服务应用与开发知识点练习【Gateway,OpenFeign,Dubbo,RocketMQ和RabbitMQ,JPA,Redis,Mycat】

一、选择题 【Gateway】 1.Spring Cloud Gateway与Nacos整合实现负载均衡时&#xff0c;路由配置中的URI前缀应该是&#xff1f;&#xff08;A &#xff09; A. lb:// B. nacos:// C. http:// D. discovery:// Spring Cloud Gateway与Nacos整合实现负载均衡时&#xff0c…

华为od 2024 | 什么是华为od,od 薪资待遇,od机试题清单

目录 专栏导读华为OD机试算法题太多了&#xff0c;知识点繁杂&#xff0c;如何刷题更有效率呢&#xff1f; 一、逻辑分析二、数据结构1、线性表① 数组② 双指针 2、map与list3、队列4、链表5、栈6、滑动窗口7、二叉树8、并查集9、矩阵 三、算法1、基础算法① 贪心思维② 二分查…

鸿蒙面试心得

自疫情过后&#xff0c;java和web前端都进入了冰河时代。年龄、薪资、学历都成了找工作路上躲不开的门槛。 年龄太大pass 薪资要高了pass 学历大专pass 好多好多pass 找工作的路上明明阳关普照&#xff0c;却有一种凄凄惨惨戚戚说不清道不明的“优雅”意境。 如何破局&am…

vite-ts-cesium项目集成mars3d修改相关的包和配置参考

如果vite技术栈下使用原生cesium&#xff0c;请参考下面文件的包和配置修改&#xff0c;想用原生创建的viewer结合我们mars3d的功能的话。 1. package.json文件 "dependencies": {"cesium": "^1.103.0","mars3d": "^3.7.18&quo…

Java——IO流(一)-(8/8):释放资源-try-catch-finally、try-catch-resource

目录 try-catch-finally 介绍 实例演示1 实例演示2 try-catch-resource 介绍 实例演示 try-catch-finally 介绍 普通的释放流的方法可能会因中间的异常或是其他原因&#xff0c;导致程序执行不到释放流的代码就结束了&#xff0c;会有资源浪费的风险&#xff0c;所以建…

Web渗透:文件包含漏洞(part.1)

"文件包含漏洞"&#xff08;File Inclusion Vulnerability&#xff09;是一种常见的Web应用程序漏洞&#xff0c;攻击者可以通过这个漏洞在目标系统上包含或执行任意文件。主要有两种类型的文件包含漏洞&#xff1a; 本地文件包含&#xff08;Local File Inclusion, …

Python学习打卡:day17

day17 笔记来源于&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了 目录 day17121、Python 操作 MySQL 基础使用pymysql创建到 MySQL 的数据库链接执行 SQL 语句执行非查询性质的SQL语句执行查询性质的SQL语句 122、Pyth…

全局mixins

一、文章由来 在开发过程中发现在钩子函数位置直接使用dicts就能直接绑定数据了&#xff0c;由此溯源发现了自己的盲区 二、局部使用 // myMixin.js文件 var myMixin {created: function () {this.hello()},methods: {hello: function () {console.log(hello from mixin!)…

隐秘而又复杂的恶意软件:SSLoad

SSLoad 是一种隐秘的恶意软件&#xff0c;主要通过钓鱼邮件打开突破口&#xff0c;收集各种信息再回传给攻击者。近期&#xff0c;研究人员发现 SSLoad 通过诱饵 Word 文档投递恶意 DLL 文件&#xff0c;最终部署 Cobalt Strike。另一种攻击方式是利用钓鱼邮件诱导受害者到 Azu…

JVM专题十三:总结与整理(持续更新)

图解JVM JVM与Java体系结构 JVM垃圾回收算法 JVM垃圾回收器 图解JVM主要是放了前面12个章节的我们给大家画的图&#xff0c;做了整体的汇总&#xff0c;大家可以根据图区回忆我们所说的内容&#xff0c;查缺补漏。 实战经验 1、项目中数据量多少&#xff0c;QPS与TPS最高多少…

展开说说:Android列表之RecyclerView

RecyclerView 它是从Android5.0出现的全新列表组件&#xff0c;更加强大和灵活。用于显示列表形式 (list) 或者网格形式 (grid) 的数据&#xff0c;替代ListView和GridView成为Android主流的列表组件。可以说Android客户端只要有表格的地方就有RecyclerView。 RecyclerView 内…