【SSM框架】Spring笔记 – AOP详解;AspectJ中四种通知的使用

1、面向切面编程AOP

AOP(Aspect Orient Programming),面向切面编程。

切面:公共的,通用的,重复的功能称为切面,面向切面编程就是将切面提取出来,单独开发,在需要调用的方法中通过动态代理的方式进行织入。

2、AOP框架的”进化”

1)第一个版本:业务和切面紧耦合在一起,没有拆分.

2)第二个版本:使用子类代理的方式拆分业务和切面.

3)第三个版本:使用静态代理拆分业务和切面.业务和业务接口已拆分.此时切面紧耦合在业务中

4)第四个版本:使用静态代理拆分业务和业务接口,切面和切面接口.

5)第五个版本:使用动态代理完成第四个版本的优化.

3、Spring支持的AOP的实现

Spring支持AOP的编程,常用的有以下几种:

1)Before通知:在目标方法被调用前调用,涉及接口为 org.springframework.aop.MethodBeforeAdvice

2)After通知:在目标方法被调用后调用,涉及接口为 org.springframework.aop.AfterReturningAdvice

3)Throws通知:在目标方法抛出异常时调用,涉及接口为 org.springframework.aop.ThrowsAdvice

4)Around通知:拦截对目标对象方法调用,涉及接口为 org.aopalliance.intercept.MethodInterceptor

4、AOP常用的术语

1)切面:就是那些重复的,公共的,通用的功能称为切面,例如:日志,事务,权限.

2)连接点:就是目标方法.因为在目标方法中要实现目标方法的功能和切面功能.

3)切入点(Pointcut):指定切入的位置,多个连接点构成切入点,切入点可以是一个目标方法,可以是一个类中的所有方法,可以是某个包下的所有类中的方法.

4)目标对象:操作谁,谁就是目标对象.

5)通知(Advice):来指定切入的时机,是在目标方法执行前还是执行后还是出错时,还是环绕目标方法切入切面功能.

5、AspectJ框架

  • AspectJ 是一个优秀的面向切面的框架,它扩展了 Java 语言,提供了强大的切面实现。它因为是基于java语言开发的,所以无缝扩展

AspectJ 中常用的通知有四种类型:

1)前置通知@Before

2)后置通知@AfterReturning

3)环绕通知@Around

4)最终通知@After

5)定义切入点@Pointcut(了解)

6、AspectJ 的切入点表达式(掌握)

规范的公式:

  • execution(访问权限 方法返回值 方法声明(参数) 异常类型)

可简化为:

  • execution( 方法返回值 方法声明(参数) )

用到的符号:

  • 代表任意(通配符)
    .. 如果出现在方法的参数中,则代表任意参数;如果出现在路径中,则代表本路径及其所有的子路径(其实就相当于路径中的省略号呗)

示例:

//任意的公共方法:

execution(public * *(..))

//任何一个以”set”开始的方法

execution( set(..))

//任意的返回值类型,在com.xyz.service.impl包下的任意类的任意方法

execution( com.xyz.service.impl..*(..))

//任意的返回值类型 ,在com.xyz.service及其子包下的任意类的任意方法

execution( com.xyz.service...*(..))

//service之前可以有任意的子包

execution( ..service..(..))

//service之前只有一个包

execution( .service..(..))

7、AspectJ的前置通知@Before:

  • 在目标方法执行前切入切面功能,在切面方法中不可以获得目标方法的返回值,只能得到目标方法的签名。

实现的步骤:

1)添加依赖:

<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-aspects</artifactid>
    <version>5.2.5.RELEASE</version>&#xA0;
</dependency>

2)创建业务接口

3)创建业务实现

4)创建切面类,实现切面方法

5)在applicationContext.xml文件中进行切面绑定

栗子:

