自定义注释就是一个标记,一个信息收集器,如果配合spring的aop使用,可以记录用户的操作行为。
import java.lang.annotation.elementtype;
import java.lang.annotation.retention;
import java.lang.annotation.retentionpolicy;
import java.lang.annotation.target;
/**
* 新增的用法:@audit(behaviour="新增了专题",
* value="#{args[0].colsubject}")
*
* 修改的用法:@audit(behaviour="修改了专题", id="#{args[0].colsubject.id}",
* classname="com.paul.program.colsubject.valueobject.colsubject",
* value="#{args[0].colsubject}")
*
* 删除的用法:@audit(behaviour="删除了专题", id="#{args[0].colsubject.id}"
* classname="com.paul.program.colsubject.valueobject.colsubject")
*
* @author paul
*
*/
@retention(retentionpolicy.runtime)
@target(elementtype.method)
public @interface audit {
string id() default "";
string classname() default "";
string collectionname() default "";
string value() default "";
string behaviour();
}
值对象
auditdata.java
package com.paul.common.audit;
import java.io.serializable;
import java.util.date;
import org.codehaus.jackson.annotate.jsonproperty;
import org.codehaus.jackson.map.annotate.jsonserialize;
import org.springframework.data.annotation.createdby;
import org.springframework.data.annotation.createddate;
import org.springframework.data.annotation.id;
import org.springframework.data.mongodb.core.mapping.document;
import org.springframework.data.mongodb.core.mapping.field;
import com.paul.common.util.jackson.customjsondateserializer;
@document(collection = "auditdata")
public class auditdata implements serializable{
private static final long serialversionuid = -4011585863836336249l;
@id
private string id;
@createdby
@field("userid")
@jsonproperty("userid")
private string userid;
@createddate
@field("createdate")
@jsonproperty("createdate")
@jsonserialize(using = customjsondateserializer.class)
private date createdate;
private string behaviour;
@field("newvalue")
@jsonproperty("newvalue")
private string newvalue;
@field("oldvalue")
@jsonproperty("oldvalue")
private string oldvalue;
public string getid() {
return id;
}
public void setid(string id) {
this.id = id;
}
public string getuserid() {
return userid;
}
public void setuserid(string userid) {
this.userid = userid;
}
public date getcreatedate() {
return createdate;
}
public void setcreatedate(date createdate) {
this.createdate = createdate;
}
public string getbehaviour() {
return behaviour;
}
public void setbehaviour(string behaviour) {
this.behaviour = behaviour;
}
public string getnewvalue() {
return newvalue;
}
public void setnewvalue(string newvalue) {
this.newvalue = newvalue;
}
public string getoldvalue() {
return oldvalue;
}
public void setoldvalue(string oldvalue) {
this.oldvalue = oldvalue;
}
public string tostring() {
return "auditdata [id=" id ", userid=" userid ", createdate="
createdate ", behaviour=" behaviour ", newvalue="
newvalue ", oldvalue=" oldvalue "]";
}
}
rootobject.java
package com.paul.common.audit;
public class rootobject {
private final object[] args;
private final object invokedobject;
private final object returned;
private final throwable throwned;
public rootobject(object invokedobject, object[] args, object returned, throwable throwned) {
super();
this.invokedobject = invokedobject;
this.args = args;
this.returned = returned;
this.throwned = throwned;
}
public object[] getargs() {
return args;
}
public object getinvokedobject() {
return invokedobject;
}
public object getreturned() {
return returned;
}
public throwable getthrowned() {
return throwned;
}
}
templateparsercontext.java
package com.paul.common.audit;
import org.springframework.expression.parsercontext;
public class templateparsercontext implements parsercontext {
public string getexpressionprefix() {
return "#{";
}
public string getexpressionsuffix() {
return "}";
}
public boolean istemplate() {
return true;
}
}
获取用户id
package com.paul.common.audit.aware;
import javax.servlet.http.httpservletrequest;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
import org.springframework.data.domain.auditoraware;
import org.springframework.stereotype.component;
import org.springframework.web.context.request.requestcontextholder;
import org.springframework.web.context.request.servletrequestattributes;
import com.paul.common.constant.constants;
import com.paul.program.account.valueobject.account;
@component
public class myappauditor implements auditoraware {
private static logger logger = loggerfactory.getlogger(myappauditor.class);
// get your user name here
public string getcurrentauditor() {
string result = "n/a";
try {
httpservletrequest request = ((servletrequestattributes) requestcontextholder
.getrequestattributes()).getrequest();
account account = (account)request.getsession().getattribute(constants.user_info);
result = account.getloginname();
} catch (exception e) {
logger.error(e.getmessage(), e);
}
return result;
}
}
切面
package com.paul.common.audit.interceptor;
import java.text.simpledateformat;
import java.util.arraylist;
import java.util.date;
import java.util.list;
import java.util.map;
import java.util.concurrent.concurrenthashmap;
import java.util.concurrent.timeunit;
import org.apache.commons.lang.builder.tostringbuilder;
import org.apache.commons.lang.builder.tostringstyle;
import org.aspectj.lang.proceedingjoinpoint;
import org.aspectj.lang.annotation.around;
import org.aspectj.lang.annotation.aspect;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.data.mongodb.core.mongotemplate;
import org.springframework.expression.evaluationexception;
import org.springframework.expression.expression;
import org.springframework.expression.expressionparser;
import org.springframework.expression.parseexception;
import org.springframework.expression.parsercontext;
import org.springframework.expression.spel.standard.spelexpressionparser;
import org.springframework.stereotype.component;
import com.paul.common.audit.auditdata;
import com.paul.common.audit.auditdatarequest;
import com.paul.common.audit.rootobject;
import com.paul.common.audit.templateparsercontext;
import com.paul.common.audit.annotation.audit;
import com.paul.common.audit.service.auditdataservice;
import com.paul.common.util.stringutils;
@component
@aspect
public class auditaspect {
private static logger logger = loggerfactory.getlogger(auditaspect.class);
@autowired
private auditdataservice auditdataservice;
@autowired
private mongotemplate mongotemplate;
private simpledateformat dateformatprototype = new simpledateformat("yyyy-mm-dd hh:mm:ss");
private map expressioncache = new concurrenthashmap();
private expressionparser expressionparser = new spelexpressionparser();
private parsercontext parsercontext = new templateparsercontext();
protected static void appendthrowablecauses(throwable throwable, string separator, stringbuilder toappendto) {
list alreadyappendedthrowables = new arraylist();
while (throwable != null) {
// append
toappendto.append(throwable.tostring());
alreadyappendedthrowables.add(throwable);
// cause
throwable cause = throwable.getcause();
if (cause == null || alreadyappendedthrowables.contains(cause)) {
break;
} else {
throwable = cause;
toappendto.append(separator);
}
}
}
private string getvaluebyel(string template, object invokedobject, object[] args, object returned, throwable throwned)
{
string result = "n/a";
if(stringutils.isblank(template))
return result;
try {
expression expression = expressioncache.get(template);
if (expression == null) {
expression = expressionparser.parseexpression(template, parsercontext);
expressioncache.put(template, expression);
}
object evaluatedmessage = expression.getvalue(new rootobject(invokedobject, args, returned, throwned), object.class);
result = evaluatedmessage.tostring();
} catch (parseexception e) {
logger.error(e.getmessage(), e);
} catch (evaluationexception e) {
logger.error(e.getmessage(), e);
}
return result;
}
protected auditdata buildauditdata(audit auditannotation, object invokedobject, object[] args, object returned, throwable throwned, long durationinnanos) {
auditdata auditdata = new auditdata();
auditdata.setbehaviour(auditannotation.behaviour());
string id = this.getvaluebyel(auditannotation.id(), invokedobject, args, returned, throwned);
auditdata.setoldvalue(this.getoldvaluetostring(id, auditannotation.classname()));
try {
string newvalue = this.getvaluebyel(auditannotation.value(), invokedobject, args, returned, throwned);
auditdata.setnewvalue(newvalue);
stringbuilder msg = new stringbuilder();
simpledateformat simpledateformat = (simpledateformat) dateformatprototype.clone();
msg.append(simpledateformat.format(new date()));
// auditdata.setcreatedate(simpledateformat.format(new date()));
msg.append(" ").append(newvalue);
if (throwned != null) {
msg.append(" threw '");
appendthrowablecauses(throwned, ", ", msg);
msg.append("'");
}
msg.append(" by ");
string user = this.getuser();
if (user == null) {
user = "anonymous";
}
msg.append(" in ") .append(timeunit.milliseconds.convert(durationinnanos, timeunit.nanoseconds)).append(" ms");
return auditdata;
} catch (exception e) {
/*stringbuilder msg = new stringbuilder("exception evaluating template '" template "': ");
appendthrowablecauses(e, ", ", msg);*/
return auditdata;
}
}
private string getoldvaluetostring(/*proceedingjoinpoint proceedingjoinpoint,*/ string id, string classname)
{
string result = "n/a";
/*string id = "5385be613d2a47eec07c53d4";
try {
methodsignature methodsig = (methodsignature) proceedingjoinpoint.getsignature();
object target = proceedingjoinpoint.gettarget();
object newvalue = proceedingjoinpoint.getargs()[0];
string findmethodname = "findone";
object oldvalue=null;
method findmethod = target.getclass().getdeclaredmethod(findmethodname, (class[])null);
oldvalue = findmethod.invoke(target, (object[]) null);
} catch (exception e) {
logger.error(e.getmessage(), e);
}*/
if(stringutils.isblank(id) || stringutils.isblank(classname))
return result;
try {
object object = mongotemplate.findbyid(id, class.forname(classname));
result = tostringbuilder.reflectiontostring(object, tostringstyle.short_prefix_style);
} catch (exception e) {
logger.error(e.getmessage(), e);
}
return result;
}
// @around("execution(* com.paul..**.repository..*(..))")
@around("@annotation(auditannotation)")
public object aroundadvice(proceedingjoinpoint proceedingjoinpoint, audit auditannotation) throws throwable {
boolean ok = false;
object o = null;
auditdata auditdata = null;
try
{
auditdata = buildauditdata(auditannotation, proceedingjoinpoint.getthis(),
proceedingjoinpoint.getargs(),
o, null, 10);
o = proceedingjoinpoint.proceed();
ok = true;
return o;
}
finally
{
if (ok)
{
// string value = (messageformat.format(auditannotation.value(), proceedingjoinpoint.getargs()));
try
{
auditdatarequest auditdatarequest = new auditdatarequest();
auditdatarequest.setauditdata(auditdata);
auditdataservice.addauditdata(auditdatarequest);
logger.info(auditdata "");
}
catch (exception e)
{
logger.error(e.getmessage(), e);
}
}
}
}
private string getuser()
{
return "paul";
}
}
保存至数据库
package com.paul.common.audit.service;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.data.domain.page;
import org.springframework.stereotype.service;
import com.paul.common.audit.auditdata;
import com.paul.common.audit.auditdatarequest;
import com.paul.common.audit.annotation.audit;
import com.paul.common.audit.repository.auditdatarepository;
import com.paul.program.colsubject.valueobject.colsubjectrequest;
@service
public class auditdataservice {
@autowired
private auditdatarepository auditdatarepository;
// @audited(message = "save(#{args[0].name}, #{args[0].email}): #{returned?.id}")
@audit(behaviour="修改了审计", id="#{args[0].colsubject.id}",
classname="com.paul.program.colsubject.valueobject.colsubject",
value="#{args[0].colsubject}")
public void saveobject(colsubjectrequest colsubjectrequest)
{
}
@audit(behaviour="删除了专题", id="#{args[0]}",
classname="com.paul.program.subject.valueobject.subject")
public void delete(string id) {
}
@audit(behaviour="新增了专题", value="#{args[0].colsubject}")
public void add(colsubjectrequest colsubjectrequest) {
}
public auditdata addauditdata(auditdatarequest auditdatarequest)
{
return auditdatarepository.save(auditdatarequest.getauditdata());
}
public page
findall(auditdatarequest auditdatarequest)
{
page page = auditdatarepository.findall(auditdatarequest.getpageable());
return page;
}
}
dao
package com.paul.common.audit.repository;
import org.springframework.data.repository.pagingandsortingrepository;
import com.paul.common.audit.auditdata;
/**
* 审计
*
*/
public interface auditdatarepository
extends pagingandsortingrepository
{
}
]]>