spring4 - 自定义注解并使用

1、元注解(meta-annotation):

元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:

  1. @Target,
  2. @Retention,
  3. @Documented,
  4. @Inherited
1.1@Target:
作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
取值(ElementType)有:
  1. CONSTRUCTOR:用于描述构造器
  2. FIELD:用于描述域
  3. LOCAL_VARIABLE:用于描述局部变量
  4. METHOD:用于描述方法
  5. PACKAGE:用于描述包
  6. PARAMETER:用于描述参数
  7. TYPE:用于描述类、接口(包括注解类型) 或enum声明
1.2@Retention:
作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
取值(ElementType)有:
  1. SOURCE:在源文件中有效(即源文件保留)
  2. CLASS:在class文件中有效(即class保留)
  3. RUNTIME:在运行时有效(即运行时保留)
1.3@Documented::
作用:用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。
1.4@Inherited:
作用:标记注解,阐述了某个被标注的类型是被继承的。
取值(ElementType)有:
  1. SOURCE:在源文件中有效(即源文件保留)
  2. CLASS:在class文件中有效(即class保留)
  3. RUNTIME:在运行时有效(即运行时保留)

2、自定义注解

public @interface 注解名 {定义体}

/**
 * 水果供应者注解
 * @author peida
 *
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitProvider {
/**
 * 供应商编号
 * @return
 */
public int id() default -1;

/**
 * 供应商名称
 * @return
 */
public String name() default "";

/**
 * 供应商地址
 * @return
 */
public String address() default "";
}

#3、注解的使用

3.1自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation
{		
	String hello () default "hello";
	String world();
}
3.2自定义使用-标记
public class MyTest
{
    @MyAnnotation(hello = "Hello,Beijing",world = "Hello,world")
	public void output() {
	   System.out.println("method output is running ");
	}
}
3.3自定义使用-解析
public class MyReflection
{
	public static void main(String[] args) throws Exception
		{
		//1.获得要调用的类
		Class<MyTest> myTestClass = MyTest.class;
		//2.获得要调用的方法,output是要调用的方法名字,new Class[]{}为所需要的参数。空则不是这种
		Method method = myTestClass.getMethod("output", new Class[]{});
		//3.方法中是否有类型为MyAnnotation的注解
		if (method.isAnnotationPresent(MyAnnotation.class))
		{
		//4.获得注解
		MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
		//5.调用注解的内容
		System.out.println(annotation.hello());
		System.out.println(annotation.world());
		}
		System.out.println("----------------------------------");
		// 获得所有注解。必须是runtime类型的
		Annotation[] annotations = method.getAnnotations();
		for (Annotation annotation : annotations)
		{
		// 遍历所有注解的名字
		System.out.println(annotation.annotationType().getName());
		}
	}
}

实际使用:权限控制与校验

用户—角色—资源

自定义标签

@Permission({role1,role2})

权限注解 用于检查权限 规定访问权限
对目标方法进行标注@Permission(Const.ADMIN_NAME)

相当于shiro的@RequiresPermissions("/mgr/role_assign") ,指定某方法需要指定的资源访问权限【资源】/mgr/role_assign

@Permission不需要写资源参数。他的参数代表指定角色的权限【任意1即可】。

本质:无参-判断hasPermission 有参-判断hasAnyRoles

控制和使用

@Order(200) 控制AOP顺序

1.将实现类加入spring管理
2.编写切面类 PermissionAop
3.定义可以定义可重用的切点@Pointcut
4.在需要执行的切面的方法上即可【这里是无参节点】
当需要AOP操作时,相关注解内传入刚才定义的方法就可以。

@Pointcut(value = "@annotation(cn.stylefeng.guns.core.common.annotion.Permission)")
private void cutPermission() {}



@Around("cutPermission()")
public Object doPermission(ProceedingJoinPoint point) throws Throwable {
    //获得注释方法签名【方法名+形参】
    MethodSignature ms = (MethodSignature) 
    //获得方法
    point.getSignature();
    Method method = ms.getMethod();
    //获取方法上的注释
    Permission permission = method.getAnnotation(Permission.class);
    //获取注释的值
    Object[] permissions = permission.value();
    if (permissions.length == 0) {

        //检查全体角色-用户是否拥有当前请求的servlet的权限
        boolean result = check.checkAll();
        if (result) {
            return point.proceed();
        } else {
            throw new NoPermissionException();
        }

    } else {

        //检查指定角色
        boolean result = check.check(permissions);
        if (result) {
            return point.proceed();
        } else {
            throw new NoPermissionException();
        }
    }
}

5.有参案例:
有参切点定义:

@Pointcut("execution(* com.ooo.Pointcut.OperatorTest.add222(..))"+"&& args(food,name)")
   public  void  function(String food,String name){}

@Before("function(food,name)")
public void beforeMethod(JoinPoint jp,String food,String name){
    String methodName = jp.getSignature().getName();
    System.out.println("【前置通知】获取参数food:"+food);
    System.out.println("【前置通知】获取参数name:"+name);
    System.out.println("【前置通知】the method 【" + methodName + "】 begins with " + Arrays.asList(jp.getArgs()));
}

权限检查服务check的实现

1.接口定义

public interface PermissionCheckService {	
	/**
	 * 检查当前登录用户是否拥有指定的角色访问当
	 */
	boolean check(Object[] permissions);
	
	/**
	 * 检查当前登录用户是否拥有当前请求的servlet的权限
	 */
	boolean checkAll();
}

2.接口实现

  1. 获取request

  2. 获取user

  3. 获取requestURI

  4. 只判断前2/段的权限

    @Override
    public boolean checkAll() {
        HttpServletRequest request = HttpContext.getRequest();
        ShiroUser user = ShiroKit.getUser();
        if (null == user) {
            return false;
        }
        String requestURI = request.getRequestURI().replaceFirst(ConfigListener.getConf().get("contextPath"), "");
        String[] str = requestURI.split("/");
        if (str.length > 3) {
            requestURI = "/" + str[1] + "/" + str[2];
        }
        if (ShiroKit.hasPermission(requestURI)) {
            return true;
        }
        return false;
    }
    

http://localhost:8080/news/main/list.jsp

1.request.getContextPath()–>/news
2.request.getServletPath()–>/main/list.jsp
3.request.getRequestURI() -->/news/main/list.jsp

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

良之才-小良

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值