- 浏览: 1526782 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (225)
- JAVA (27)
- Spring (49)
- Linux (51)
- JavaScript (8)
- Scrum (23)
- IDE (2)
- JSON (2)
- Solr (0)
- Webharvest (0)
- Hibernate (8)
- 杂谈 (3)
- Windows 7 (4)
- 持续集成 (23)
- tomcat (3)
- Android (1)
- SpringSecurity (11)
- Maven (9)
- jotm (3)
- C3P0 (1)
- Active Directory (2)
- cas (1)
- JQuery (2)
- ajax (1)
- plsql (2)
- nginx (4)
- apache (1)
- thrift (7)
- python (3)
- oracle (4)
- php (2)
- redis (1)
- fedora (1)
- windows7 (0)
- SVN (1)
- NFS (1)
- SAMBA (1)
- Atomikos (1)
- apache-poi (1)
- mysql (2)
- vncserver (1)
- mac (2)
- firefox (1)
- JIRA (1)
- p6spy (1)
- git (1)
- github (1)
- gitlab (1)
- gogs (1)
- Druid (1)
- MyBatis (1)
- docker (8)
- zabbix (1)
最新评论
-
lialatd:
您好,我用您的方法通过java api往jira系统中添加is ...
JIRA REST API ---- JAVA -
sprcen945:
可以了,是因为没加intercept-url 的拦截, 尼玛, ...
SpringSecurity3.X--Cas client 配置 -
sprcen945:
请问为什么我配了security.xml后切入点不起作用(之前 ...
SpringSecurity3.X--Cas client 配置 -
linxingyul:
根据楼主的代码 继承了WebMvcConfigurationS ...
SpringMVC4零配置--Web上下文配置【MvcConfig】 -
java_老头:
MvcConfig.java的FilterType.ANNOT ...
SpringMVC4零配置--Web上下文配置【MvcConfig】
在日常开发中经常需要在代码中加入一些记录用户操作日志的log语句,比如谁在什么时间做了什么操作,等等。
把这些对于开发人员开说无关痛痒的代码写死在业务方法中实在不是一件很舒服的事情,于是AOP应运而生。
Spring对AOP的支持有以下4种情况:
1.基于代理的AOP
2.@Aspectj
3.纯POJO
4.注入式Aspectj切面
前三种都是基于方法级的,最后一个可以精确到属性及构造器。
关于Spring对AOP的支持的详细内容,读者可以参考《Spring in Action (第二版)中文版》第四章。
我这里使用的是第三种,纯POJO的方式,这种方式仅能在spring2.0及以后的版本中使用。
ok,言归正传,还是来说一说方法级注解的日志配置方式吧,顾名思义,就是只需要在方法上增加一个注释就可以自动打印日志,所以首先需要创建一个注解,如下:
package com.hqf.common.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; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface UserOperateLog { /** * 用户操作名称 * @return 用户操作名称,默认为空串 */ String value() default ""; /** * 用户操作类型,默认类型为0<br/> * 0 - 其他操作 <br/> * 1 - 查询 <br/> * 2 - 新增 <br/> * 3 - 修改 <br/> * 4 - 删除 * @return 用户操作类型 */ int type() default 0; /** * 用户操作名称对应的key,可以通过该key值在属性文件中查找对应的value * @return key */ String key() default ""; }
这里只是抛砖引玉,读者可以根据需要建立自己的注解。
有了注解,之后就需要在方法被调用时能解析注解,这就用到了SpringAOP的通知,我这里使用MethodBeforeAdvice,就是在方法被调用前执行。关于SpringAOP的通知的详细讨论读者可以参考《Spring in Action (第二版)中文版》第四章4.2.1
package com.hqf.common.annotation; import java.io.FileInputStream; import java.io.IOException; import java.lang.reflect.Method; import java.util.Properties; import javax.annotation.PostConstruct; import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; import org.springframework.aop.MethodBeforeAdvice; import org.springframework.core.io.Resource; import org.springframework.util.Assert; import org.springframework.util.StringUtils; public class UserOperateLogAdvisor implements MethodBeforeAdvice { private Logger logger;//日志句柄 private String loggerName;//日志名称 private Properties properties;//属性文件句柄 /** * 描述 : <该方法用于初始化属性文件>. <br> *<p> 日志内容可以预先配置在配置文件中,在需要打印日志时从配置文件中找到对应的值。 这里是做扩展使用,读者可以根据实际情况进行设计 * @param propertiesFilePath * @throws IOException */ public void setPropertiesFilePath(Resource propertiesFilePath) throws IOException { if (properties == null) properties = new Properties(); properties.load(new FileInputStream(propertiesFilePath.getFile())); } /* * (non-Javadoc) * * @see * org.springframework.aop.MethodBeforeAdvice#before(java.lang.reflect.Method * , java.lang.Object[], java.lang.Object) */ public void before(Method method, Object[] args, Object target) throws Throwable { String username = "未知"; for (Object object : args) { //这里只提供一种获得操作人的方式,既从HttpSession中获取,但这要求方法参数中包含HttpSession //这里只是抛砖引玉,读者可以根据实际情况进行设计 if (object instanceof HttpSession) { username = ((HttpSession) object).getAttribute("username") == null ? "未知" : (String) ((HttpSession) object) .getAttribute("username"); } } //判断方法是否注解了UserOperateLog UserOperateLog anno = method.getAnnotation(UserOperateLog.class); if (anno == null) return; String defaultMessage = anno.value(); String methodName = target.getClass().getName() + "." + method.getName(); String desc = this.handleDescription(anno.key(), StringUtils .hasText(defaultMessage) ? defaultMessage : methodName); //装配日志信息 String logline = this.buildLogLine(username, anno.type(), desc); logger.info(logline); } /** * 构建日志行 * * @param usrname * 用户名称 * @param operateType * 操作类型 * @param description * 操作描述 * @return 日志行: username - operateType - description */ protected String buildLogLine(String username, int operateType, String description) { StringBuilder sb = new StringBuilder(); sb.append(username).append(" - ").append(operateType).append(" - ") .append(description); return sb.toString(); } /** * 获取日志内容描述,可以从消息配置文件中找到对应的信息 * * @param key * 日志内容key * @param defaultMessage * 默认的描述信息 * @return 描述信息 */ protected String handleDescription(String key, String defaultMessage) { if (properties == null) return defaultMessage; if (!StringUtils.hasText(key)) return defaultMessage; String message = properties.getProperty(key); if (!StringUtils.hasText(message)) return defaultMessage; else return message; } @PostConstruct public void init() { Assert.notNull(loggerName); logger = Logger.getLogger(loggerName); } /** * @param loggerName * the loggerName to set */ public void setLoggerName(String loggerName) { this.loggerName = loggerName; } }
为了使通知起作用,需要在spring配置文件加入如下内容:
<!-- 定义用户操作日志切入点和通知器 --> <aop:config proxy-target-class="true"> <aop:pointcut id="operatePoint" expression="@annotation(com.hqf.common.annotation.UserOperateLog)" /> <aop:advisor pointcut-ref="operatePoint" id="logAdvisor" advice-ref="userOperateLogAdvisor" /> </aop:config> <!-- 定义日志文件写入位置,需要在log4j.properties中加入名称为 useroperatorlog的日志配置--> <bean id="userOperateLogAdvisor" class="com.hqf.common.annotation.UserOperateLogAdvisor" p:loggerName="useroperatorlog" p:propertiesFilePath="classpath:messages/messages.properties"/>
ok,配置完成,在使用时只需要在方法上加入@UserOperateLog
例如:
@RequestMapping(value = "/demo/index2.do") @UserOperateLog(value="注解日志",type=1,key="annotation.log") public String handleIndex2(Model model,HttpSession session){ return "demo/list"; }
日志输出结果如下:
2010-03-04 16:01:45 useroperatorlog:68 INFO - hanqunfeng - 1 - 注解日志
注解里使用了key,这样就会从指定的配置文件中查找,如果查找到就替换掉默认的value值。
详细的代码请参考附件。
- AnnotationLog.rar (5.4 MB)
- 下载次数: 408
评论
4 楼
hanqunfeng
2013-09-24
fly_宇光十色 写道
按照你这样配置之后,启动报错啊!错误信息如下
Caused by: org.xml.sax.SAXParseException; lineNumber: 31; columnNumber: 97; 与元素类型 "bean" 相关联的属性 "p:loggerName" 的前缀 "p" 未绑定。
Caused by: org.xml.sax.SAXParseException; lineNumber: 31; columnNumber: 97; 与元素类型 "bean" 相关联的属性 "p:loggerName" 的前缀 "p" 未绑定。
提示的很清楚了,你没有配置命名空间。
xmlns:p="http://www.springframework.org/schema/p"
3 楼
fly_宇光十色
2013-09-23
按照你这样配置之后,启动报错啊!错误信息如下
Caused by: org.xml.sax.SAXParseException; lineNumber: 31; columnNumber: 97; 与元素类型 "bean" 相关联的属性 "p:loggerName" 的前缀 "p" 未绑定。
Caused by: org.xml.sax.SAXParseException; lineNumber: 31; columnNumber: 97; 与元素类型 "bean" 相关联的属性 "p:loggerName" 的前缀 "p" 未绑定。
2 楼
hanqunfeng
2011-01-25
dengquanhao 写道
引用
@RequestMapping(value = "/demo/index2.do")
@UserOperateLog(value="注解日志",type=1,key="annotation.log")
public String handleIndex2(Model model,HttpSession session){
return "demo/list";
}
@UserOperateLog(value="注解日志",type=1,key="annotation.log")
public String handleIndex2(Model model,HttpSession session){
return "demo/list";
}
请问如上的@UserOperateLog(value="注解日志",type=1,key="annotation.log")中的value或则key,type等
,我可否传入一个动态值呢?
貌似不可以。
1 楼
dengquanhao
2011-01-24
引用
@RequestMapping(value = "/demo/index2.do")
@UserOperateLog(value="注解日志",type=1,key="annotation.log")
public String handleIndex2(Model model,HttpSession session){
return "demo/list";
}
@UserOperateLog(value="注解日志",type=1,key="annotation.log")
public String handleIndex2(Model model,HttpSession session){
return "demo/list";
}
请问如上的@UserOperateLog(value="注解日志",type=1,key="annotation.log")中的value或则key,type等
,我可否传入一个动态值呢?
发表评论
-
Druid学习笔记
2016-10-07 11:55 2449官方网站:https://github.com/aliba ... -
Spring Cache注解+Redis
2015-01-15 13:36 54438Spring3.1 Cache注解 依赖jar包: ... -
Spring Cache注解+Memcached
2015-01-12 16:11 20396Spring3.1 Cache注解 依赖jar包: ... -
Spring4+Hibernate4+Atomikos3.3多数据源事务管理
2014-09-25 10:46 8338Spring3+后不再对JTOM提供支持,所以可以改用At ... -
SpringMVC4零配置--Web上下文配置【MvcConfig】
2014-09-10 18:22 73358与SpringSecurity的配置类似,spring同样 ... -
SpringMVC4零配置--SpringSecurity相关配置【SpringSecurityConfig】
2014-09-10 18:22 71921SpringSecurity的配置相对来说有些复杂,如果 ... -
SpringMVC4零配置--应用上下文配置【AppConfig】
2014-09-10 18:21 26477从spring3.0开始,Spring将JavaConfi ... -
SpringMVC4零配置--web.xml
2014-09-10 18:21 98638servlet3.0+规范后,允许servlet,filt ... -
SpringMVC4零配置
2014-09-05 19:11 89909基于Servlet3.0规范和SpringMVC4注解式配 ... -
SpringSecurity3.X--LDAP:AD配置
2014-07-08 17:08 5522前面介绍过基于本地数据库验证的方式,参考http://ha ... -
Thrift--JSClient
2013-09-26 14:45 5920thrift提供了基于jquery--ajax的客户端调用 ... -
Thrift--Spring集成ThriftServlet
2013-09-25 11:42 11083Thrift除了可以通过TCP协议访问,还可以通过HTTP ... -
Thrift转SpringHttpInvoker
2013-09-24 13:26 1732关于在spring中集成Thrift请参看:http://h ... -
Spring集成Thrift--Server AND Client
2013-09-04 20:13 13716Thrift网上有N多教程, ... -
C3P0配置实战
2012-09-04 18:34 51852C3P0: 一个开源的JDBC连接池,它实现了数据源和JN ... -
spring+jotm 多数据源事务管理(三)JNDI+Tomcat
2012-06-07 16:27 5226spring+jotm 多数据源事务管理系列 spr ... -
spring+jotm 多数据源事务管理(二)hibernate
2012-06-07 11:20 2817spring+jotm 多数据源事务管理系列 spr ... -
spring+jotm 多数据源事务管理(一)jdbc
2012-06-07 11:00 5236spring+jotm 多数据源事务管理系列 spr ... -
SpringSecurity3.X--Cas client 配置之配置session-management遇到的问题(2)
2011-10-27 14:19 2101关于“SpringSecurity3.X--Cas clien ... -
SpringSecurity3.X--Cas client 配置之配置session-management遇到的问题
2011-10-26 18:56 7869关于“SpringSecurity3.X--Cas ...
相关推荐
第八课:Spring AOP配置选项 21 一、 AOP配置annotation方式 21 (一) 搭建annotation开发环境 21 (二) aspectJ类库 22 (三) AOP的annotation实例 22 (四) AspectJ的专业术语 23 (五) 织入点语法 23 (六) Advice 24 ...
Spring.NET是一个应用程序框架,其目的是协助开发人员创建企业级的.NET应用程序。它提供了很多方面的功能,比如依赖注入、面向方面编程(AOP)、数据访问抽象及ASP.NET扩展等等。Spring.NET以Java版的Spring框架为...
而Spring Boot 是Spring 主推的基于“习惯优于配置”的原则,让你能够快速搭建应用的框架,从而使得Java EE 开发变得异常简单。 《JavaEE开发的颠覆者: Spring Boot实战》从Spring 基础、Spring MVC 基础讲起,从而...
而Spring Boot 是Spring 主推的基于“习惯优于配置”的原则,让你能够快速搭建应用的框架,从而使得Java EE 开发变得异常简单。 《JavaEE开发的颠覆者: Spring Boot实战》从Spring 基础、Spring MVC 基础讲起,从而...
而Spring Boot 是Spring 主推的基于“习惯优于配置”的原则,让你能够快速搭建应用的框架,从而使得Java EE 开发变得异常简单。 《JavaEE开发的颠覆者: Spring Boot实战》从Spring 基础、Spring MVC 基础讲起,从而...
4.9 基于注解的容器配置. 85 4.9.1 @Required.. 86 4.9.2 @Autowired和@Inject.. 86 4.9.3 使用限定符来微调基于注解的自动装配 89 4.9.4 CustomAutowireConfigurer. 94 4.9.5 @Resource.....
第3章 Spring AOP和AspectJ支持 112 3.1 启用Spring的AspectJ注解支持 113 3.1.1 问题 113 3.1.2 解决方案 113 3.1.3 工作原理 113 3.2 用AspectJ注解声明aspect 115 3.2.1 问题 115 3.2.2 解决方案...
第3章 Spring AOP和AspectJ支持 112 3.1 启用Spring的AspectJ注解支持 113 3.1.1 问题 113 3.1.2 解决方案 113 3.1.3 工作原理 113 3.2 用AspectJ注解声明aspect 115 3.2.1 问题 115 3.2.2 解决方案...
6.2使用AOP统一处理Web请求日志 9 七、 缓存支持 9 7.1注解配置与EhCache使用 9 使用Redis做集中式缓存 9 八、 其他内容 9 8.1、使用@Scheduled创建定时任务 9 8.2、使用@Async实现异步调用 9 8.3、自定义...
6.2使用AOP统一处理Web请求日志 32 6.3Spring Boot集成lombok让代码更简洁 33 七、 缓存支持 35 7.1注解配置与EhCache使用 35 7.2使用Redis集成缓存 37 八、 热部署 37 8.1 什么是热部署 37 8.2 项目演示案例...
2.commons-logging-1.1.1.jar(ASF出品的日志包,struts2 2、spring、hibernate框架使用这个日志包来支持Log4J和JDK 1.4+的日志记录) 3.common-annotations.jar(支持注解的包) 4.aspectjrt.jar(支持AOP的包) 5....
spring3.1中文参考文档,南磊翻译,现在有4章,目录如下: 第一部分 Spring framework概述.......................................................................................................................
2.commons-logging-1.1.1.jar(ASF出品的日志包,struts2 2、spring、hibernate框架使用这个日志包来支持Log4J和JDK 1.4+的日志记录) 3.common-annotations.jar(支持注解的包) 4.aspectjrt.jar(支持AOP的包) 5....
2.commons-logging-1.1.1.jar(ASF出品的日志包,struts2 2、spring、hibernate框架使用这个日志包来支持Log4J和JDK 1.4+的日志记录) 3.common-annotations.jar(支持注解的包) 4.aspectjrt.jar(支持AOP的包) 5....
2.2.3. 本地方法区(线程私有) ................................................................................................................ 23 2.2.4. 堆(Heap-线程共享)-运行时数据区 .....................