spring boot aop 自定义注解 实现 日志检验 权限过滤
核心代码:
package com.tran.demo.aspect; import java.lang.reflect.Method;
import java.time.LocalDateTime; import javax.servlet.http.HttpServletRequest; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import com.tran.demo.annotation.AuthAnnotation;
import com.tran.demo.enums.ResultEnum;
import com.tran.demo.exception.MyException;
import com.tran.demo.model.User; @Component
@Aspect
public class MyAspect { private Logger log = LoggerFactory.getLogger(MyAspect.class); /**
* 定义切入点,切入点为com.tran.demo.controller下的所有函数
*
* // @Pointcut("@annotation(com.tran.demo.annotation.AuthAnnotation)") 对注解形式方法拦截
*/
@Pointcut("execution(public * com.tran.demo.controller..*.*(..))")
public void aspectLog(){} /**
*
* 前置通知 ,就是到达controller之前
* @param joinPoint
*/
@Before("aspectLog()")
public void doBefore(JoinPoint joinPoint){
log.info("开始执行:{}",LocalDateTime.now());
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest(); log.info("method={}", request.getMethod());
log.info("class={} and method name = {}",joinPoint.getSignature().getDeclaringTypeName(),joinPoint.getSignature().getName()); Object[] args = joinPoint.getArgs();
String[] paramNames = ((CodeSignature)joinPoint.getSignature()).getParameterNames(); for (int i = 0; i < args.length; i++) {
log.info("参数:{},值:{}",paramNames[i],args[i]);
} } /**
* HTTP请求结束时的日志
*/
@After("aspectLog()")
public void doAfter(){ log.info("结束执行:{}",LocalDateTime.now()); } /**
* 接口返回的具体内容
* @param object
*/
@AfterReturning(returning = "object",pointcut = "aspectLog()")
public void doAfterReturn(Object object){ log.info("返回数据:{}", object);
} /**
*
* 进行业务处理,判断是否有权限
*
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("aspectLog()")
public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature(); Method method = methodSignature.getMethod();
AuthAnnotation authAnnotation = method.getAnnotation(AuthAnnotation.class); if (null == authAnnotation) {
log.info("该方法不需要权限,表示没有vip权限即可访问");
return proceedingJoinPoint.proceed();
} log.info("需要的权限:{}", authAnnotation.auth());
String auth = request.getHeader("auth");
log.info("请求头匹配权限:{}",auth);
if (StringUtils.isEmpty(auth) || !auth.equals(authAnnotation.auth())) {
log.info("该请求需要权限");
throw new MyException(ResultEnum.PERMISSION_DENIED);
} return proceedingJoinPoint.proceed();
}
}
控制层(Controller):
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
private IUserService userService;
@GetMapping("/get/{userid}")
@ResponseBody
@AuthAnnotation(auth="vip")
public List<User> hello(@PathVariable Integer userid) {
Wrapper user = new EntityWrapper<User>();
user.where("userid >= {0}", 10000).and("userid <= {0}", userid);
return userService.selectList(user);
}
}
注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthAnnotation { // 非vip不能访问 user
String auth() default "vip"; }
全局异常处理:
@ControllerAdvice
@ResponseBody
public class MyAdvice { private Logger log = LoggerFactory.getLogger(MyAdvice.class); //声明要捕获的异常
@ExceptionHandler(MyException.class)
public Object defultExcepitonHandler(HttpServletRequest request,Exception e) {
log.info("进入增强异常处理:{}",LocalDateTime.now());
log.info("异常信息:{}",e.getMessage());
return e.getMessage();
}
}
这里可以多定义一些常见异常 。。。。。。。。。
枚举:
public enum ResultEnum {
UNKONW_ERROR(401,"未知错误"),
SUCCESS(200,"成功"),
ERROR(402,"失败"),
ID_NOT_IN_SCOPE(403,"id不在范围内"),
PERMISSION_DENIED(405,"权限不足"),
;
private Integer code;
private String msg;
ResultEnum(Integer code,String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
测试:

后台控制台日志:

这里需要注意的是 必须around通过之后才会走 before 注解
spring boot aop 自定义注解 实现 日志检验 权限过滤的更多相关文章
- redis分布式锁-spring boot aop+自定义注解实现分布式锁
接这这一篇redis分布式锁-java实现末尾,实现aop+自定义注解 实现分布式锁 1.为什么需要 声明式的分布式锁 编程式分布式锁每次实现都要单独实现,但业务量大功能复杂时,使用编程式分布式锁无疑 ...
- 利用Spring AOP自定义注解解决日志和签名校验
转载:http://www.cnblogs.com/shipengzhi/articles/2716004.html 一.需解决的问题 部分API有签名参数(signature),Passport首先 ...
- spring AOP自定义注解 实现日志管理
今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在appli ...
- (转)利用Spring AOP自定义注解解决日志和签名校验
一.需解决的问题 部分API有签名参数(signature),Passport首先对签名进行校验,校验通过才会执行实现方法. 第一种实现方式(Origin):在需要签名校验的接口里写校验的代码,例如: ...
- Spring Boot中自定义注解+AOP实现主备库切换
摘要: 本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需求:实现关键业务的查询监控,当用Mybatis查询数据时需要从主库切换到备库或者直接连到备库上查询,从而减小主库的 ...
- 【Spring】每个程序员都使用Spring(四)——Aop+自定义注解做日志拦截
一.前言 上一篇博客向大家介绍了Aop的概念,对切面=切点+通知 .连接点.织入.目标对象.代理(jdk动态代理和CGLIB代理)有所了解了.理论很强,实用就在这篇博客介绍. 这篇博客中,小编向大家介 ...
- spring boot通过自定义注解和AOP拦截指定的请求
一 准备工作 1.1 添加依赖 通过spring boot创建好工程后,添加如下依赖,不然工程中无法使用切面的注解,就无法对制定的方法进行拦截 <dependency> <group ...
- Spring Boot实现自定义注解
在Spring Boot项目中可以使用AOP实现自定义注解,从而实现统一.侵入性小的自定义功能. 实现自定义注解的过程也比较简单,只需要3步,下面实现一个统一打印日志的自定义注解: 1. 引入AOP依 ...
- 通过AOP自定义注解实现日志管理
前言: 通过自定义注解和AOP结合的方式,实现日志的记录功能 大致流程:项目运行->用户操作调用业务处理类->通过自定义的注解(我理解为一个切点)->进入到AOP切面类(在这里可以获 ...
随机推荐
- 陈斌python语言基础与应用00
软件改变生活:购物.餐饮.商旅出行.资料查找... Everybody in this country should learn how to program a computer...because ...
- hello.java分析
如下图源码所示: 该段代码声明了一个entity实体类,该类有一个变量name,对该变量写了对应的get和set方法.类中还有一个空的构造方法hello(). @RequestScoped用于指定一个 ...
- advanceskeleton插件分身体和表情单独绑定的时候合并表情步骤
advanceskeleton插件分身体和表情单独绑定的时候合并表情使用的代码以及合并步骤 1.身体单独绑定 2.表情单独绑定 3.合并步骤 ①原有adv表情文件删掉除了curve组以外所有东西 删除 ...
- 解题报告 『[NOI2003]逃学的小孩(树上操作)』
原题地址 今天翻看集训队巨佬写的一篇有关于树形动规的论文时看到了这道题,但感觉并不需要用动规,求出树的直径再暴力枚举一下就搞出来了. 其实是因为我太弱了,看不懂大佬在写什么orz 代码实现如下: #i ...
- 企业SQL笔试
Student(SID, Sname, Sage, Ssex) 学生表 Course(CID, Cname, TID) 课程表 SC(SID, CID, score) 成绩 ...
- Salesforce Lightning Builder Flows (Salesforce Lightning 构建Flows)
本文构建Salesforce Lightning Flows 只是一个简单的实现步骤,原文地址如下: https://trailhead.salesforce.com/en/content/learn ...
- Netty中的基本组件及关系
原文:https://blog.csdn.net/summerZBH123/article/details/79344226--------------------- 概述 这篇文章主要是用来 ...
- Combat 战斗任务
发售年份 1977 平台 VCS 开发商 雅达利(Atari) 类型 射击 https://www.youtube.com/watch?v=2LxPEdUZOkE
- GitHub Pages:静态站点托管服务(待补充)
不管是 react 还是 vue 项目路由都必须使用 hash 方式,否则页面打不开,切记!!! 如果使用的是 vue-cli 3 创建项目,那么你要在根目录创建 vue.config.js 文件,并 ...
- 使用透视表pivot_table
使用透视表pivot_table 功能:从一张大而全的表格中提取出我们需要的信息来分析 import pandas as pd unames = ['user_id', 'gender', 'age' ...