@Aspect &#xA0;//&#x4EA4;&#x7ED9;AspectJ&#x7684;&#x6846;&#x67B6;&#x53BB;&#x8BC6;&#x522B;&#x5207;&#x9762;&#x7C7B;
@Component
public class MyAspect {
&#xA0; &#xA0; /**
&#xA0; &#xA0; &#xA0;* &#x6240;&#x6709;&#x5207;&#x9762;&#x7684;&#x529F;&#x80FD;&#x90FD;&#x662F;&#x7531;&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x6765;&#x5B9E;&#x73B0;&#x7684;
&#xA0; &#xA0; &#xA0;* &#x53EF;&#x4EE5;&#x5C06;&#x5404;&#x79CD;&#x5207;&#x9762;&#x90FD;&#x5728;&#x6B64;&#x7C7B;&#x4E2D;&#x8FDB;&#x884C;&#x5F00;&#x53D1;
&#xA0; &#xA0; &#xA0;*
&#xA0; &#xA0; &#xA0;* &#x524D;&#x7F6E;&#x901A;&#x77E5;&#x7684;&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x7684;&#x89C4;&#x8303;
&#xA0; &#xA0; &#xA0;* 1)&#x8BBF;&#x95EE;&#x6743;&#x9650;&#x662F;public
&#xA0; &#xA0; &#xA0;* 2)&#x65B9;&#x6CD5;&#x7684;&#x8FD4;&#x56DE;&#x503C;&#x662F;void
&#xA0; &#xA0; &#xA0;* 3)&#x65B9;&#x6CD5;&#x540D;&#x79F0;&#x81EA;&#x5B9A;&#x4E49;
&#xA0; &#xA0; &#xA0;* 4)&#x65B9;&#x6CD5;&#x6CA1;&#x6709;&#x53C2;&#x6570;&#xFF0C;&#x5982;&#x679C;&#x6709;&#x4E5F;&#x53EA;&#x80FD;&#x662F;JoinPoint&#x7C7B;&#x578B;
&#xA0; &#xA0; &#xA0;* 5)&#x5FC5;&#x987B;&#x4F7F;&#x7528;@Before&#x6CE8;&#x89E3;&#x6765;&#x58F0;&#x660E;&#x5207;&#x5165;&#x7684;&#x65F6;&#x673A;&#x662F;&#x524D;&#x5207;&#x529F;&#x80FD;&#x548C;&#x5207;&#x5165;&#x70B9;
&#xA0; &#xA0; &#xA0;* &#xA0; &#x53C2;&#x6570;:value &#xA0;&#x6307;&#x5B9A;&#x5207;&#x5165;&#x70B9;&#x8868;&#x8FBE;&#x5F0F;
&#xA0; &#xA0; &#xA0;*
&#xA0; &#xA0; &#xA0;* &#x4E1A;&#x52A1;&#x65B9;&#x6CD5;
&#xA0; &#xA0; &#xA0;* public String doSome(String name&#xFF0C; int age)
&#xA0; &#xA0; &#xA0;*/
&#xA0; &#xA0; @Before(value = "execution(public String com.bjpowernode.s01.SomeServiceImpl.*(String&#xFF0C;int))")
&#xA0; &#xA0; public void myBefore(){
&#xA0; &#xA0; &#xA0; &#xA0; System.out.println("&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x4E2D;&#x7684;&#x524D;&#x7F6E;&#x901A;&#x77E5;&#x529F;&#x80FD;&#x5B9E;&#x73B0;............");
&#xA0; &#xA0; }

&#xA0; &#xA0; @Before(value = "execution(public * com.bjpowernode.s01.SomeServiceImpl.*(..))")
&#xA0; &#xA0; public void myBefore(){
&#xA0; &#xA0; &#xA0; &#xA0; System.out.println("&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x4E2D;&#x7684;&#x524D;&#x7F6E;&#x901A;&#x77E5;&#x529F;&#x80FD;&#x5B9E;&#x73B0;............");
&#xA0; &#xA0; }

&#xA0; &#xA0; @Before(value = "execution( * com.bjpowernode.s01.*.*(..))")
&#xA0; &#xA0; public void myBefore(JoinPoint jp){
&#xA0; &#xA0; &#xA0; &#xA0; System.out.println("&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x4E2D;&#x7684;&#x524D;&#x7F6E;&#x901A;&#x77E5;&#x529F;&#x80FD;&#x5B9E;&#x73B0;............");
&#xA0; &#xA0; &#xA0; &#xA0; System.out.println("&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x7684;&#x7B7E;&#x540D;:"+jp.getSignature());
&#xA0; &#xA0; &#xA0; &#xA0; System.out.println("&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x7684;&#x53C2;&#x6570;:"+ Arrays.toString(jp.getArgs()));
&#xA0; &#xA0; }
&#xA0; &#xA0; @Before(value = "execution( * com.bjpowernode.s01..*(..))")
&#xA0; &#xA0; public void myBefore(){
&#xA0; &#xA0; &#xA0; &#xA0; System.out.println("&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x4E2D;&#x7684;&#x524D;&#x7F6E;&#x901A;&#x77E5;&#x529F;&#x80FD;&#x5B9E;&#x73B0;............");
&#xA0; &#xA0; }

&#xA0; &#xA0; @Before(value = "execution( * *(..))")
&#xA0; &#xA0; public void myBefore(){
&#xA0; &#xA0; &#xA0; &#xA0; System.out.println("&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x4E2D;&#x7684;&#x524D;&#x7F6E;&#x901A;&#x77E5;&#x529F;&#x80FD;&#x5B9E;&#x73B0;............");
&#xA0; &#xA0; }
}

