首页>代码>基于ssm的图书馆预约占座管理系统>/LibrarySeats/src/dingzhen/aop/LogAspect.java
package dingzhen.aop;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;  
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import dingzhen.entity.Log;
import dingzhen.entity.User;
import dingzhen.service.LogService;
import dingzhen.util.StringUtil;
import dingzhen.util.TimeUtil;

/**
 * 操作日志拦截。拦截所有service层中的的add和update开头的方法
 */
@Aspect
public class LogAspect {
	
	@Autowired
	private LogService<Log> logService;
	
	/** 
     * 添加业务逻辑方法切入点 
     */ 
	@Pointcut("execution(* dingzhen.service.*.add*(..))")  
	public void addServiceCall() { }  
	
	/** 
     * 修改业务逻辑方法切入点 
     */  
    @Pointcut("execution(* dingzhen.service.*.update*(..))")  
    public void updateServiceCall() { }  
    
    
    /** 
     * 删除业务逻辑方法切入点 
     * 此处拦截要拦截到具体的莫一个模块
     * 如deleteUser方法。则删除user的时候会记录日志
     * deleteRole时删除role会记录日志
     */  
    @Pointcut("execution(* dingzhen.service.*.delete*(..))")  
    public void deleteServiceCall() { }  
      
	
    /** 
     * 管理员添加操作日志(后置通知) 
     * @param joinPoint 
     * @param rtv 
     * @throws Throwable 
     */  
    @AfterReturning(value="addServiceCall()", argNames="rtv", returning="rtv")  
    public void insertServiceCallCalls(JoinPoint joinPoint, Object rtv) throws Throwable{  
    	HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    	User currentUser = (User) request.getSession().getAttribute("currentUser");
        //判断参数  
        if(joinPoint.getArgs() == null){//没有参数  
            return;  
        }  
        //获取方法名  
        //String methodName = joinPoint.getSignature().getName();  
        String className = joinPoint.getArgs()[0].getClass().getName();
        //获取操作内容  
		className = className.substring(className.lastIndexOf(".") + 1);
        String opContent = adminOptionContent(joinPoint.getArgs(), "添加");  
         
        //创建日志对象  
        Log log = new Log();
        log.setModule(className.toLowerCase());
        try {
        	 log.setUserName(currentUser.getUserName()); 
		} catch (Exception e) {
			log.setUserName("开发者");
		}
        log.setCreateTime(TimeUtil.formatTime(new Date(),"yyyy-MM-dd HH:mm:ss"));//操作时间  
        log.setContent(opContent);//操作内容  
        log.setOperation("添加");//操作
        log.setIp(getIpAddr(request));
        logService.insertLog(log);
    }  
    
    
    
    
    /** 
     * 管理员修改操作日志(后置通知) 
     * @param joinPoint 
     * @param rtv 
     * @throws Throwable 
     */ 
    @AfterReturning(value="updateServiceCall()", argNames="rtv", returning="rtv")  
    public void updateServiceCallCalls(JoinPoint joinPoint, Object rtv) throws Throwable{  
    	HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    	User currentUser = (User) request.getSession().getAttribute("currentUser");
       
          
        //判断参数  
        if(joinPoint.getArgs() == null){//没有参数  
            return;  
        }  
        //获取方法名  
        String className = joinPoint.getArgs()[0].getClass().getName();
		className = className.substring(className.lastIndexOf(".") + 1);
        //获取操作内容  
        String opContent = adminOptionContent(joinPoint.getArgs(), "修改");  
        Log log = new Log();  
        log.setModule(className.toLowerCase());
        log.setUserName(currentUser.getUserName()); 
        log.setCreateTime(TimeUtil.formatTime(new Date(),"yyyy-MM-dd HH:mm:ss"));//操作时间  
        log.setContent(opContent);//操作内容  
        log.setOperation("修改");//操作
       
         //logService.insertLog(log);//添加日志  
         
    }  
    
    
	/**
	 * 使用Java反射来获取被拦截方法(insert、update)的参数值, 将参数值拼接为操作内容
	 */
	public String adminOptionContent(Object[] args, String type) throws Exception {
		if (args == null) {
			return null;
		}
		StringBuffer sb = new StringBuffer();
		Object info = args[0];
		String className = info.getClass().getName();
		className = className.substring(className.lastIndexOf(".") + 1);
		sb.append(type+className+" 属性名和值:");
		// 获取对象的所有方法
		Method[] methods = info.getClass().getDeclaredMethods();
		// 遍历方法,判断get方法
		for (Method method : methods) {
			String methodName = method.getName();
			// 判断是不是get方法
			if (methodName.indexOf("get") == -1) {// 不是get方法
				continue;// 不处理
			}
			Object rsValue = null;
			try {
				// 调用get方法,获取返回值
				rsValue = method.invoke(info);
				if (rsValue == null) {// 没有返回值
					continue;
				}
			} catch (Exception e) {
				continue;
			}
			// 将值加入内容中
			sb.append(" " + methodName.substring(3) + "-->" + rsValue + "  ");
		}
		return sb.toString();
	}
	
