这里有四种类型的元注解:
1. @Documented —— 指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明的类型。如果一种声明使用Documented进行注解,这种类型的注解被作为被标注的程序成员的公共API。
2. @Target——指明该类型的注解可以注解的程序元素的范围。该元注解的取值可以为TYPE,METHOD,CONSTRUCTOR,FIELD等。如果Target元注解没有出现,那么定义的注解可以应用于程序的任何元素。
3. @Inherited——指明该注解类型被自动继承。如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行知道这个标注类型被找到,或者是查询到顶层的父类。
4.@Retention——指明了该Annotation被保留的时间长短。RetentionPolicy取值为SOURCE,CLASS,RUNTIME。
(2)使用元注解对注解进行描述
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
获取注解上的属性?获取到注解对象后,就像调用方法一样后去注解的属性
注解元素的默认值:
注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或0作为默认值是一种常用的做法。这个约束使得处理器很难表现一个元素的存在或缺失的状态,因为每个注解的声明中,所有元素都存在,并且都具有相应的值,为了绕开这个约束,我们只能定义一些特殊的值,例如空字符串或者负数,一次表示某个元素不存在,在定义注解时,这已经成为一个习惯用法。例如:
@Target(ElementType.FIELD) 15 @Retention(RetentionPolicy.RUNTIME) 16 @Documented 17 public @interface FruitProvider { 18 /** 19 * 供应商编号 20 * @return 21 */ 22 public int id() default -1; 23 24 /** 25 * 供应商名称 26 * @return 27 */ 28 public String name() default ""; 29 30 /** 31 * 供应商地址 32 * @return 33 */ 34 public String address() default "";
二、代码实现
1.作用在类上面
@Retention(RetentionPolicy.RUNTIME)// 用于反射 注解的保留范围
@Target(ElementType.TYPE) // 注解的作用目标 类方法或包
public @interface TranSName{
public String name();
public int age() default 100;
}
业务实现
@TranSName(name="ans")
public class Student {
}
public static void main(String[] args) {
Class
//sc.getAnnotation(annotationClass)
if(sc.isAnnotationPresent(TranSName.class)){// 判断此类上是否有此注解
TranSName ts = sc.getAnnotation(TranSName.class); // 获取注解对象
System.out.println(ts.name());// 读取参数
}
}
2、作用在方法上
/**
* 自定义注�?
*/
//被这个注解修饰的注解,利用反射,将其他的注解读取出来
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationLimit {
String mid(); //子模块模块名�?
String pid(); //父模块操作名�?
}
通过拦截器实现权限的控制,模仿配置文件,操作某个方法时,查看当前用户所具有的角色是否有此方法的访问权限,方法的访问权限用自定义注解的方式在方法上,
通过拦截器。do获取角色与方法权限查数据库,是否有对应的记录,,有则放行,执行方法代码。
package cn.itcast.elec.util;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.StrutsStatics;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import cn.itcast.elec.domain.ElecUser;
import cn.itcast.elec.service.IElecRoleService;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
@SuppressWarnings("serial")
public class ErrorAndLimitInterceptor extends MethodFilterInterceptor {
public void init() {
}
/**
* 过滤器过滤url�?do�?jsp�?
* 拦截器拦截url�?do�?
* actioninvocation.invoke():调用struts2的Action的方法,并返回String类型的对应的返回�?
*/
public String doIntercept(ActionInvocation actioninvocation) {
//把自定义错误信息 放置到request�?
HttpServletRequest request = (HttpServletRequest) actioninvocation
.getInvocationContext().get(StrutsStatics.HTTP_REQUEST);
try {
//获取请求的action对象
Object action = actioninvocation.getAction();
//获取请求的方法的名称
String methodName = actioninvocation.getProxy().getMethod();
//获取action中的方法的封装类(action中的方法没有参数)
Method method = action.getClass().getMethod(methodName, null);
// Action的返回�?
String result = null;
boolean flag = isCheckLimit(request,method);
//if(flag){
if(true){//去掉细颗粒权限控�?
// 运行被拦截的Action,期间如果发生异常会被catch�?
result = actioninvocation.invoke();
}
else{
request.setAttribute("errorMsg", "对不起!您没有权限操作此功能�?);
return "errorMsg";
}
return result;
} catch (Exception e) {
/**
* 处理异常
*/
String errorMsg = "出现错误信息,请查看日志�?;
//通过instanceof判断到底是什么异常类�?
if (e instanceof RuntimeException) {
//未知的运行时异常
RuntimeException re = (RuntimeException) e;
//re.printStackTrace();
errorMsg = re.getMessage().trim();
}
/**
* 发�?错误消息到页�?
*/
request.setAttribute("errorMsg", errorMsg);
/**
* log4j记录日志
*/
Log log = LogFactory
.getLog(actioninvocation.getAction().getClass());
log.error(errorMsg, e);
return "errorMsg";
}// ...end of catch
}
public void destroy() {
}
public boolean isCheckLimit(HttpServletRequest request, Method method) {
if(method == null){
return false;
}
//获取当前的登陆用�?
ElecUser elecUser = (ElecUser)request.getSession().getAttribute("globle_user");
if(elecUser == null){
return false;
}
//获取当前登陆用户的角色(�?��用户可以对应多个角色�?
Hashtable
if(ht == null){
return false;
}
//处理注解,判断方法上是否存在注解(注解的名称为:AnnotationLimit�?
/*
* 例如�?
* @AnnotationLimit(mid="aa",pid="0")
public String home(){
*/
boolean isAnnotationPresent = method.isAnnotationPresent(AnnotationLimit.class);
//不存在注解(此时不能操作该方法)
if(!isAnnotationPresent){
return false;
}
//存在注解(调用注解)
AnnotationLimit limit = method.getAnnotation(AnnotationLimit.class);
//获取注解上的�?
String mid = limit.mid(); //权限子模块名�?
String pid = limit.pid(); //权限父操作名�?
/**
* 如果登陆用户的角色id+注解上的@AnnotationLimit(mid="aa",pid="0")
* * 在elec_role_popedom表中存在 flag=true,此时可以访问Action的方�?
* * 在elec_role_popedom表中不存�?flag=false,此时不能访问Action的方�?
*/
boolean flag = false;
//从Session中获取当前登录名�?��有的权限code的集合(aa@ab@ac@ad�?
// String popedom = (String)request.getSession().getAttribute("globle_popedom");
// if(popedom.contains(mid)){
// flag = true;
// }
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
IElecRoleService elecRoleService = (IElecRoleService)wac.getBean(IElecRoleService.SERVICE_NAME);
//遍历角色ID
if(ht!=null && ht.size()>0){
for(Iterator
Entry
//获取角色ID
String roleID = entry.getKey();
flag = elecRoleService.findRolePopedomByID(roleID, mid, pid);
if(flag){
break;
}
}
}
return flag;
}
}