JAVA SE5内置了3种:
- @Override 表示当前类中的方法将覆盖父类中的方法,如果不写也不会有错,但是@Override可以起到检查作用,如方法名拼写错误,编译器就会报警告信息。
- @Deprecated 表示被标注的方法已经被废弃了,如果使用编译器会发出警告信息。
- @SuppressWarnings 关闭不当的编译器警告信息。除非你确定编译器的警告信息是错误的,否则最好不要使用这个注解。
四种元注解是指注解的注解:
@Target:
表示该注解可以用于什么地方,可能的ElementType参数有:
CONSTRUCTOR
:构造器的声明FIELD
:域声明(包括enum
实例)LOCAL_VARIABLE
:局部变量声明METHOD
:方法声明PACKAGE
:包声明PARAMETER
:参数声明TYPE
:类、接口(包括注解类型)或enum
声明
@Retention
表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:
SOURCE
:注解将被编译器丢弃CLASS
:注解在class文件中可用,但会被VM丢弃RUNTIME
:VM将在运行期间保留注解,因此可以通过反射机制读取注解的信息
@Document
将注解包含在Javadoc中
@Inherited
允许子类继承父类中的注解
自定义 注解+拦截器 模拟权限管理框架
1.定义注解标签
package net.zicp.xiaochangwei.web.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author xiaochangwei
* 自定义权限标签
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SelfPermission {
String value() default "";
}
2.自定义拦截器
package net.zicp.xiaochangwei.web.interceptors;
import java.lang.annotation.Annotation;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.zicp.xiaochangwei.web.annotation.SelfPermission;
import net.zicp.xiaochangwei.web.common.Result;
import net.zicp.xiaochangwei.web.entity.Permission;
import net.zicp.xiaochangwei.web.entity.Role;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.Predicate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
/**
* 对有@SelfPermission标签的方法进行拦截,模拟进行权限检查
*
* @author xiaochangwei
*
*/
public class SelfPermissionInterceptor implements HandlerInterceptor {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
SelfPermission permission = getAnnotation(handlerMethod, SelfPermission.class);
if (permission != null) {
try {
return checkPermission(permission.value());
} catch (Exception e) {
Result result = new Result("120001", "没得权限", Result.Status.ERROR);
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().write(JSONObject.toJSONString(result));
return false;
}
}
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
}
public boolean checkPermission(final String permissionCode)
throws Exception {
String cachedRole = redisTemplate.opsForValue().get("role1");
if (cachedRole != null) {
System.out.println("缓存中找到权限数据");
Role jrole = JSON.parseObject(cachedRole, Role.class);
boolean result = IterableUtils.matchesAny(jrole.getPermissions(),
new Predicate<Permission>() {
public boolean evaluate(Permission p) {
return permissionCode.equals(p.getPermission());
}
});
if (!result) {
throw new Exception("没得权限");
}
return result;
} else {
System.out.println("缓存中没有找到权限数据");
return false;
}
}
private <T extends Annotation> T getAnnotation(HandlerMethod handlerMethod,
Class<T> clazz) {
T annotation = handlerMethod.getMethodAnnotation(clazz);
if (annotation != null) {
return annotation;
}
annotation = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), clazz);
return annotation;
}
}
3.配置拦截器xml
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="net.zicp.xiaochangwei.web.interceptors.SelfPermissionInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
4.自定义jsp标签在页面上使用
package net.zicp.xiaochangwei.web.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import net.zicp.xiaochangwei.web.entity.Permission;
import net.zicp.xiaochangwei.web.entity.Role;
import net.zicp.xiaochangwei.web.utils.Constant;
import net.zicp.xiaochangwei.web.utils.SpringBeanUtil;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.Predicate;
import org.springframework.data.redis.core.RedisTemplate;
import com.alibaba.fastjson.JSON;
/**
* @author 肖昌伟 E-mail:[email protected]
* @version 创建时间:2016年9月18日 上午11:45:06
*
*/
public class HasPermissionTag extends TagSupport {
private static final long serialVersionUID = 1L;
private RedisTemplate<String, String> redisTemplate;
String name = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int doStartTag() throws JspException {
try {
return isPermitted();
} catch (Exception e) {
e.printStackTrace();
}
return TagSupport.SKIP_BODY;
}
public int isPermitted() throws Exception{
String p = getName();
boolean show = checkPermission(p);
if (show) {
return TagSupport.EVAL_BODY_INCLUDE;
} else {
return TagSupport.SKIP_BODY;
}
}
@SuppressWarnings("unchecked")
public boolean checkPermission(final String permissionCode)
throws Exception {
redisTemplate = (RedisTemplate<String, String>) SpringBeanUtil.getBean("redisCache");
String cachedRole = redisTemplate.opsForValue().get(Constant.ROLE+"1");
if (cachedRole != null) {
System.out.println("缓存中找到权限数据");
Role jrole = JSON.parseObject(cachedRole, Role.class);
boolean result = IterableUtils.matchesAny(jrole.getPermissions(),
new Predicate<Permission>() {
public boolean evaluate(Permission p) {
return permissionCode.equals(p.getPermission());
}
});
if (!result) {
throw new Exception("没得权限");
}
return result;
} else {
System.out.println("缓存中没有找到权限数据");
return false;
}
}
}
5.定义tld文件,直接放在WEB-INF下即可,其它路径请在web.xml中配置
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>权限自定义标签库</description>
<tlib-version>1.0</tlib-version>
<short-name>PermissionTagLibrary</short-name>
<uri>http://xiaochangwei.com/tags</uri>
<tag>
<description>这个标签的作用是用来判断有没有权限</description>
<name>hasPermission</name>
<!-- 标签对应的处理器类-->
<tag-class>net.zicp.xiaochangwei.web.tag.HasPermissionTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>name</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
6.页面的使用
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://xiaochangwei.com/tags" prefix="permission" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<link rel="shortcut icon" href="/favicon.ico" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>网站首页</title>
</head>
<body>
<permission:hasPermission name="viewInfo">有权限<br/><br/></permission:hasPermission>
自定义注解处理器
1.自定义一个AbstractProcessor 实现类
package common.Annotation;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("com.suyun.aopermission.annotation.CompileAnnotation")
public class AnnotationCompileProcessor extends AbstractProcessor {
private Messager messager;
private Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
//processingEnvironment提供各种工具类 如Elements Filer Types SourceVersion等
super.init(processingEnvironment);
messager = processingEnv.getMessager();
filer = processingEnv.getFiler();
}
/**
* 扫描 评估和处理注解代码 生成Java代码
*
* @param annotations 注解类型
* @param roundEnvironment 有关当前和以前的信息环境 查询出包含特定注解的被注解元素
* @return 返回true 表示注解已声明 后续Processor不会再处理 false表示后续Processor会处理他们
*/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
messager.printMessage(Diagnostic.Kind.NOTE, "----------start----------");
for (TypeElement annotation : annotations) {
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(annotation);
for (Element element : elements) {
if (element.getKind() != ElementKind.FIELD) {
messager.printMessage(Diagnostic.Kind.ERROR, "Only FIELD can be annotated with AnnotationInfo");
return true;
}
//获取注解
CompileAnnotation annotationInfo = element.getAnnotation(CompileAnnotation.class);
//获取注解中的值
int value = annotationInfo.value();
messager.printMessage(Diagnostic.Kind.NOTE, "value: " + value);
}
}
return true;
}
}
2.在javax.annotation.processing.Processor
中定义注解处理器:
common.Annotation.AnnotationCompileProcessor
目录结构