springaop属于spring的重要属性,在java中有相当广泛的用途,大家一般都接触过aop实现事务的管理,在xml里配好声明式事务,然后直接在service上直接加上相应注解即可,

今天我们来实现下SpringAOP的自定义注解,用来在前置通知中做下权限校验,有利于我们代码的解藕,提高复用性,增加代码B格;

话不多说,上代码,首先定义一个自定义注解

这里的参数我们并没有在使用,先随意定义个type,以后想使用时可以再赋值

再来看切面

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
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.AfterThrowing;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.jiubao.common.core.cache.redis.JedisUtil;
import com.jiubao.common.core.exception.MyException;
import com.jiubao.livenet.cache.JiuBaoCache;
import com.jiubao.livenet.constant.ServiceConstants;
import com.jiubao.livenet.enums.Limitsenum;
import com.jiubao.livenet.service.CustomerService;

/**
* 注解切面
* @author Administrator
*
*/
@Aspect
@Component
public class AuthorityAspect {

private static final Logger logger = LoggerFactory.getLogger(AuthorityAspect.class);

@Resource
private CustomerService customerService;

//Controller层切点
@Pointcut("execution (* com.jiubao.livenet.controller.*.*(..))")
public void controllerAspect() {}

/**
* 前置通知
* 只拦截带有Authority注解的controller方法
* @param joinPoint 切点
* @return
*/

//@org.springframework.stereotype.Controller *) 表示拦截controller方法   @annotation(Authority) 表示只拦截带此注解的方法

@Before("within(@org.springframework.stereotype.Controller *) && @annotation(Authority)")
public void doBefore(JoinPoint joinPoint) throws MyException {
  logger.info("==========执行商户权限controller前置通知===============");
    Object[] args = joinPoint.getArgs();
  HttpServletRequest request=null;
  for (int i = 0; i < args.length; i++) {
    Object object = args[i];
    if(object instanceof HttpServletRequest) {
    request=(HttpServletRequest) args[i];
    break;
   }
}
  Map<String, Object> paramMap = new HashMap<String, Object>();
  if(request ==null) {
    return;
  }

  String url = request.getRequestURI().toString(); //请求的url,注意,只有方法参数里有HttpServletRequest request才能获取到request

  /**
  * 权限控制
    */
   JedisUtil jedis = JiuBaoCache.getJedisUtil();
   String userId = jedis.getUserId(request);
   paramMap.put("uid", userId); //登录人UID
   boolean isAccess=false;
   List<Map<String, String>> userAuthlist= customerService.getUserAuth(paramMap); //查询登录人的商户角色列表
  for (int i = 0; i < userAuthlist.size(); i++) {
    if(userAuthlist.get(i).get("role")!=null) {
     String[] limitsArray = Limitsenum.limitsArray(Integer.valueOf(userAuthlist.get(i).get("role")));  //使用枚举得到此角色对应的URL数组
      for (int a = 0; a < limitsArray.length; a++) {
      if(url.contains(limitsArray[a])) {  //判断是否有,如果有则跳出
         isAccess=true;
        break;
     }
}
  if(isAccess) {
     break;
   }
  }
}

  if (!isAccess){
      throw new MyException(-1,ServiceConstants.NO_ACCESS); //无权限访问,如果没有权限直接扔出个自定义异常,在那里会用response返回给前端提示
       }
}

  //全部拦截,这样的before就是全局拦截,会拦截所有方法
  @Before("controllerAspect()")
  public void doBefore2(JoinPoint joinPoint) {
    System.out.println("==========执行全部拦截controller前置通知===============");
  }

  

  @AfterReturning(returning="rvt",pointcut="controllerAspect()") //打印所有方法的返回值
  public Object AfterExec(JoinPoint joinPoint,Object rvt){ //pointcut是对应的注解类 rvt就是方法运行完之后要返回的值
    logger.info("返回值为:" + rvt);
    return rvt;
  }

}

再看看调用过程

直接加在controller里想要限制的方法上即可

上面就是全部逻辑了,还有after和Around注解在此省略,这里要开始测试了,我几次都测不通,发现根本无效,而且

我配置文件里也有  <aop:aspectj-autoproxy proxy-target-class="true" />,不知道怎么回事,后来才发现

如果你的配置文件是这样的:

你除了在spring-mybaits.xml里要有这个外,还需要在spring-mvc.xml里有,好吧,都要加上才有效,而且别忘了头部的声明哦

顺便鄙视一下springmvc,配置文件就是麻烦

在此就完成了所有代码了,亲测是有效的

需提醒是的,当一个切面里有多个同样的注解时,会按链式分先后执行,比如上面第1个before,所有配了@Authority的方法会执行,接着执行第2个before,

而没有配@Authority的方法会直接执行第2个before,第1个由于不满足条件不会执行,这样方便我们在一个切面里写多种灵活的逻辑.

springaop由于配置灵活,复用性强,无性能损耗,在封装代码上很好用,比拦截器更方法,推荐使用

再推荐几个这方面比较好的文章:

1.https://www.cnblogs.com/jianjianyang/p/4910851.html