AspectJ框架切换JDK动态代理和CGLib动态代理:

<!--默认是JDK动态代理,取时必须使用接口类型-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> &#xA0;
<!--设置为CGLib子类代理,可以使用接口和实现类接,记住:使用接口来接,永远不出错-->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy> &#xA0;

8、@AfterReturning后置通知:

  • 后置通知是在目标方法执行后切入切面功能,可以得到目标方法的返回值.如果目标方法的返回值是简单类型(8种基本类型+String)则不可改变.如果目标方法的返回值是引用类型则可以改变.
@Aspect
@Component
public class MyAspect {
    /**
&#xA0; &#xA0;* &#x540E;&#x7F6E;&#x901A;&#x77E5;&#x7684;&#x65B9;&#x6CD5;&#x7684;&#x89C4;&#x8303;
&#xA0; &#xA0;* 1)&#x8BBF;&#x95EE;&#x6743;&#x9650;&#x662F;public
&#xA0; &#xA0;* 2)&#x65B9;&#x6CD5;&#x6CA1;&#x6709;&#x8FD4;&#x56DE;&#x503C;void
&#xA0; &#xA0;* 3)&#x65B9;&#x6CD5;&#x540D;&#x79F0;&#x81EA;&#x5B9A;&#x4E49;
&#xA0; &#xA0;* 4)&#x65B9;&#x6CD5;&#x6709;&#x53C2;&#x6570;(&#x4E5F;&#x53EF;&#x4EE5;&#x6CA1;&#x6709;&#x53C2;&#x6570;&#xFF0C;&#x5982;&#x679C;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x6CA1;&#x6709;&#x8FD4;&#x56DE;&#x503C;&#xFF0C;&#x5219;&#x53EF;&#x4EE5;&#x5199;&#x65E0;&#x53C2;&#x7684;&#x65B9;&#x6CD5;&#xFF0C;&#x4F46;&#x4E00;&#x822C;&#x4F1A;&#x5199;&#x6709;&#x53C2;&#xFF0C;&#x8FD9;&#x6837;&#x53EF;&#x4EE5;&#x5904;&#x7406;&#x65E0;&#x53C2;&#x53EF;&#x4EE5;&#x5904;&#x7406;&#x6709;&#x53C2;)&#xFF0C;&#x8FD9;&#x4E2A;&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x7684;&#x53C2;&#x6570;&#x5C31;&#x662F;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x7684;&#x8FD4;&#x56DE;&#x503C;
&#xA0; &#xA0;* 5)&#x4F7F;&#x7528;@AfterReturning&#x6CE8;&#x89E3;&#x8868;&#x660E;&#x662F;&#x540E;&#x7F6E;&#x901A;&#x77E5;
&#xA0; &#xA0;* &#xA0; &#x53C2;&#x6570;:
&#xA0; &#xA0;* &#xA0; &#xA0; &#xA0;value:&#x6307;&#x5B9A;&#x5207;&#x5165;&#x70B9;&#x8868;&#x8FBE;&#x5F0F;
&#xA0; &#xA0;* &#xA0; &#xA0; &#xA0;returning:&#x6307;&#x5B9A;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x7684;&#x8FD4;&#x56DE;&#x503C;&#x7684;&#x540D;&#x79F0;&#xFF0C;&#x5219;&#x540D;&#x79F0;&#x5FC5;&#x987B;&#x4E0E;&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x7684;&#x53C2;&#x6570;&#x540D;&#x79F0;&#x4E00;&#x81F4;.

&#xA0; &#xA0;*/
    @AfterReturning(value = "execution(* com.bjpowernode.s02.*.*(..))"&#xFF0C;returning = "obj")
    public void myAfterReturning(Object obj){
        System.out.println("&#x540E;&#x7F6E;&#x901A;&#x77E5;&#x529F;&#x80FD;&#x5B9E;&#x73B0;..............");
        if(obj != null){
            if(obj instanceof String){
                obj = obj.toString().toUpperCase();
                System.out.println("&#x5728;&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x4E2D;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x7684;&#x8FD4;&#x56DE;&#x503C;:"+obj);
            }
            if(obj instanceof Student){
                Student stu = (Student) obj;
                stu.setName("&#x674E;&#x56DB;");
                System.out.println("&#x5728;&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x4E2D;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x7684;&#x8FD4;&#x56DE;&#x503C;:"+stu);
            }
        }
    }
}

9、环绕通知@Around:

