Spring之@Aspect中通知的5种方式详解

目录
  • @Before:前置通知
    • 案例
    • 对应的通知类
  • 通知中获取被调方法信息
    • JoinPoint:连接点信息
    • ProceedingJoinPoint:环绕通知连接点信息
    • Signature:连接点签名信息
  • @Around:环绕通知
    • 介绍
    • 特点
    • 案例
    • 对应的通知类
  • @After:后置通知
    • 介绍
    • 特点
    • 对应的通知类
  • @AfterReturning:返回通知
    • 用法
    • 特点
    • 案例
    • 对应的通知类
  • @AfterThrowing:异常通知
    • 用法
    • 特点
    • 案例
    • 对应的通知类
  • 几种通知对比

@Aspect中有5种通知

  • @Before:前置通知, 在方法执行之前执行
  • @Aroud:环绕通知, 围绕着方法执行
  • @After:后置通知, 在方法执行之后执行
  • @AfterReturning:返回通知, 在方法返回结果之后执行
  • @AfterThrowing:异常通知, 在方法抛出异常之后

这几种通知用起来都比较简单,都是通过注解的方式,将这些注解标注在@Aspect类的方法上,这些方法就会对目标方法进行拦截,下面我们一个个来看一下。

@Before:前置通知

介绍

定义一个前置通知

@Aspect
public class BeforeAspect {

    @Before("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void before(JoinPoint joinPoint) {
        System.out.println("我是前置通知!");
    }
}
  • 类上需要使用@Aspect标注
  • 任意方法上使用@Before标注,将这个方法作为前置通知,目标方法被调用之前,会自动回调这个方法
  • @Before标注的方法参数可以为空,或者为JoinPoint类型,当为JoinPoint类型时,必须为第一个参数
  • @Before标注的方法名称可以随意命名,符合java规范就可以,其他通知也类似

@Before中value的值为切入点表达式,也可以采用引用的方式指定切入点,如:

package com.javacode2018.aop.demo10.test1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class BeforeAspect {

    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @Before("com.javacode2018.aop.demo10.test1.BeforeAspect.pc()")
    public void before(JoinPoint joinPoint) {
        System.out.println("我是前置通知!");
    }
}

此时,before方法上面的切入引用了pc方法上面的@Pointcut的值

案例

来个普通的service

package com.javacode2018.aop.demo10.test1;

public class Service1 {
    public String say(String name) {
        return "你好:" + name;
    }

    public String work(String name) {
        return "开始工作了:" + name;
    }
}

给上面的类定义一个前置通知,Service1中的所有方法执行执行,输出一段文字我是前置通知!

package com.javacode2018.aop.demo10.test1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class BeforeAspect1 {

    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @Before("com.javacode2018.aop.demo10.test1.BeforeAspect1.pc()")
    public void before(JoinPoint joinPoint) {
        System.out.println("我是前置通知!");
    }
}

测试代码

package com.javacode2018.aop.demo10;

import com.javacode2018.aop.demo10.test1.BeforeAspect1;
import com.javacode2018.aop.demo10.test1.Service1;
import org.junit.Test;
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;

public class AopTest10 {

    @Test
    public void test1() {
        Service1 target = new Service1();
        Class<BeforeAspect1> aspectClass = BeforeAspect1.class;
        AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
        proxyFactory.setTarget(target);
        proxyFactory.addAspect(aspectClass);
        Service1 proxy = proxyFactory.getProxy();
        System.out.println(proxy.say("路人"));
        System.out.println(proxy.work("路人"));
    }
}

运行输出

我是前置通知!
你好:路人
我是前置通知!
开始工作了:路人

对应的通知类

@Before通知最后会被解析为下面这个通知类

org.springframework.aop.aspectj.AspectJMethodBeforeAdvice

通知中获取被调方法信息

通知中如果想获取被调用方法的信息,分2种情况

  • 非环绕通知,可以将org.aspectj.lang.JoinPoint作为通知方法的第1个参数,通过这个参数获取被调用方法的信息
  • 如果是环绕通知,可以将org.aspectj.lang.ProceedingJoinPoint作为方法的第1个参数,通过这个参数获取被调用方法的信息

JoinPoint:连接点信息

org.aspectj.lang.JoinPoint

提供访问当前被通知方法的目标对象、代理对象、方法参数等数据:

package org.aspectj.lang;
import org.aspectj.lang.reflect.SourceLocation;

