应用场景:程序需要将政务的操作记录到日志中,但程序除了政务还有其他方法,所以不可能直接在过滤器(或拦截器)里全部做过滤,手动判断类的代价太高,于是就想到自定义注释了。
一、定义注释import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiLog {
String desc() default "";//接口的功能说明
}
我这里主要是要对被调用的接口进行记录,还得加上说明
1.@Retention定义注解的保留策略@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
因为我们是要记录被调用的接口,所以肯定是RetentionPolicy.RUNTIME,需要用到反射
2.@Target定义注解的作用目标@Target(ElementType.TYPE) //接口、类、枚举、注解
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR) //构造函数
@Target(ElementType.LOCAL_VARIABLE) //局部变量
@Target(ElementType.ANNOTATION_TYPE) //注解
@Target(ElementType.PACKAGE) //包
这里我们选择METHOD
3.还有两个没用到的
@Document说明该注解将被包含在javadoc中
@Inherited说明子类可以继承父类中的该注解
二、调用的示例:@ApiLog(desc = "进入政务首页")
public void goverIndex(){
...
}
三、对加过注释的方法做处理
这边用的是Nutz框架,非Spring,可能看起来不大一样,主要是插入数据库操作@IocBean
public class OperationLogFilter implements ActionFilter {
@Inject
private Dao dao;
@Override
public View match(ActionContext arg0) {
// TODO Auto-generated method stub
HttpSession session = Mvcs.getHttpSession();
HttpServletRequest request = Mvcs.getReq();
try {
//nutz下获取方法参数总是返回空,所以就用循环了
Method[] methodArr = arg0.getModule().getClass()
.getDeclaredMethods();
for (Method method : methodArr) {
if (arg0.getMethod().getName().equals(method.getName())
&& method.isAnnotationPresent(ApiLog.class)) {
OperationLog log = new OperationLog();
log.setIp(ClientInfo.getIp(request));
log.setOpertionDate(new Date());
User user = (User) session.getAttribute("me");
if (user != null) {
log.setOpertionUser(user.getName());
log.setOpertionUserId(user.getId());
} else {
Manager manager = (Manager) session.getAttribute("ma");
if (manager != null) {
log.setOpertionUser(manager.getUsername());
log.setOpertionUserId(manager.getId());
}
}
//取出desc说明
log.setOpertionContent(method.getAnnotation(ApiLog.class).desc());
dao.insert(log);
}
}
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
---------------------------------------------2017-06-28 补上Spring版-----------------------------------------------------
在preHandle中if (handler.getClass().isAssignableFrom(HandlerMethod.class)) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
AppAuth appAuth = handlerMethod.getMethodAnnotation(AppAuth.class);
//请求中包含AppAuth标签,则发起验证
if(appAuth!=null){
String appKey = request.getParameter("appKey");
String appSecret = request.getParameter("appSecret");
long timestamp = Tools.parseLong(request.getParameter("timestamp"));
App app = appService.findByKeyAndSecret(appKey, appSecret, timestamp);
PrintWriter pw = null;
if(app==null){
Map map = new HashMap<>();
Result result = new Result(false, ErrorCodes.UNKNOW_ERROR, "appKey或appSecret不正确");
map.put("result", result);
Gson gson = GsonUtil.getGson();
response.setContentType("text/javascript; charset=utf-8");
pw = response.getWriter();
pw.write(gson.toJson(map));
pw.flush();
return false;
}
}
}