  • 它是通过拦截目标方法的方式 ,在目标方法前后增强功能的通知,它是功能最强大的通知,一般事务使用此通知.它可以轻易的改变目标方法的返回值.
@Aspect
@Component
public class MyAspect {
    /**
&#xA0; &#xA0; &#xA0;* &#x73AF;&#x7ED5;&#x901A;&#x77E5;&#x65B9;&#x6CD5;&#x7684;&#x89C4;&#x8303;
&#xA0; &#xA0; &#xA0;* 1)&#x8BBF;&#x95EE;&#x6743;&#x9650;&#x662F;public
&#xA0; &#xA0; &#xA0;* 2)&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x6709;&#x8FD4;&#x56DE;&#x503C;&#xFF0C;&#x6B64;&#x8FD4;&#x56DE;&#x503C;&#x5C31;&#x662F;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x7684;&#x8FD4;&#x56DE;&#x503C;
&#xA0; &#xA0; &#xA0;* 3)&#x65B9;&#x6CD5;&#x540D;&#x79F0;&#x81EA;&#x5B9A;&#x4E49;
&#xA0; &#xA0; &#xA0;* 4)&#x65B9;&#x6CD5;&#x6709;&#x53C2;&#x6570;&#xFF0C;&#x6B64;&#x53C2;&#x6570;&#x5C31;&#x662F;&#x76EE;&#x6807;&#x65B9;&#x6CD5;
&#xA0; &#xA0; &#xA0;* 5)&#x56DE;&#x907F;&#x5F02;&#x5E38;Throwable
&#xA0; &#xA0; &#xA0;* 6)&#x4F7F;&#x7528;@Around&#x6CE8;&#x89E3;&#x58F0;&#x660E;&#x662F;&#x73AF;&#x7ED5;&#x901A;&#x77E5;
&#xA0; &#xA0; &#xA0;* &#xA0; &#x53C2;&#x6570;:
&#xA0; &#xA0; &#xA0;* &#xA0; &#xA0; &#xA0;value:&#x6307;&#x5B9A;&#x5207;&#x5165;&#x70B9;&#x8868;&#x8FBE;&#x5F0F;
&#xA0; &#xA0; &#xA0;*/

    @Around(value = "execution(* com.bjpowernode.s03.*.*(..))")
    public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
        //&#x524D;&#x5207;&#x529F;&#x80FD;&#x5B9E;&#x73B0;
        System.out.println("&#x73AF;&#x7ED5;&#x901A;&#x77E5;&#x4E2D;&#x7684;&#x524D;&#x7F6E;&#x529F;&#x80FD;&#x5B9E;&#x73B0;............");
        //&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x8C03;&#x7528;
        Object obj = pjp.proceed(pjp.getArgs());
        //&#x540E;&#x5207;&#x529F;&#x80FD;&#x5B9E;&#x73B0;
        System.out.println("&#x73AF;&#x7ED5;&#x901A;&#x77E5;&#x4E2D;&#x7684;&#x540E;&#x7F6E;&#x529F;&#x80FD;&#x5B9E;&#x73B0;............");
        return obj.toString().toUpperCase(); &#xA0;//&#x6539;&#x53D8;&#x4E86;&#x76EE;&#x6807;&#x65B9;&#x6CD5;&#x7684;&#x8FD4;&#x56DE;&#x503C;
    }
}

10、最终通知@After

无论目标方法是否正常执行,最终通知的代码都会被执行.

