spring4 - 自定义注解并使用

向右看齐 2022-02-24 05:34 307阅读 0赞

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 注解名 {定义体}

  1. /**
  2. * 水果供应者注解
  3. * @author peida
  4. *
  5. */
  6. @Target(ElementType.FIELD)
  7. @Retention(RetentionPolicy.RUNTIME)
  8. @Documented
  9. public @interface FruitProvider {
  10. /**
  11. * 供应商编号
  12. * @return
  13. */
  14. public int id() default -1;
  15. /**
  16. * 供应商名称
  17. * @return
  18. */
  19. public String name() default "";
  20. /**
  21. * 供应商地址
  22. * @return
  23. */
  24. public String address() default "";
  25. }

#3、注解的使用

3.1自定义注解

  1. @Target(ElementType.METHOD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface MyAnnotation
  4. {
  5. String hello () default "hello";
  6. String world();
  7. }

3.2自定义使用-标记

  1. public class MyTest
  2. {
  3. @MyAnnotation(hello = "Hello,Beijing",world = "Hello,world")
  4. public void output() {
  5. System.out.println("method output is running ");
  6. }
  7. }

3.3自定义使用-解析

  1. public class MyReflection
  2. {
  3. public static void main(String[] args) throws Exception
  4. {
  5. //1.获得要调用的类
  6. Class<MyTest> myTestClass = MyTest.class;
  7. //2.获得要调用的方法,output是要调用的方法名字,new Class[]{}为所需要的参数。空则不是这种
  8. Method method = myTestClass.getMethod("output", new Class[]{});
  9. //3.方法中是否有类型为MyAnnotation的注解
  10. if (method.isAnnotationPresent(MyAnnotation.class))
  11. {
  12. //4.获得注解
  13. MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
  14. //5.调用注解的内容
  15. System.out.println(annotation.hello());
  16. System.out.println(annotation.world());
  17. }
  18. System.out.println("----------------------------------");
  19. // 获得所有注解。必须是runtime类型的
  20. Annotation[] annotations = method.getAnnotations();
  21. for (Annotation annotation : annotations)
  22. {
  23. // 遍历所有注解的名字
  24. System.out.println(annotation.annotationType().getName());
  25. }
  26. }
  27. }

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

用户—角色—资源

自定义标签

@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操作时,相关注解内传入刚才定义的方法就可以。

  1. @Pointcut(value = "@annotation(cn.stylefeng.guns.core.common.annotion.Permission)")
  2. private void cutPermission() {}
  3. @Around("cutPermission()")
  4. public Object doPermission(ProceedingJoinPoint point) throws Throwable {
  5. //获得注释方法签名【方法名+形参】
  6. MethodSignature ms = (MethodSignature)
  7. //获得方法
  8. point.getSignature();
  9. Method method = ms.getMethod();
  10. //获取方法上的注释
  11. Permission permission = method.getAnnotation(Permission.class);
  12. //获取注释的值
  13. Object[] permissions = permission.value();
  14. if (permissions.length == 0) {
  15. //检查全体角色-用户是否拥有当前请求的servlet的权限
  16. boolean result = check.checkAll();
  17. if (result) {
  18. return point.proceed();
  19. } else {
  20. throw new NoPermissionException();
  21. }
  22. } else {
  23. //检查指定角色
  24. boolean result = check.check(permissions);
  25. if (result) {
  26. return point.proceed();
  27. } else {
  28. throw new NoPermissionException();
  29. }
  30. }
  31. }

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

  1. @Pointcut("execution(* com.ooo.Pointcut.OperatorTest.add222(..))"+"&& args(food,name)")
  2. public void function(String food,String name){}
  3. @Before("function(food,name)")
  4. public void beforeMethod(JoinPoint jp,String food,String name){
  5. String methodName = jp.getSignature().getName();
  6. System.out.println("【前置通知】获取参数food:"+food);
  7. System.out.println("【前置通知】获取参数name:"+name);
  8. System.out.println("【前置通知】the method 【" + methodName + "】 begins with " + Arrays.asList(jp.getArgs()));
  9. }

权限检查服务check的实现

1.接口定义

  1. public interface PermissionCheckService {
  2. /**
  3. * 检查当前登录用户是否拥有指定的角色访问当
  4. */
  5. boolean check(Object[] permissions);
  6. /**
  7. * 检查当前登录用户是否拥有当前请求的servlet的权限
  8. */
  9. boolean checkAll();
  10. }

2.接口实现

  1. 获取request
  2. 获取user
  3. 获取requestURI
  4. 只判断前2/段的权限

    1. @Override
    2. public boolean checkAll() {
    3. HttpServletRequest request = HttpContext.getRequest();
    4. ShiroUser user = ShiroKit.getUser();
    5. if (null == user) {
    6. return false;
    7. }
    8. String requestURI = request.getRequestURI().replaceFirst(ConfigListener.getConf().get("contextPath"), "");
    9. String[] str = requestURI.split("/");
    10. if (str.length > 3) {
    11. requestURI = "/" + str[1] + "/" + str[2];
    12. }
    13. if (ShiroKit.hasPermission(requestURI)) {
    14. return true;
    15. }
    16. return false;
    17. }

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

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

发表评论

表情:
评论列表 (有 0 条评论,307人围观)

还没有评论,来说两句吧...

相关阅读

    相关 spring定义注解

    编程思想:垂直化编程,就是A—B---C—D…等执行下去,一个逻辑一个逻辑完了再执行下一个,但是spring 中AOP提供了一种思想,它的作用就是,当在业务不知情的情况下,对业

    相关 spring 定义注解

    在Java中创建自定义注解 创建自定义注解与编写接口很相似,除了它的接口关键字前有个@符号。我们可以在注解中定义方法,示例如下: package com.xxx.co