应用场景:程序需要将政务的操作记录到日志中,但程序除了政务还有其他方法,所以不可能直接在过滤器(或拦截器)里全部做过滤,手动判断类的代价太高,于是就想到自定义注释了。
一、定义注释
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<String, Object> 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; } } }