2.https://www.cnblogs.com/sjlian/p/7325602.html

3.https://www.cnblogs.com/mouseIT/p/5033746.html

SpringAOP的自定义注解实践的更多相关文章

  1. SpringBoot+SpringAOP+Java自定义注解+mybatis实现切库读写分离

    一.定义我们自己的切库注解类 自定义注解有几点需要注意: 1)@Target 是作用的目标,接口.方法.类.字段.包等等,具体看:ElementType 2)@Retention 是注解存在的范围,R ...

  2. springAop整合自定义注解做方法日志配置(源码在附件)

    package com.aop.log.anno; import java.lang.annotation.ElementType; import java.lang.annotation.Reten ...

  3. java自定义注解注解方法、类、属性等等【转】

    http://anole1982.iteye.com/blog/1450421 http://www.open-open.com/doc/view/51fe76de67214563b20b385320 ...

  4. JAVA自定义注解SpringAOP

    原文:https://my.oschina.net/wangnian/blog/801348 前言:Annotation(注解)是JDK5.0及以后版本引入的,它的作用就是负责注解其他注解.现在开发过 ...

  5. SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)

    转载:http://itindex.net/detail/50710-springaop-controller-service 从业近二,三年了,第一次写博客,平时做做脚手架或者架构一些基础框架然后给 ...

  6. Spring Boot系列——AOP配自定义注解的最佳实践

    AOP(Aspect Oriented Programming),即面向切面编程,是Spring框架的大杀器之一. 首先,我声明下,我不是来系统介绍什么是AOP,更不是照本宣科讲解什么是连接点.切面. ...

  7. spring --解析自定义注解SpringAOP(配合@Aspect)

    1:首先,声明自定义注解 @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface DtT ...

  8. 使用自定义注解和springAOP捕获Service层异常,并处理自定义异常

    一 自定义异常 /** * 自定义参数为null异常 */ public class NoParamsException extends Exception { //用详细信息指定一个异常 publi ...

  9. ssm+redis 如何更简洁的利用自定义注解+AOP实现redis缓存

    基于 ssm + maven + redis 使用自定义注解 利用aop基于AspectJ方式 实现redis缓存 如何能更简洁的利用aop实现redis缓存,话不多说,上demo 需求: 数据查询时 ...

随机推荐

  1. 求最大公约数和最大公倍数(Java算法)

    最大公约数(最大公因数):指某几个整数共有约数中最大的一个. 求两个整数最大公约数主要的方法: 列举法:各自列出约数,再找出最大的公约数. 素因数分解法:两数各作素因数分解,然后取出共有的项乘起来. ...

  2. “微软热爱Linux“ – 心声传遍中国

    去年十月微软CEO Satya Nadella在旧金山的活动中说 “微软热爱Linux(Microsoft loves Linux)”,这句话让诸多人感到惊喜.至此之后,您可以在众多Linux和开源的 ...

  3. Windows ->> Windows Server 2012打开管理添加“我的电脑”桌面图标途径

    Windows Server 2012打开管理添加“我的电脑”桌面图标途径 rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0

  4. Windows Server 2008 R2 /2012 修改密码策略(摘抄 原文地址 https://www.cnblogs.com/mili3/p/7799347.html)

    今天建了域环境,在添加新用户的时候,发现用简单的密码时域安全策略提示密码复杂度不够,于是我就想在域安全策略里面把密码复杂度降低一点. 问题:    在“管理工具 >> 本地安全策略 > ...

  5. 彻底解密 Spark 的 HashShuffle

    本课主题 Shuffle 是分布式系统的天敌 Spark HashShuffle介绍 Spark Consolidated HashShuffle介绍 Shuffle 是如何成为 Spark 性能杀手 ...

  6. npm ERR! path: '/usr/local/lib/node_modules/npm/node_modules/cacache/node_modules/ssri' }

    在安装appium 或者升级npm的过程中会遇到这个问题.出错时的代码提示如下: npm ERR! path /usr/local/lib/node_modules/npm/node_modules/ ...

  7. PDF文件如何转成markdown格式

    百度上根据pdf转makrdown为关键字进行搜索,结果大多数是反过来的转换,即markdown文本转PDF格式. 但是PDF转markdown的解决方案很少. 正好我工作上有这个需求,所以自己实现了 ...

  8. window下使用SetUnhandledExceptionFilter捕获让程序的崩溃(转)

    简单使用SetUnhandledExceptionFilter()函数让程序优雅崩溃 虽然是大公司的产品,QQ它还是会在我们的折腾下崩溃的,但是它总是崩溃的很优雅,还要弹出自己的对话框来结束.并且发送 ...

  9. 【转】ios 抓取 tcp/udp 包

    原文: http://useyourloaf.com/blog/2012/02/07/remote-packet-capture-for-ios-devices.html Remote Packet ...

  10. 如何实现本机Windows连接虚拟机中的CentOS

    1.确定CentOS的IP地址,命令为 ifconfig,由此可知,LinuxIP地址为 192.168.85.128 2.WIndows的IP地址为192.168.16.1, 3.保证CentOS和 ...