业务场景:业务要求记录用户在系统的操作行为,并保存到数据库当中。
1、自定义注解,记录操作日志
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @company *********
* @description 类的方法描述注解
* @author zzg
* @create 2017-02-03==17
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MethodAction {
/**
* 方法描述
* @return
*/
public String optionDescription() default "no description";
/**
* 方法名称
* @return
*/
public String methodName() default "no method name";
}
2、切面类
package aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson.JSON;
import com.wlsq.kso.annotation.MethodAction;
import com.wlsq.kso.entity.AccountSysLog;
import com.wlsq.kso.service.AccountSysLogService;
import com.wlsq.kso.util.SpringContextUtil;
import java.lang.reflect.Method;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
public class AccountSysOptionLogAspect {
public Object doSystemLog(ProceedingJoinPoint point) throws Throwable {
// 切入方法名称
String methodName = point.getSignature().getName();
// 目标方法不为空
if (StringUtils.isNotEmpty(methodName)) {
String targetName = point.getTarget().getClass().getName();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
for (Method m : methods) {
if (m.getName().equals(methodName)) {
boolean hasAnnotation = m
.isAnnotationPresent(MethodAction.class);
if (hasAnnotation) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
//请求参数
String parame = null;
StringBuilder builder = new StringBuilder();
// 用户openId
String userOpenId = request.getParameter("userOpenId") == null ? null
: request.getParameter("userOpenId").trim();
String accessToken = request.getParameter("accessToken") == null ? null
: request.getParameter("accessToken").trim();// 用户访问令牌
String generalAccount = request.getParameter("generalAccount") == null ? null
: request.getParameter("generalAccount").trim();// 未来社区总账户
String sellerOpenId = request.getParameter("sellerOpenId") ==null ? null :request.getParameter("sellerOpenId").trim();//商户唯一编号
String consumState = request.getParameter("consumState") == null ? null
: request.getParameter("consumState").trim();// 消费状态【0:未消费,1:支付,2支付超时,订单取消
// ,3、已支付,超时需要退款】
String consumType = request.getParameter("consumType") == null ? null
: request.getParameter("consumType").trim();// 消费类型【0:普通商品,1:服务商品,2预售商品,3余额充值】
String money = request.getParameter("money") == null ? null
: request.getParameter("money").trim();// 消费金额
String orderDetail = request.getParameter("orderDetail") == null ? null
: request.getParameter("orderDetail").trim();// 订单详情
String orderNum = request.getParameter("orderNum") == null ? null
: request.getParameter("orderNum").trim();// 订单编号
String playType = request.getParameter("playType") == null ? null
: request.getParameter("playType").trim();// 支付平台类型【0:余额支付,1:微信支付,2:支付宝支付】
String plateType = request.getParameter("plateType") == null ? null
: request.getParameter("plateType").trim();// 平台类型【0:未来社区】
String sign = request.getParameter("sign") == null ? null : request
.getParameter("sign").trim();// 数字签名证书。
//设置支付密码
String password = request.getParameter("password") == null ? null : request
.getParameter("password").trim();//支付密码。
String optionType = request.getParameter("optionType") == null ? null : request
.getParameter("optionType").trim();// 支付密码动作。
if(userOpenId != null){
builder.append(";参数userOpenId:"+userOpenId);
}
if(accessToken != null){
builder.append(";参数accessToken:"+accessToken);
}
if(generalAccount !=null){
builder.append(";参数generalAccount:"+generalAccount);
}
if(sellerOpenId !=null){
builder.append(";参数sellerOpenId:"+sellerOpenId);
}
if(consumState !=null){
builder.append(";参数consumState:"+consumState);
}
if(consumType !=null){
builder.append(";参数consumType:"+consumType);
}
if(money !=null){
builder.append(";参数money:"+money);
}
if(orderDetail !=null){
builder.append(";参数orderDetail:"+orderDetail);
}
if(orderNum !=null){
builder.append(";参数orderNum:"+orderNum);
}
if(playType !=null){
builder.append(";参数playType:"+playType);
}
if(plateType != null){
builder.append(";参数plateType:"+plateType);
}
if(sign !=null){
builder.append(";参数sign:"+sign);
}
if(password !=null){
builder.append(";参数password:"+password);
}
if(optionType !=null){
builder.append(";参数optionType:"+optionType);
}
parame = builder.toString();
MethodAction annotation = m
.getAnnotation(MethodAction.class);
// 方法描述
String methodDescp = annotation.optionDescription();
// 方法名称
String name = annotation.methodName();
// 用户IP地址
String ip = getIpAddr(request) == null ? null : getIpAddr(
request).trim();
AccountSysLog log = new AccountSysLog();
log.setOpenId(userOpenId);
log.setOptionDesc(methodDescp);
log.setOptionIp(ip);
log.setOptionMethod(name);
log.setOptionTime(new Date());
log.setParame(parame);
AccountSysLogService accountSysLogService =(AccountSysLogService) SpringContextUtil.getBean("accountSysLogService") ;
accountSysLogService.insert(log);
}
}
}
}
return point.proceed();
}
// 返回用IP地址
public String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader(" x-forwarded-for ");
if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {
ip = request.getHeader(" Proxy-Client-IP ");
}
if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {
ip = request.getHeader(" WL-Proxy-Client-IP ");
}
if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
3、spring-context.xml 切面类型配置
<bean id="logAspect" class="aspect.AccountSysOptionLogAspect"/>
<aop:config>
<aop:aspect ref="logAspect">
<aop:pointcut id="logPointCut" expression="execution(* com.wlsq.kso.web.*.*(..))"/>
<aop:around pointcut-ref="logPointCut" method="doSystemLog"/>
</aop:aspect>
</aop:config>
通过上面的配置,我们可以清楚知道切入点:com.wlsq.kso.web 下所有控制类的方法。
切面类:aspect.AccountSysOptionLogAspect
切面方法:doSystemLog
4、切入目标控制层,相关注解配置