public interface JoinPoint {
    String toString();         //连接点所在位置的相关信息
    String toShortString();     //连接点所在位置的简短相关信息
    String toLongString();     //连接点所在位置的全部相关信息
    Object getThis();         //返回AOP代理对象
    Object getTarget();       //返回目标对象
    Object[] getArgs();       //返回被通知方法参数列表,也就是目前调用目标方法传入的参数
    Signature getSignature();  //返回当前连接点签名,这个可以用来获取目标方法的详细信息,如方法Method对象等
    SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置
    String getKind();        //连接点类型
    StaticPart getStaticPart(); //返回连接点静态部分
} 

ProceedingJoinPoint:环绕通知连接点信息

用于环绕通知,内部主要关注2个方法,一个有参的,一个无参的,用来继续执行拦截器链上的下一个通知。

package org.aspectj.lang;
import org.aspectj.runtime.internal.AroundClosure;

public interface ProceedingJoinPoint extends JoinPoint {

    /**
     * 继续执行下一个通知或者目标方法的调用
     */
    public Object proceed() throws Throwable;

    /**
     * 继续执行下一个通知或者目标方法的调用
     */
    public Object proceed(Object[] args) throws Throwable;

}

Signature:连接点签名信息

注意JoinPoint#getSignature()这个方法,用来获取连接点的签名信息,这个比较重要

Signature getSignature();

通常情况,spring中的aop都是用来对方法进行拦截,所以通常情况下连接点都是一个具体的方法,Signature有个子接口

org.aspectj.lang.reflect.MethodSignature

JoinPoint#getSignature()都可以转换转换为MethodSignature类型,然后可以通过这个接口提供的一些方法来获取被调用的方法的详细信息。

下面对上面的前置通知的案例改造一下,获取被调用方法的详细信息,新建一个Aspect类:BeforeAspect2

package com.javacode2018.aop.demo10.test2;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;

@Aspect
public class BeforeAspect2 {

    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @Before("com.javacode2018.aop.demo10.test2.BeforeAspect2.pc()")
    public void before(JoinPoint joinPoint) {
        //获取连接点签名
        Signature signature = joinPoint.getSignature();
        //将其转换为方法签名
        MethodSignature methodSignature = (MethodSignature) signature;
        //通过方法签名获取被调用的目标方法
        Method method = methodSignature.getMethod();
        //输出方法信息
        System.out.println(method);
    }
}

测试用例

@Test
public void test2() {
    Service1 target = new Service1();
    Class<BeforeAspect2> aspectClass = BeforeAspect2.class;
    AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
    proxyFactory.setTarget(target);
    proxyFactory.addAspect(aspectClass);
    Service1 proxy = proxyFactory.getProxy();
    System.out.println(proxy.say("路人"));
    System.out.println(proxy.work("路人"));
}

运行输出

public java.lang.String com.javacode2018.aop.demo10.test1.Service1.say(java.lang.String)
你好:路人
public java.lang.String com.javacode2018.aop.demo10.test1.Service1.work(java.lang.String)
开始工作了:路人

@Around:环绕通知

介绍

环绕通知会包裹目标目标方法的执行,可以在通知内部调用ProceedingJoinPoint.process方法继续执行下一个拦截器。

用起来和@Before类似,但是有2点不一样

若需要获取目标方法的信息,需要将ProceedingJoinPoint作为第一个参数

通常使用Object类型作为方法的返回值,返回值也可以为void

特点

环绕通知比较特殊,其他4种类型的通知都可以用环绕通知来实现。

案例

通过环绕通知来统计方法的耗时。

package com.javacode2018.aop.demo10.test3;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;

@Aspect
public class AroundAspect3 {

    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @Around("com.javacode2018.aop.demo10.test3.AroundAspect3.pc()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取连接点签名
        Signature signature = joinPoint.getSignature();
        //将其转换为方法签名
        MethodSignature methodSignature = (MethodSignature) signature;
        //通过方法签名获取被调用的目标方法
        Method method = methodSignature.getMethod();

        long startTime = System.nanoTime();
        //调用proceed方法,继续调用下一个通知
        Object returnVal = joinPoint.proceed();
        long endTime = System.nanoTime();
        long costTime = endTime - startTime;
        //输出方法信息
        System.out.println(String.format("%s,耗时(纳秒):%s", method.toString(), costTime));
        //返回方法的返回值
        return returnVal;
    }
}

