springboot aop的简单使用demo、RequestBody的参数只读一次的问题

在项目中遇到接口参数@RequestBody的参数需要在后面的全局异常处理器中打印出来,发现@RequestBody注解的参数是流的形式,内部的流限制为只能读取一次(inputStream的数据只能读取一次,从inputStream中读取过数据之后,后续再从inputStream中就不能再读取到数据了),解决方案采用aop面在进入方法前通过JoinPoint获取方法参数并把参数set进request,顺便总结写一个aop的demo

注:
aop切面主要有三部分组成

  1. Aspect切面类
  2. Pointcut切点
  3. @Before、@After等通知

切点配置说明
在这里插入图片描述

pom.xml添加依赖

        <!--  springboot aop依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

新建一个切面类(主要有切点和通知组成)

@Aspect
@Component
public class ControllerAspect {

    private Logger logger = LoggerFactory.getLogger(getClass());

    /*@PointCut注解表示表示横切点,哪些方法需要被横切*/
    @Pointcut("execution(* com.xinhuo.demo.web.StudentController.*(..))")
    public void pointCut() {

    }

    /**
     * 前置通知:方法调用前被调用
     * 通过JoinPoint 获取通知的签名信息,如目标方法名,目标方法参数信息等
     * 把接口中的requestMsg参数重新设置进request
     * @param joinPoint
     */
//    @Before("execution(* com.xinhuo.demo.web..*.*(..))")
    @Before("execution(* com.xinhuo.demo.web.StudentController.*(..))")
    public void beforeController(JoinPoint joinPoint){
        logger.info("aop before");
        //获取接口的参数,设置回request
        Object[] o = joinPoint.getArgs();
//        RequestMsg requestMsg = (RequestMsg) o[0];
        //获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        request.setAttribute("body",o[0]);
    }

    /**
     * 后置返回通知
     * @AfterReturning注解用于获取方法的返回值
     * @param object
     */
    @AfterReturning(pointcut = "pointCut()", returning = "object")
    public void getAfterReturn(Object object) {
        logger.info("aop afterReturning");
        logger.info("aop afterReturning返回值:{}", JSONObject.toJSONString(object));
    }

    /**
     * 后置最终通知(目标方法只要执行完了就会执行后置通知方法)
     * @After注解表示在方法执行之后执行
     */
    @After("pointCut()")
    public void after(JoinPoint joinPoint) {
        logger.info("aop after");
    }

    /**
     * 后置异常通知
     * 当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;
     */
    @AfterThrowing(value="pointCut()",throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint,Throwable exception) {
        logger.info("aop afterThrowing");
    }
}

web层

@RestController
@RequestMapping("/student")
public class StudentController {

    Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private StudentService studentService;

    /**
     * 查询学生信息
     * @param requestMsg
     * @return
     */
    @GetMapping("/find")
    public ResultMsg findStudent(@RequestBody RequestMsg requestMsg) {
        log.info("进入findStudent start");
        int sid = requestMsg.getData().getIntValue("sid");
        if(sid == 0){             
//            return ResultMsg.error(-1,"参数sid为空");
              throw new RuntimeException("参数sid为空");
        }
        Student stu = studentService.getById(sid);
        ResultMsg resultMsg = new ResultMsg();
        resultMsg.setData(stu);
        log.info("进入findStudent end");
        return resultMsg;
    }
}

测试aop的方法的通知顺序
在这里插入图片描述在这里插入图片描述
异常时的顺序
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值