@Aspect
@Component
public class MyAspect {
    /**
     * &#x6700;&#x7EC8;&#x65B9;&#x6CD5;&#x7684;&#x89C4;&#x8303;
     * 1)&#x8BBF;&#x95EE;&#x6743;&#x9650;&#x662F;public
     * 2)&#x5207;&#x9762;&#x65B9;&#x6CD5;&#x6CA1;&#x6709;&#x8FD4;&#x56DE;&#x503C;void
     * 3)&#x65B9;&#x6CD5;&#x540D;&#x79F0;&#x81EA;&#x5B9A;&#x4E49;
     * 4)&#x65B9;&#x6CD5;&#x53EF;&#x4EE5;&#x6CA1;&#x6709;&#x53C2;&#x6570;,&#x4E5F;&#x53EF;&#x4EE5;&#x6709;,&#x5219;JoinPoint.

     * 5)&#x4F7F;&#x7528;@After&#x6CE8;&#x89E3;
     * 6)&#x53C2;&#x6570;:value:&#x6307;&#x5B9A;&#x5207;&#x5165;&#x70B9;&#x8868;&#x8FBE;&#x5F0F;
     */
    @After(value = "execution(* com.bjpowernode.s04.SomeServiceImpl.*(..))")
    public void myAfter(){
        System.out.println("&#x6700;&#x7EC8;&#x901A;&#x77E5;&#x88AB;&#x6267;&#x884C;.............");
    }
}

11、给切入点表达式起别名@Pointcut

如果多个切面切入到同一个切入点,可以使用别名简化开发。使用@Pointcut注解,创建一个空方法,此方法的名称就是别名。

@Aspect
@Component
public class MyAspect {
    /**
&#xA0; &#xA0;* &#x6700;&#x7EC8;&#x901A;&#x77E5;&#x65B9;&#x6CD5;&#x7684;&#x89C4;&#x8303;
&#xA0; &#xA0;* 1)&#x8BBF;&#x95EE;&#x6743;&#x9650;&#x662F;public
&#xA0; &#xA0;* 2)&#x65B9;&#x6CD5;&#x6CA1;&#x6709;&#x8FD4;&#x56DE;&#x503C;
&#xA0; &#xA0;* 3)&#x65B9;&#x6CD5;&#x540D;&#x79F0;&#x81EA;&#x5B9A;&#x4E49;
&#xA0; &#xA0;* 4)&#x65B9;&#x6CD5;&#x6CA1;&#x6709;&#x53C2;&#x6570;&#xFF0C;&#x5982;&#x679C;&#x6709;&#x4E5F;&#x53EA;&#x80FD;&#x662F;JoinPoint
&#xA0; &#xA0;* 5)&#x4F7F;&#x7528;@After&#x6CE8;&#x89E3;&#x8868;&#x660E;&#x662F;&#x6700;&#x7EC8;&#x901A;&#x77E5;
&#xA0; &#xA0;* &#xA0; &#x53C2;&#x6570;:
&#xA0; &#xA0;* &#xA0; &#xA0; value:&#x6307;&#x5B9A;&#x5207;&#x5165;&#x70B9;&#x8868;&#x8FBE;&#x5F0F;
&#xA0; &#xA0;*/
    @After(value = "mycut()")
    public void myAfter(){
        System.out.println("&#x6700;&#x7EC8;&#x901A;&#x77E5;&#x7684;&#x529F;&#x80FD;........");
    }

    @Before(value = "mycut()")
    public void myBefore(){
        System.out.println("&#x524D;&#x7F6E;&#x901A;&#x77E5;&#x7684;&#x529F;&#x80FD;........");
    }

    @AfterReturning(value = "mycut()"&#xFF0C;returning = "obj")
    public void myAfterReturning(Object obj){
        System.out.println("&#x540E;&#x7F6E;&#x901A;&#x77E5;&#x7684;&#x529F;&#x80FD;........");
    }
    @Around(value = "mycut()")
    public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("&#x73AF;&#x7ED5;&#x901A;&#x77E5;&#x4E2D;&#x7684;&#x524D;&#x7F6E;&#x901A;&#x77E5;&#x7684;&#x529F;&#x80FD;........");
        Object obj = pjp.proceed(pjp.getArgs());
        System.out.println("&#x73AF;&#x7ED5;&#x901A;&#x77E5;&#x4E2D;&#x7684;&#x540E;&#x7F6E;&#x901A;&#x77E5;&#x7684;&#x529F;&#x80FD;........");
        return obj;
    }

    @Pointcut(value = "execution(* com.bjpowernode.s04.*.*(..))")
    public void mycut(){}
}