测试用例

@Test
public void test3() {
    Service1 target = new Service1();
    Class<AroundAspect3> aspectClass = AroundAspect3.class;
    AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
    proxyFactory.setTarget(target);
    proxyFactory.addAspect(aspectClass);
    Service1 proxy = proxyFactory.getProxy();
    System.out.println(proxy.say("路人"));
    System.out.println(proxy.work("路人"));
}

运行输出

public java.lang.String com.javacode2018.aop.demo10.test1.Service1.say(java.lang.String),耗时(纳秒):19000500
你好:路人
public java.lang.String com.javacode2018.aop.demo10.test1.Service1.work(java.lang.String),耗时(纳秒):59600
开始工作了:路人

对应的通知类

@Around通知最后会被解析为下面这个通知类

org.springframework.aop.aspectj.AspectJAroundAdvice

@After:后置通知

介绍

后置通知,在方法执行之后执行,用法和前置通知类似。

特点

  • 不管目标方法是否有异常,后置通知都会执行
  • 这种通知无法获取方法返回值
  • 可以使用JoinPoint作为方法的第一个参数,用来获取连接点的信息

案例

Service1中任意方法执行完毕之后,输出一行日志。

package com.javacode2018.aop.demo10.test4;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

@Aspect
public class AfterAspect4 {

    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @After("com.javacode2018.aop.demo10.test4.AfterAspect4.pc()")
    public void after(JoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        System.out.println(String.format("%s,执行完毕!", methodSignature.getMethod()));
    }
}

测试案例

@Test
public void test4() {
    Service1 target = new Service1();
    Class<AfterAspect4> aspectClass = AfterAspect4.class;
    AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
    proxyFactory.setTarget(target);
    proxyFactory.addAspect(aspectClass);
    Service1 proxy = proxyFactory.getProxy();
    System.out.println(proxy.say("路人"));
    System.out.println(proxy.work("路人"));
}

运行输出

public java.lang.String com.javacode2018.aop.demo10.test1.Service1.say(java.lang.String),执行完毕!
你好:路人
public java.lang.String com.javacode2018.aop.demo10.test1.Service1.work(java.lang.String),执行完毕!
开始工作了:路人

对应的通知类

@After通知最后会被解析为下面这个通知类

org.springframework.aop.aspectj.AspectJAfterAdvice

这个类中有invoke方法,这个方法内部会调用被通知的方法,其内部采用try..finally的方式实现的,所以不管目标方法是否有异常,通知一定会被执行。

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    try {
        //继续执行下一个拦截器
        return mi.proceed();
    }
    finally {
        //内部通过反射调用被@After标注的方法
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
}

@AfterReturning:返回通知

用法

返回通知,在方法返回结果之后执行。

特点

  • 可以获取到方法的返回值
  • 当目标方法返回异常的时候,这个通知不会被调用,这点和@After通知是有区别的

案例

后置通知中打印出方法及返回值信息。

package com.javacode2018.aop.demo10.test5;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

@Aspect
public class AfterReturningAspect5 {
    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @AfterReturning(value = "com.javacode2018.aop.demo10.test5.AfterReturningAspect5.pc()", returning = "retVal")
    public void afterReturning(JoinPoint joinPoint, Object retVal) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        System.out.println(String.format("%s返回值:%s", methodSignature.getMethod(), retVal));
    }

}

注意@AfterReturning注解,用到了2个参数

  • value:用来指定切入点
  • returning:用来指定返回值对应方法的参数名称,返回值对应方法的第二个参数,名称为retVal

对应的通知类

@AfterReturning通知最后会被解析为下面这个通知类

org.springframework.aop.aspectj.AspectJAfterReturningAdvice

@AfterThrowing:异常通知

用法

在方法抛出异常之后会回调@AfterThrowing标注的方法。

@AfterThrowing标注的方法可以指定异常的类型,当被调用的方法触发该异常及其子类型的异常之后,会触发异常方法的回调。也可以不指定异常类型,此时会匹配所有异常。

未指定异常类型

未指定异常类型,可以匹配所有异常类型,如下

@AfterThrowing(value = "切入点")
public void afterThrowing()

指定异常类型

通过@AfterThrowingthrowing指定参数异常参数名称,我们用方法的第二个参数用来接收异常,第二个参数名称为e,下面的代码,当目标方法发生IllegalArgumentException异常及其子类型异常时,下面的方法会被回调。

