前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java自定义注解及应用

Java自定义注解及应用

作者头像
Java识堂
发布2019-08-13 10:32:50
1.3K0
发布2019-08-13 10:32:50
举报
文章被收录于专栏:Java识堂Java识堂

前言

注解是在jdk1.5之后引入的,极大的方便了我们编写程序,并且上文Spring中XML,注解,JavaConfig如何选择,就说了用注解和JavaConfig比较优雅,必须得用注解和JavaConfig写个小例子啊

Java目前只内置了三种标准注解

四种元注解,元注解专职负责注解其他的注解

如何在运行时获取注解的值?java在java.lang.reflect包中定义了AnnotatedElement接口,Class,Method,Field等都实现了该接口,通过该接口提供的方法,就可以获得我们需要的信息,并且该接口的方法返回的数组可以由调用方修改,而不影响返回到其他调用方的数组。

AnnotatedElement接口的一部分方法

java.lang.Class中的getDeclared**表示获取自己的东西,而get**方法表示获取自己的和父类的东西,这个接口沿用了这种命名方式

例子

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FruitName {

    // 当不指定默认值时,则必须在写注解的时候写上这个属性的值
    String value() default "";
    String alias() default "";
}
public enum Color {
    BLUE, RED, GREEN
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FruitColor {

    Color fruitColor() default Color.GREEN;
}

测试类

public class Apple {

    // 当只想给value赋值时,可以使用如下快捷方式
    // @FruitName("apple")
    // 当多个属性赋值时,必须采用key=value的形式
    @FruitName(value = "apple", alias = "iphone")
    private String name;

    @FruitColor(fruitColor = Color.RED)
    private String color;

    public static void main(String[] args) {

        Field[] fields = Apple.class.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(FruitName.class)) {
                FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);
                // fruitName is apple
                System.out.println("fruitName is " + fruitName.value());
                // alias is iphone
                System.out.println("alias is " + fruitName.alias());
            } else if (field.isAnnotationPresent(FruitColor.class)) {
                FruitColor fruitColor = (FruitColor) field.getAnnotation(FruitColor.class);
                // fruitColor is RED
                System.out.println("fruitColor is " + fruitColor.fruitColor().name());
            }
        }
    }
}

应用

自定义注解一般用在日志记录,权限管理的部分,配置动态数据源一般也会用自定义注解配合AOP来完成动态切库

写了一个自定义注解配合拦截器实现权限管理的小Demo,用的是Spring Boot框架

定义权限注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Authority {

    String value() default "admin";
}

增加拦截器

public class AuthorityInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        Authority authority = method.getAnnotation(Authority.class);
        if (authority == null) {
            // 如果注解为null, 说明不需要拦截, 直接放过
            return true;
        }
        // 这里为了方便直接传递了参数
        // 一般的做法是用户第一次登录,将信息放到session中
        // 以后每次操作时从request中获取session,从session中获取用户信息
        // 然后根据用户信息从数据库中查权限信息
        String userAuthority = httpServletRequest.getParameter("userAuthority");
        if (!userAuthority.equals("admin")) {
            // 脱离了Spring MVC的返回流程,重新编码
            httpServletResponse.setCharacterEncoding("utf-8");
            httpServletResponse.setContentType("application/json;charset=UTF-8");
            PrintWriter out = httpServletResponse.getWriter();
            out.print("没有权限");
            out.flush();
            out.close();
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}

配置拦截器

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthorityInterceptor()).addPathPatterns("/**");
    }
}

测试Controller

@RestController
public class UserController {

    // 这个是为了测试没有注解时,是否会拦截
    @RequestMapping(value = "login", method = RequestMethod.GET)
    public Map login() {
        Map<String, String> map = new HashMap<>();
        map.put("msg", "login success");
        return map;
    }

    @Authority()
    @RequestMapping(value = "queryAllProduct", method = RequestMethod.GET)
    public Map queryAllProduct() {
        Map<String, String> map = new HashMap<>();
        map.put("msg", "this is all data");
        return map;
    }
}

测试

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java识堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档