Original: https://www.cnblogs.com/Burning-youth/p/16310931.html
Author: 猿头猿脑的王狗蛋
Title: 【SSM框架】Spring笔记 – AOP详解;AspectJ中四种通知的使用

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/683430/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 微信白名单获取

    公司在微信WIFI登录项目中,需要在BRAS设备上添加微信服务器的IP地址到白名单列表中,以实现用户连接热点后,能够使用微信中的功能(如:添加公众号),但不能使用其他应用进行上网操…

    技术杂谈 2023年7月11日
    093
  • idea Transparent-native-to-ascii 是否需要勾选?

    首先看一下官方对该选项的解释: 第一段是说标准的Java api是用 ISO 8859-1编码 .properties文件的,所以如果你在properties文件中可以使用转义序列…

    技术杂谈 2023年7月11日
    067
  • Lombok中关于@Data的使用解析

    public class TestB extends TestA {private String name;private int age;public TestB() {}pub…

    技术杂谈 2023年5月30日
    080
  • Linux Cgroup v1(中文翻译)(1):Control Group

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    技术杂谈 2023年7月11日
    085
  • 【主流技术】Spring Boot中的微信支付(小程序)

    前言 微信支付是企业级项目中经常使用到的功能,作为后端开发人员,完整地掌握该技术是十分有必要的。 logo 一、申请流程和步骤 图1-1 注册微信支付账号 获取微信小程序APPID…

    技术杂谈 2023年7月10日
    0120
  • ArcGIS Pro sdk判断是否多面体

    ShapeType=esriGeometryMultiPatch Original: https://www.cnblogs.com/gisoracle/p/16272237.ht…

    技术杂谈 2023年5月30日
    087
  • Go学习第二天:查看变量的类型

    方法一: %T 格式化输出%T。详情见这个例子: import "fmt" func main(){ var a = 1 fmt.Printf( "a…

    技术杂谈 2023年7月24日
    086
  • 数据结构简单话(一)线性表

    前言 逻辑结构 物理存储结构 一、顺序表 二、链表 总结 前言 本菜鸟笔者打算入门一下数据结构,在学习过程中通过自己简单话术总结相关基础知识要点,希望能帮助同样在入门的小伙伴们快速…

    技术杂谈 2023年6月21日
    063
  • Node安装与卸载命令汇总

    nvm(MAC管理node版本) 安装最新稳定版node: nvm install stable 安装指定版本: nvm install <version></v…

    技术杂谈 2023年6月21日
    088
  • SeataServer1.5.2源码学习

    Seata 包括 Server端和Client端。Seata中有三种角色:TC、TM、RM,其中,Server端就是TC,TM和RM属Client端。Client端的源码学习上一篇…

    技术杂谈 2023年7月24日
    065
  • 017 Linux 之啥是 ssh ?

    1 什么是 ssh?有什么用? (1)ssh 是一种协议 (2)ssh 服务 2 ssh 基于密匙的安全验证过程是怎样的? 3 对称加密与非对称加密区别是什么? (1)对称加密 (…

    技术杂谈 2023年7月10日
    0130
  • umeditor实现ctrl+v粘贴word图片并上传

    这种方法是servlet,编写好在web.xml里配置servlet-class和servlet-mapping即可使用 后台(服务端)java服务代码:(上传至ROOT/lqxc…

    技术杂谈 2023年5月31日
    0103
  • 软件装在D盘,实测有效

    C盘容量小,希望把所有软件都装到D盘,试过很多次,没什么作用。今天装MS全家桶的时候看到了个帖子,实测有效,Visio、Word、Excel、PowerPoint都装到了D盘原贴链…

    技术杂谈 2023年7月25日
    0160
  • AJAX 简介

    AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。 您应当具备的基础知识 在继续学习之前,您需要对下面的知识有基本的了解: HTML / XHTML CSS …

    技术杂谈 2023年5月31日
    0129
  • crash命令 —— rd

    参考: https://crash-utility.github.io/help_pages/rd.html 用法: 读取内核虚地址地址或者内核符号的值,默认16进制显示,类型为u…

    技术杂谈 2023年5月30日
    0107
  • nodejs参数的处理与用户的交互

    解析脚本参数 作为脚本或者命令行工具,一般都需要支持不同的用户参数。默认参数被保存在process.argv的数组中,如下:[ nodeBinary, script, arg0, …

    技术杂谈 2023年5月31日
    0107
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球