一、先介绍下自定义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>