Shiro 等权限管理框架本质很简单,一个注解 + 拦截器就可实现
======
Java 目前只内置了三种标准注解
四种元注解,元注解专职负责注解其他的注解
如何在运行时获取注解的值?java 在 java.l
ang.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("没有权限");
评论