	 /** 
     * 管理员删除XX操作(环绕通知),使用环绕通知的目的是 
     * 在XX被删除前可以先查询出影片信息用于日志记录
     * 删除操作参数是ID,所以要指定模块。
     * 在上面的aop拦截中,拦截具体的莫一个模块的删除方法。 
     * @param joinPoint 
     * @param rtv 
     * @throws Throwable 
    
    @Around(value="deleteFilmCall()", argNames="rtv")  
    public Object deleteFilmCallCalls(ProceedingJoinPoint pjp) throws Throwable {  
          
        Object result = null;  
         //环绕通知处理方法  
         try {  
              
            //获取方法参数(被删除的影片id)  
            Integer id = (Integer)pjp.getArgs()[0];  
            Film obj = null;//影片对象  
            if(id != null){  
                //删除前先查询出影片对象  
                obj = filmService.getFilmById(id);  
            }  
              
            //执行删除影片操作  
            result = pjp.proceed();  
              
            if(obj != null){  
                  
                //创建日志对象  
                Log log = new Log();  
                log.setUserid(logService.loginUserId());//用户编号  
                log.setCreatedate(new Date());//操作时间  
                  
                StringBuffer msg = new StringBuffer("影片名 : ");  
                msg.append(obj.getFname());  
                log.setContent(msg.toString());//操作内容  
                  
                log.setOperation("删除");//操作  
                  
                logService.log(log);//添加日志  
            }  
              
         }  
         catch(Exception ex) {  
            ex.printStackTrace();  
         }  
           
         return result;  
    }  
    
     */  
    
	/**
	 * 反射获得对象信息
	 * @param o
	 * @return
	 */
	public static String getFieldsInfo(Object o){
		Field[] fields = o.getClass().getDeclaredFields();
		//String[] fieldNames = new String[fields.length];
		StringBuffer sb = new StringBuffer("属性名和值:");
		/**
		 * 遍历所有字段
		 * 从下标1开始
		 * 把0位置的serialVersionUID过滤掉
		 * 所以要求实体类的第一个属性都是serial*UID
		 */
		for (int i = 1; i < fields.length; i++) {    
			sb.append(fields[i].getName()+ "-->"+getFieldValueByName(fields[i].getName(), o)+"  ");
			/**infoMap = new HashMap();
			infoMap.put("type",fields[i].getType().toString());
			infoMap.put("name",fields[i].getName());
			infoMap.put("value", getFieldValueByName(fields[i].getName(), o));
			list.add(infoMap);*/
		}
		return sb.toString();
	}
	
	
	
    
	/**
	 * 通过反射
	 * 根据字段名称获取字段值
	 * @param fieldName
	 * @param o
	 * @return
	 */
	private static Object getFieldValueByName(String fieldName,Object o){
		try {
			String firstLetter = fieldName.substring(0, 1).toUpperCase();   //手写字母大写
			String getter = "get" + firstLetter + fieldName.substring(1);   // get方法
			Method method = o.getClass().getMethod(getter,new Class[]{});
			Object object = method.invoke(o, new Object[]{});
			return object;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	
	
	/**
	 * 反射获得字段值
	 * @param o
	 * @return
	 */
	@SuppressWarnings("unused")
	private static String[] getFieldName(Object o){
		Field[] fields = o.getClass().getDeclaredFields();
		String[] fieldNames = new String[fields.length];
		for (int i = 0; i < fieldNames.length; i++) {
			fieldNames[i] = fields[i].getName();
		}
		return fieldNames;
	}
 
    
 
    
    /**
	 * 获取访问者IP
	 * 
	 * 在一般情况下使用Request.getRemoteAddr()即可,但是经过nginx等反向代理软件后,这个方法会失效。
	 * 
	 * 本方法先从Header中获取X-Real-IP,如果不存在再从X-Forwarded-For获得第一个IP(用,分割),
	 * 如果还不存在则调用Request .getRemoteAddr()。
	 * 
	 * @param request
	 * @return
	 */
	public static String getIpAddr(HttpServletRequest request) throws Exception{
		String ip = request.getHeader("X-Real-IP");
		if (!StringUtil.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) {
			return ip;
		}
		ip = request.getHeader("X-Forwarded-For");
		if (!StringUtil.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) {
			// 多次反向代理后会有多个IP值,第一个为真实IP。
			int index = ip.indexOf(',');
			if (index != -1) {
				return ip.substring(0, index);
			} else {
				return ip;
			}
		} else {
			return request.getRemoteAddr();
		}
	}
	
    
    
    
    
	
}
最近下载更多
柳咪华沙  LV7 6月28日
heweimin  LV13 4月15日
自由吃柚子  LV2 3月26日
江江江2326  LV1 1月2日
hehanhan  LV1 2023年11月8日
lilong007  LV22 2022年10月21日
171337601  LV9 2022年4月18日
123qwer123  LV1 2022年4月2日
18784679855  LV8 2022年3月5日
ypf12345  LV2 2022年3月2日
最近浏览更多
柳咪华沙  LV7 6月28日
TY0165  LV20 6月22日
bingo111 5月25日
暂无贡献等级
yangyuer  LV1 4月28日
heweimin  LV13 4月15日
Charismatic 4月14日
暂无贡献等级
WBelong  LV8 3月29日
自由吃柚子  LV2 3月26日
renyong  LV3 3月1日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友