【项目总结:波士顿东南大学】使用注解和反射实现权限控制

一、先介绍下自定义Annotation类

使用@interface,与定义一个新的接口非常像:

public @interface Test

{

//可以定义成员变量,带成员变量成为元数据Annotation,不带成为标记Annotation。可以添加defult设置默认值,这样在

String name() default "zhoule";

int age();

}

定义完以后可以在程序的任何地方使用该Annotation,类似于public 、final。通常可用于修饰程序的类、方法、变量、接口等定义。


二、再介绍下提取Anntion的方法:

在java.lang.reflect包下新增了 一个AnnotatedElement接口,代表程序可以接受注释的程序元素。包括Class、Constructor、Field、Method、Package。

当一个Annotation类型被定义为运行时可见。AnnotatedElement接口是所有程序元素的父接口。所以程序通过反射获取类的AnnotatedElement对象后。就可以通过getAnnotation(Class<T> annotationClass)、Annotation[] getAnnotations()、isAnnotationPresent(Class<? extends Annotation> annotionClass),获得指定指定类型的注释、返回所有注释、判断该程序元素上是否包含指定类型注释。


JDK的注释相当简单,为源代码中添加一些特殊标记,这些特殊标记可通过反射获取,一旦程序访问到这些特殊标记后,程序就可以做出相应处理。


三、实现权限控制

1.权限注释类

package org.konghao.cms.auth;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * 只要在Controller上增加了这个方法的类,都需要进行权限的控制
 * @author Administrator
 *
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthClass {
	/**
	 * 如果value为admin就表示这个类只能超级管理员访问
	 * 如果value为login表示这个类中的方法,某些可能为相应的角色可以访问
	 * @return
	 */
	public String value() default "admin";
}

2.权限注释方法

package org.konghao.cms.auth;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * 只要在Controller上增加了这个方法的类,都需要进行权限的控制
 * @author Administrator
 *
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthClass {
	/**
	 * 如果value为admin就表示这个类只能超级管理员访问
	 * 如果value为login表示这个类中的方法,某些可能为相应的角色可以访问
	 * @return
	 */
	public String value() default "admin";
}


3、初始化系统的角色所访问的功能信息

package org.konghao.cms.auth;

import java.io.File;
import java.io.FilenameFilter;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class AuthUtil {
	/**
	 * 初始化系统的角色所访问的功能信息
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Map<String,Set<String>> initAuth(String pname) {
		try {
			Map<String,Set<String>> auths = new HashMap<String, Set<String>>();
			//通过包获取所有的类
			String[] ps = getClassByPackage(pname);
			for(String p:ps) {
				String pc = pname+"."+p.substring(0,p.lastIndexOf(".class"));//将完整类名提取
				//得到了类的class对象
				Class clz = Class.forName(pc);
				if(!clz.isAnnotationPresent(AuthClass.class)) continue;//如果类的注释不是AuthClass注释类 就终止
//				System.out.println(pc);
				//获取每个类中的方法,以此确定哪些角色可以访问哪些方法
				Method[] ms = clz.getDeclaredMethods();
				/*
				 * 遍历method来判断每个method上面是否存在相应的AuthMethd
				 * 如果存在就直接将这个方法存储到auths中,如果不存在就不存储
				 * 不存储就意味着该方法只能由超级管理员访问
				 */
				for(Method m:ms) {
					if(!m.isAnnotationPresent(AuthMethod.class)) continue;
					//如果存在就要获取这个Annotation
					AuthMethod am = m.getAnnotation(AuthMethod.class);
					String roles = am.role();
					//可能一个action可以被多个角色所访问,使用,进行分割
					String[] aRoles = roles.split(",");
					for(String role:aRoles) {
						Set<String> actions = auths.get(role);
						if(actions==null) {
							actions = new HashSet<String>();
							auths.put(role, actions);
						}
						actions.add(pc+"."+m.getName());
					}
				}
			}
			return auths;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * 根据包获取所有的类
	 * @param pname
	 * @return
	 */
	private static String[] getClassByPackage(String pname) {
		String pr = pname.replace(".", "/");
		String pp = AuthUtil.class.getClassLoader().getResource(pr).getPath();
		File file = new File(pp);
		//列出文件名
		String[] fs = file.list(new FilenameFilter() {//文件过滤器,jdk1.0,匿名类实现
			@Override
			public boolean accept(File dir, String name) {
				if(name.endsWith(".class")) return true;
				return false;
			}
		});
		return fs;
	}
	
	public static void main(String[] args) {
		System.out.println(initAuth("org.konghao.cms.controller"));
	}
}




4、初始化Servlet类

package org.konghao.cms.web;

import java.util.Map;
import java.util.Set;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.konghao.cms.auth.AuthUtil;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class InitServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	private static WebApplicationContext wc;
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		//初始化spring的工厂
		wc = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
		//初始化权限信息
		Map<String,Set<String>> auths = AuthUtil.initAuth("org.konghao.cms.controller");
		this.getServletContext().setAttribute("allAuths", auths);
		this.getServletContext().setAttribute("baseInfo", BaseInfoUtil.getInstacne().read());
		System.out.println("------------------------系统初始化成功:"+auths+"-----------------------------");
	}
	
	public static WebApplicationContext getWc() {
		return wc;
	}

}

5、在web.xml中进行配置

	<servlet>
		<servlet-name>initServlet</servlet-name>
		<servlet-class>org.konghao.cms.web.InitServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值