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
                2024年6月28日
            
            
        
                heweimin     LV13
                2024年4月15日
            
            
        
                自由吃柚子     LV2
                2024年3月26日
            
            
        
                江江江2326     LV1
                2024年1月2日
            
            
        
                hehanhan     LV1
                2023年11月8日
            
            
        
                lilong007     LV23
                2022年10月21日
            
            
        
                171337601     LV9
                2022年4月18日
            
            
        
                123qwer123     LV1
                2022年4月2日
            
            
        
                18784679855     LV8
                2022年3月5日
            
            
        
                ypf12345     LV2
                2022年3月2日
            
            
         最近浏览更多
最近浏览更多
                
                d374307168     LV1
                8月17日
            
            
        
                SX520886     LV6
                4月24日
            
            
        
                PLVAE_514     LV2
                3月10日
            
            
        
                987654321666    
                3月7日
            
            
                    暂无贡献等级
            
        
                柳咪华沙     LV7
                2024年6月28日
            
            
        
                TY0165     LV20
                2024年6月22日
            
            
        
                bingo111    
                2024年5月25日
            
            
                    暂无贡献等级
            
        
                微信网友_7000012089643008     LV4
                2024年5月19日
            
            
        
                yangyuer     LV1
                2024年4月28日
            
            
        
                heweimin     LV13
                2024年4月15日
            
            
        
 
                 
                 
                