@AfterThrowing(value = "com.javacode2018.aop.demo10.test6.AfterThrowingAspect6.pc()", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, IllegalArgumentException e)

特点

不论异常是否被异常通知捕获,异常还会继续向外抛出。

案例

Service1中加了login方法,用户名不是路人甲java时抛出异常。

package com.javacode2018.aop.demo10.test1;

public class Service1 {
    public String say(String name) {
        return "你好:" + name;
    }

    public String work(String name) {
        return "开始工作了:" + name;
    }

    public boolean login(String name) {
        if (!"路人甲java".equals(name)) {
            throw new IllegalArgumentException("非法访问!");
        }
        return true;
    }
}

来个异常通知

package com.javacode2018.aop.demo10.test6;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

@Aspect
public class AfterThrowingAspect6 {
    @Pointcut("execution(* com.javacode2018.aop.demo10.test1.Service1.*(..))")
    public void pc() {
    }

    @AfterThrowing(value = "com.javacode2018.aop.demo10.test6.AfterThrowingAspect6.pc()", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, IllegalArgumentException e) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        System.out.println(String.format("%s发生异常,异常信息:%s", methodSignature.getMethod(), e.getMessage()));
    }

}

测试用例

@Test
public void test6() {
    Service1 target = new Service1();
    Class<AfterThrowingAspect6> aspectClass = AfterThrowingAspect6.class;
    AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
    proxyFactory.setTarget(target);
    proxyFactory.addAspect(aspectClass);
    Service1 proxy = proxyFactory.getProxy();
    proxy.login("路人");
}

运行输出

public boolean com.javacode2018.aop.demo10.test1.Service1.login(java.lang.String)发生异常,异常信息:非法访问!
 
java.lang.IllegalArgumentException: 非法访问!
 
 at com.javacode2018.aop.demo10.test1.Service1.login(Service1.java:14)
 at com.javacode2018.aop.demo10.test1.Service1$$FastClassBySpringCGLIB$$ea03ccbe.invoke(<generated>)
 at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
 at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)

对应的通知类

@AfterThrowing通知最后会被解析为下面这个通知类

org.springframework.aop.aspectj.AspectJAfterThrowingAdvice

来看一下这个类的invoke方法,这个方法是关键

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    try {
        //继续调用下一个拦截器链
        return mi.proceed();
    }
    catch (Throwable ex) {
        //判断ex和需要不糊的异常是否匹配
        if (shouldInvokeOnThrowing(ex)) {
            //通过反射调用@AfterThrowing标注的方法
            invokeAdviceMethod(getJoinPointMatch(), null, ex);
        }
        //继续向外抛出异常
        throw ex;
    }
}

几种通知对比

通知类型 执行时间点 可获取返回值 目标方法异常时是否会执行
@Before 方法执行之前
@Around 环绕方法执行 自己控制
@After 方法执行后
@AfterReturning 方法执行后
@AfterThrowing 方法发生异常后

到此这篇关于Spring之@Aspect中通知的5种方式详解的文章就介绍到这了,更多相关Spring @Aspect通知内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2022-05-12

Spring-AOP @AspectJ进阶之如何绑定代理对象

概述 使用this()或target()可绑定被代理对象实例,在通过类实例名绑定对象时,还依然具有原来连接点匹配的功能,只不过类名是通过增强方法中同名入参的类型间接决定罢了. 这里我们通过this()来了解对象绑定的用法: 实例 代码已托管到Github-> https://github.com/yangshangwei/SpringMaster 业务类 package com.xgj.aop.spring.advisor.aspectJAdvance.bindProxyObj; import

谈谈Spring AOP中@Aspect的高级用法示例

前言 本文主要跟大家分享介绍了关于Spring AOP中@Aspect的高级用法,下面话不多说了,来随着小编一起看看详细的介绍吧. 1 切点复合运算 支持在切点定义中加入以下运算符进行复合运算: 运算符 说明 && 与运算. ! 非运算. || 或运算. 2 切点命名 一般情况下,切点是直接声明在需要增强方法处,这种切点的声明方式称为匿名切点,匿名切点只能在声明处被使用 . 如果希望在其它地方可以重用这个切点,我们可以通过 @Pointcut 注解及切面类方法来命名它. public cl

Spring声明式事务和@Aspect的拦截顺序问题的解决

