I.背景
ロギング動作を詳述する各種の動作を行うためのプロジェクトのユーザ、記録動作モジュールは、ユーザの操作を必要とし、データの記録及び他の操作IDの特定動作。
方法は、保存操作の書き込みをする場合は、その都度手動で呼び出す必要があります。善悪、リピートの多くのビジネスの動作は、春AOPは、この問題に対する良い解決策になることができ。
ユーザ操作の実装は、同じクラスではなく、各操作の説明は、そうカスタム注釈を開始点として、同一ではなく、ユーザの異なる動作命令を記録するため。
二、配置
2.1、ジャーパッケージを導入
- 春-aop.jar
- aspectjrt.jar
- aspectjweaver.jar
- aopalliance-1.0.jar
2.2、Springの設定ファイルapplicationContext.xmlを
2.2.1コンフィギュレーション・ヘッダ
xmlns:aop="http://www.springframework.org/schema/aop"
<!-- 在xsi:schemaLocation中添加 -->
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
注:追加しない場合は、==「報告されます
Javaエラー-The接頭辞」AOP「要素の」 AspectJの-自動プロキシ「バインドされていません:AOPは。
2.2.2設定に関する注記スキャンと自動プロキシAOP
<!-- 配置组件扫描功能 -->
<context:component-scan base-package="com.test"/>
<!-- 配置自动代理功能 -->
<aop:aspectj-autoproxy />
<aop:config proxy-target-class="true"></aop:config>
第三に、カスタムアノテーションを作成します
package com.test.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 品目操作日志注解
* @author zhoujin
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationLogAnno {
/** 模块 */
String module();
/** 具体操作 */
String operate();
/** 品目编号 */
String pmbh();
/** 备注说明 */
String remarks() default "";
}
注:指定しない場合、このコメントを書くために、その後の時間は、このメソッドに割り当てられなければなりませんアノテーション付きメソッド定義されたデフォルト値!
四、春AOPアスペクトクラス
package com.test.common.aop;
import java.lang.reflect.Method;
import java.util.Date;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.test.common.annotation.OperationLogAnno;
import com.test.modules.sys.entity.User;
import com.test.modules.sys.utils.UserUtils;
import com.test.modules.zxztb.entity.operationLog.OperationLog;
import com.test.modules.zxztb.service.operationLog.OperationLogService;
/**
* 品目操作日志切面类
* @author zhoujin
* @date 2018-10-23
*/
@Aspect
@Component("operationLogAspect")
public class OperationLogAspect {
private static final Logger log = LoggerFactory.getLogger(OperationLogAspect.class);
@Autowired
private OperationLogService operationLogService;
// 配置织入点(以OperationLog注解为标志)
@Pointcut("@annotation(com.test.common.annotation.OperationLogAnno)")
public void logPointCut() {
}
/**
* 后置通知 用于拦截操作,在方法返回后执行
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "logPointCut()")
public void doAfterReturn(JoinPoint joinPoint) {
handleLog(joinPoint, null);
}
/**
* 拦截异常操作,有异常时执行
* @param joinPoint
* @param e
*/
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrow(JoinPoint joinPoint, Exception e) {
handleLog(joinPoint, e);
}
private void handleLog(JoinPoint joinPoint, Exception e) {
try {
// 获得注解
OperationLogAnno controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null) {
return;
}
// 品目编号
Object pmbh = controllerLog.pmbh();
// 模块详情
Object module = controllerLog.module();
// 具体操作
Object operate = controllerLog.operate();
// 备注说明
Object remarks = controllerLog.remarks();
// 操作用户信息
User currentUser = UserUtils.getUser();
// 访问类名
String className = joinPoint.getTarget().getClass().getName();
// 访问方法名
String methodName = joinPoint.getSignature().getName();
// 保存日志
log.info("\n====================================== 保存操作日志 ======================================");
OperationLog operationLog = new OperationLog();
operationLog.setPmbh(pmbh.toString());
operationLog.setModule(module.toString());
operationLog.setOperate(operate.toString());
operationLog.setOperate(remarks.toString());
operationLog.setOperatorLoginname(currentUser.getLoginName());
operationLog.setOperatorName(currentUser.getName());
operationLog.setOperateDate(new Date());
operationLog.setClassname(className);
operationLog.setMethodname(methodName);
operationLogService.save(operationLog);
log.info("\n=====================================================================================\n");
} catch (Exception exp) {
// 记录本地异常日志
log.error("\n====================================== 异常信息通知 ======================================");
log.error("异常信息:{}", exp.getMessage());
log.error("\n====================================================================================\n");
exp.printStackTrace();
}
}
/**
* 是否存在注解,如果存在就获取
*/
private static OperationLogAnno getAnnotationLog(JoinPoint joinPoint) throws Exception {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null) {
return method.getAnnotation(OperationLogAnno.class);
}
return null;
}
}
第五には、コントローラを使用します
@ResponseBody
@RequestMapping(value = "kaiQicb")
@RequiresPermissions("zxztb:dljgKbkzt:kqcb")
@OperationLogAnno(module="控制台", operate="开启流程", pmbh="1111111")
public AjaxJson kaiQicb(String id) {
AjaxJson j = new AjaxJson();
String message = "开启流程成功";
Zfcgpmbxm zfcgpmbxm = zfcgpmbxmService.get(id);
try {
zfcgpmbxm.setFlowstatus("7");
zfcgpmbxmService.save(zfcgpmbxm);
} catch (Exception e) {
e.printStackTrace();
j.setSuccess(false);
message = "开启流程失败";
}
j.setMsg(message);
return j;
}
注:ノートのPMBHが、ここで死んで書かれている、影響はありません。しかし、現実には、パラメータID来たフロントページの値をとるべきPMBHここで、である、そしてどのようにパラメータの値に注釈はそれを得ることができることができますか?
第六は、上記ダウンロードnode2017ブログを AnnotationResolverに、あなたはフロントページには、パラメータ値を得ることができます来ました
6.1コントローラで
@OperationLogAnno(module="控制台", operate="开启流程", pmbh="#{id}")
public AjaxJson kaiQiKaiBiao(String id){
...
}
// 这样也可以
@OperationLogAnno(module="控制台", operate="开启流程", pmbh="#{pmxx.id}")
public AjaxJson kaiQiKaiBiao(Pmxx pmxx){
...
}
6.2春AOPアスペクトクラス
private void handleLog(JoinPoint joinPoint, Exception e) {
try {
// 获得注解
OperationLogAnno controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null) {
return;
}
AnnotationResolver annotationResolver = AnnotationResolver.newInstance();
// 品目编号
Object pmbh = annotationResolver.resolver(joinPoint, controllerLog.pmbh());
// 模块详情
Object module = annotationResolver.resolver(joinPoint, controllerLog.module());
// 具体操作
Object operate = annotationResolver.resolver(joinPoint, controllerLog.operate());
// 备注说明
Object remarks = annotationResolver.resolver(joinPoint, controllerLog.remarks());
// 操作用户信息
User currentUser = UserUtils.getUser();
// 访问类名
String className = joinPoint.getTarget().getClass().getName();
// 访问方法名
String methodName = joinPoint.getSignature().getName();
// 保存日志
...
} catch (Exception exp) {
exp.printStackTrace();
}
6.4 AnnotationResolverコード(から:node2017 ==「Javaは、溶液法パラメータの注釈を結合します)
package com.jeeplus.common.annotation;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
/**
* 该类的作用可以把方法上的参数绑定到注解的变量中,注解的语法#{变量名}
* 能解析类似#{user}或者#{user.id}或者{user.createBy.id}
*/
public class AnnotationResolver {
private static AnnotationResolver resolver ;
public static AnnotationResolver newInstance(){
if (resolver == null) {
return resolver = new AnnotationResolver();
}else{
return resolver;
}
}
/**
* 解析注解上的值
* @param joinPoint
* @param str 需要解析的字符串
* @return
*/
public Object resolver(JoinPoint joinPoint, String str) {
if (str == null) return null ;
Object value = null;
if (str.matches("#\\{\\D*\\}")) {// 如果name匹配上了#{},则把内容当作变量
String newStr = str.replaceAll("#\\{", "").replaceAll("\\}", "");
if (newStr.contains(".")) { // 复杂类型
try {
value = complexResolver(joinPoint, newStr);
} catch (Exception e) {
e.printStackTrace();
}
} else {
value = simpleResolver(joinPoint, newStr);
}
} else { //非变量
value = str;
}
return value;
}
private Object complexResolver(JoinPoint joinPoint, String str) throws Exception {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String[] names = methodSignature.getParameterNames();
Object[] args = joinPoint.getArgs();
String[] strs = str.split("\\.");
for (int i = 0; i < names.length; i++) {
if (strs[0].equals(names[i])) {
Object obj = args[i];
Method dmethod = obj.getClass().getDeclaredMethod(getMethodName(strs[1]), null);
Object value = dmethod.invoke(args[i]);
return getValue(value, 1, strs);
}
}
return null;
}
private Object getValue(Object obj, int index, String[] strs) {
try {
if (obj != null && index < strs.length - 1) {
Method method = obj.getClass().getDeclaredMethod(getMethodName(strs[index + 1]), null);
obj = method.invoke(obj);
getValue(obj, index + 1, strs);
}
return obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private String getMethodName(String name) {
return "get" + name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase());
}
private Object simpleResolver(JoinPoint joinPoint, String str) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String[] names = methodSignature.getParameterNames();
Object[] args = joinPoint.getArgs();
for (int i = 0; i < names.length; i++) {
if (str.equals(names[i])) {
return args[i];
}
}
return null;
}
}