在使用AbstractRoutingDataSource配置多数据源时,发现使用@aspect配置的DataSourceSwitchAspect总是在声明式事务之后执行,配置了Order依然不行,经过调研发现是由于两者的aop代理方式不一致导致. 在spring内部,是通过BeanPostProcessor(<spring 攻略>一书中翻译为,后处理器)来完成自动创建代理工作的.根据匹配规则的不同大致分为三种类别: 1.匹配Bean的名称自动创建匹配到的Bean的代理,实现类BeanNameA

基于Spring AOP @AspectJ进阶说明

@AspectJ可以使用切点函数定义切点,我们还可以使用逻辑运算符对切点进行复核运算得到复合的切点,为了在切面中重用切点,我们还可以对切点进行命名,以便在其他的地方引用定义过的切点. 当一个连接点匹配多个切点时,需要考虑织入顺序的问题,此外一个重要的问题是如何再增强中访问连接点上下文的信息. Waiter接口: package com.yyq.aspectJAdvanced; public interface Waiter { void greetTo(String name); void se

在Spring 中使用@Aspect 控制自定义注解的操作

Spring 中使用@Aspect 控制自定义注解 看这篇介绍@Aspect 1.定义系统日志注解类 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SysLog { String value() default ""; } 2.定义切面处理类 package com.kxs.common.aspect; import com.google.gso

基于spring@aspect注解的aop实现过程代码实例

@AspectJ 作为通过 Java 5 注释注释的普通的 Java 类,它指的是声明 aspects 的一种风格.通过在你的基于架构的 XML 配置文件中包含以下元素,@AspectJ 支持是可用的. 第一步:编写切面类 package com.dascom.hawk.app.web.tool; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.l

基于Spring@Autowired注解与自动装配详谈

1 配置文件的方法 我们编写spring 框架的代码时候.一直遵循是这样一个规则:所有在spring中注入的bean 都建议定义成私有的域变量.并且要配套写上 get 和 set方法. Boss 拥有 Office 和 Car 类型的两个属性: 清单 3. Boss.java package com.baobaotao; public class Boss { private Car car; private Office office; // 省略 get/setter @Override p

基于spring security实现登录注销功能过程解析

这篇文章主要介绍了基于spring security实现登录注销功能过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.引入maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependenc

springboot集成fastDfs过程代码实例

这篇文章主要介绍了springboot集成fastDfs过程代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 pom.xml 引入依赖 <dependency> <groupId>com.github.tobato</groupId> <artifactId>fastdfs-client</artifactId> <version>1.26.1-RELEASE</vers

Spring boot2.x中集成H2数据库代码实例

这篇文章主要介绍了Spring boot2.x中集成H2数据库代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在spring boot中集成 1.添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </d

Spring Boot项目维护全局json数据代码实例

这篇文章主要介绍了Spring Boot项目维护全局json数据代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 概述 过去 我们在每一个方法中处理前端发过来的请求,需要自己构造请求数据,然后通过spring 提供的@ResponseBody 强制转为JSON数据吗,实际上出现了很多重复的代码,我么亦可以通过构造一个 工具类,实现只关注需要改变的数据. 下面给出这个工具类. public class JsonMsg { private i

Springboot自动装配实现过程代码实例

创建一个简单的项目: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/PO

Spring Data Jpa实现分页和排序代码实例

之前我们学习了如何使用Jpa访问关系型数据库.通过Jpa大大简化了我们对数据库的开发工作.但是,之前的例子中我们只提到了最简单的CRUD(增删改查)操作.实际上,Spring Data Jpa对于分页以及排序的查询也有着完美的支持,接下来,我们来学习如何通过Pageable来对数据库进行分页查询. 添加maven依赖 首先我们需要引入Jpa,数据库直接使用hsqldb内存数据库就可以了: <project xmlns="http://maven.apache.org/POM/4.0.0&q

基于Python实现2种反转链表方法代码实例

题目: 反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶: 你可以迭代或递归地反转链表.你能否用两种方法解决这道题? 思路: 主要需要注意反转过程中不要丢了节点.可以使用两个指针,也可以使用三个指针. Python解法一: class Solution: def reverseList(self, head): cur, prev = head, None while

SpringBoot整合模板引擎过程代码实例

一.SpringBoot整合freemarker: 1.引入freemarker模板依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> <version>1.5.9.RELEASE</version> </dependency> 2