操作_操作系统 - CSDN
精华内容
参与话题
  • char相关 判断是否是字母、数字 Character.isLetterOrDigit(c1)//字母或者字符串 Character.isDigit();//数字 Character.isLetter();//字母 ...char的大小写转换,单个字符 ...if(Character.isUpperCase(c1)){ ...

    char相关

    • 判断是否是字母、数字
    Character.isLetterOrDigit(c1)//字母或者字符串
    Character.isDigit();//数字
    Character.isLetter();//字母
    
    • char的大小写转换,单个字符
    c1 = Character.toLowerCase(c1);
    c2 = Character.isUpperCase(c1)
    //toLowerCase() 方法可以将字符串中的所有字符全部转换成小写,而非字母的字符不受影响
    或者:
    c = (char)(c - 32);//小写字母转大写字母
    

    String相关

    String low = s.toLowerCase()//全部转成小写
    String.length() //获取字符串的长度
    String.charAt(i) //获取第i个字符的内容
    String.subString(start) //获取[start,)的字符串
    String.subString(start,end) //获取[start,end)中的字符串,左闭右开
    char[] c = iniString.toCharArray() //将字符串转为char数
    String.equal() //判断两个字符串是否相等
    
    • String 拼接
    char firstletter = s.charAt(0);
    firstletter = (char)(firstletter - 32);//小写转大写
    String firstword = firstletter + c.substring(1);
    
    • 看String字符串是否为空字符串的方法
      去空格!然后和""相比,相同就是true
    str.trim().equals("")
    

    StringBuilder相关

    StringBuffer又称为可变字符序列,它是一个类似于 String 的字符串缓冲区,通过某些方法调用可以改变该序列的长度和内容。和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象

    • StringBuilder和StringBuffer的区别?
      基本相似,两个类的构造器和方法也基本相同。不同的是:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。
    StringBuilder sb = new StringBuilder();
    sb.length()
    sb.append(s);//添加
    sb.append(s, i+1, j);//左闭右开
    sb.delete(0,1);  //删除[0,1)的数据
    sb.deleteCharAt(sb.length()-1);//删除某个位置的元素
    sb.setCharAt(0, 'c');//修改某个位置的元素,将第0个位置改成c
    sb.toString();//StringBuilder 转 String
    sb.insert(0,"we");//在0的位置加入后面的内容
    char c = stringBuilder.charAt(i);//查询某个位置上的字符
    new String(stringBuilder);//用stringBuilder来初始化String
    

    相互转换

    char[] c = iniString.toCharArray() //String转为char数组
    sb.toString();//StringBuilder 转 String
    String[] str = low.split(" ");//String转String[],根据空格切分
    //String[] to String,根据空格合并
    String ans = "";
    ans = String.join(" ", str);
    
    //List转String,这样会把逗号也加进String里
    String string1 = String.join(",",list1);
    //char转String
    String s = String.valueOf('c');
    
    展开全文
  • 如何实现操作操作日志记录

    万次阅读 2018-12-26 11:16:45
    如何实现操作操作日志记录 为什么要记录操作日志? 项目中的业务需求,需要针对用户的一些业务操作操作记录, 也就是标题中的操场日志记录,最近做的项目也有这个需求, 我也是第一次写,相信有很多开发者也有遇到这个...

    如何实现操作操作日志记录

    为什么要记录操作日志?

    项目中的业务需求,需要针对用户的一些业务操作做操作记录,
    也就是标题中的操场日志记录,最近做的项目也有这个需求,
    我也是第一次写,相信有很多开发者也有遇到这个需求的,所以
    在这里做一个简单的记录,只是提供一个思路参考,代码什么的
    其实是次要的!
    

    业务需求如下,记录用户的重要操作,记录除查询外,如增加,修改,和删除等操作

    在这里插入图片描述

    实现思路

    首先我肯定是用aop了,在后面的使用发现,apo的实现适合大部分
    的单表操作,但是多表更改,例如先加后改是没法实现的,所以我决定
    提供两种实现方式,另外一种使用service函数调用来解决了
    

    表设计

    CREATE TABLE operation_log (
    `id` INT(10) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键id',
    `name` VARCHAR(128) NULL DEFAULT NULL COMMENT '操作业务名',
    `table_name` VARCHAR(16) NULL DEFAULT NULL COMMENT '操作表名',
    `table_id` VARCHAR(16) NULL DEFAULT NULL COMMENT '操作表id',
    `type` VARCHAR(8) NULL DEFAULT NULL COMMENT '操作类型,(添加ADD,删除DELETE,修改UPDATE)' ,
    `operator_id` VARCHAR(16) NULL DEFAULT NULL COMMENT '操作人id',
    `operator_name` VARCHAR(16) NULL DEFAULT NULL COMMENT '操作人名',
    `operation_time` TIMESTAMP NULL DEFAULT NULL COMMENT '操作时间'
    )ENGINE INNODB CHARSET utf8 COMMENT '用户操作日志记录表';
    	
    CREATE TABLE operation_log_detail (
    `id` INT(10) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键id',
    `operation_log_id` INT(10) NULL DEFAULT NULL COMMENT '操作日志id',
    `clm_name` VARCHAR(16) NULL DEFAULT NULL COMMENT '字段名',
    `clm_comment` VARCHAR(128) NULL DEFAULT NULL COMMENT '字段描述',
    `old_string` VARCHAR(128) NULL DEFAULT NULL COMMENT '旧值',
    `new_string` VARCHAR(128) NULL DEFAULT NULL COMMENT '新值'
    )ENGINE INNODB CHARSET utf8 COMMENT '操作日志详情表';
    

    AOP实现

    0目标: 在业务代码函数上使用注解,通过注解实现执行时的环形切面,在切面前,切面后,做数据的变更记录操作
    开始:
    1创建注解
    package com.csp.operationlog.aspect.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import com.csp.operationlog.aspect.enums.OperationType;
    
    /**
     * 用来标注需要进行操作日志的服务函数上
     * @author taoken
     */
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface OperationLog {
    	/** 业务名 */
    	String name();
    	/** 表名 */
    	String table();
    	/** id 在函数的字段名 */
    	int idRef() default -1; 
    	/** 需要记录的字段 */
    	String[] cloum() default {};
    	/** 操作类型 */
    	OperationType type();
    	/** 操作人 id 在函数的字段名*/
    	int operatorIdRef();
    	/** 操作人名称 在函数的字段名 */
    	int operatorNameRef();
    }
    由于使用了一个枚举下面提供一个枚举,作用是分辨操作类型
    package com.csp.operationlog.aspect.enums;
    public enum OperationType {
    	ADD,
    	UPDATE,
    	DELETE;
    
    	public String getType() {
    		if (this.equals(ADD)) {
    			return "ADD";
    		}
    		if (this.equals(UPDATE)) {
    			return "UPDATE";
    		}
    		if (this.equals(DELETE)) {
    			return "DELETE";
    		}
    		return null;
    	};
    }
    2使用注解,只是提前看看使用效果
        @OperationLog(name = "更新账户",type = OperationType.UPDATE,operatorIdRef = 0,operatorNameRef = 1,idRef = 2,table = "account")
        public void updateAccount(String operatorId,String operatorName,Integer accountId){
            Account account = new Account();
            account.setId(accountId);
            account.setAccount(1100);
            accountMapper.updateAccount(account);
        }
    3下面开始实现切面
    package com.csp.operationlog.aspect.aop;
    
    import java.sql.Timestamp;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.support.TransactionCallbackWithoutResult;
    import org.springframework.transaction.support.TransactionTemplate;
    
    import com.csp.operationlog.aspect.enums.OperationType;
    import com.csp.operationlog.dto.ColumnComment;
    import com.csp.operationlog.mapper.OperationLogDetailMapper;
    import com.csp.operationlog.mapper.OperationLogMapper;
    import com.csp.operationlog.model.OperationLog;
    import com.csp.operationlog.model.OperationLogDetail;
    
    @Aspect
    @Component
    public class OperationLogAop {
    	@Autowired
    	private OperationLogMapper operationLogMapper;
    	@Autowired
    	private OperationLogDetailMapper operationLogDetailMapper;
    	@Autowired
    	private TransactionTemplate txTemplate;
    
    	@Around(value = "@annotation(operationlog)")
    	public void logAround(final ProceedingJoinPoint p,final com.csp.operationlog.aspect.annotation.OperationLog operationlog) throws Throwable {
    		OperationType type = operationlog.type();
    		if (OperationType.UPDATE.equals(type)) {
    			update(p, operationlog);
    		}
    		if (OperationType.ADD.equals(type)) {
    			add(p, operationlog);
    		}
    		if (OperationType.DELETE.equals(type)) {
    			delete(p, operationlog);
    		}
    	}
    	
    	public void delete(final ProceedingJoinPoint p,final com.csp.operationlog.aspect.annotation.OperationLog operationlog) {
    		txTemplate.execute(new TransactionCallbackWithoutResult() {
    			@Override
    			protected void doInTransactionWithoutResult(TransactionStatus status) {
    				StringBuilder sql = new StringBuilder();
    				OperationType type = operationlog.type();
    				Object[] args = p.getArgs();
    				String logName = operationlog.name();
    				String logTable = operationlog.table();
    				if (operationlog.idRef()==-1) {
    					throw new RuntimeException();
    				}
    				String id = args[operationlog.idRef()].toString();
    				String[] cloum = operationlog.cloum();
    				String operatorId = args[operationlog.operatorIdRef()].toString();
    				String operatorName = args[operationlog.operatorNameRef()].toString();
    
    				Map<String, Object> columnCommentMap = new HashMap<String, Object>();
    				List<ColumnComment> columnCommentList = operationLogMapper.selectColumnCommentByTable(logTable);
    
    				for (ColumnComment cc : columnCommentList) {
    					columnCommentMap.put(cc.getColumn(), cc.getComment());
    				}
    				if (cloum.length == 0) {
    					Set<String> keySet = columnCommentMap.keySet();
    					List<String> list = new ArrayList<String>();
    					for (String o : keySet) {
    						list.add(o.toString());
    					}
    					cloum = list.toArray(new String[list.size()]);
    				}
    				sql.append("SELECT ");
    				for (int i = 0; i < cloum.length; i++) {
    					if (i == 0) {
    						sql.append("`" + cloum[i] + "` ");
    					} else {
    						sql.append(",`" + cloum[i] + "` ");
    					}
    				}
    				sql.append(" FROM " + logTable + " WHERE id=" + id);
    				Map<String, Object> oldMap = operationLogMapper.selectAnyTalbe(sql.toString());
    
    				try {
    					p.proceed();
    				} catch (Throwable e) {
    					throw new RuntimeException(e);
    				}
    
    				if (oldMap!=null) {
    					OperationLog op = new OperationLog();
    					op.setName(logName);
    					op.setTableName(logTable);
    					op.setTableId(id);
    					op.setType(type.getType());
    					op.setOperatorId(operatorId);
    					op.setOperatorName(operatorName);
    					op.setOperationTime(new Timestamp(System.currentTimeMillis()));
    					operationLogMapper.insertOperationLog(op);
    					List<OperationLogDetail> opds = new ArrayList<OperationLogDetail>();
    					for (String clm : cloum) {
    						Object oldclm = oldMap.get(clm);
    						OperationLogDetail opd = new OperationLogDetail();
    						opd.setOldString(oldclm.toString());
    						opd.setNewString("");
    						opd.setClmName(clm);
    						opd.setClmComment(columnCommentMap.get(clm).toString());
    						opd.setOperationLogId(op.getId());
    						opds.add(opd);
    					}
    					if (!opds.isEmpty()) {
    						operationLogDetailMapper.insertOperationLogDetail(opds);
    					}
    				}
    			}
    		});
    	}
    
    	private void add(final ProceedingJoinPoint p,final com.csp.operationlog.aspect.annotation.OperationLog operationlog) {
    		txTemplate.execute(new TransactionCallbackWithoutResult() {
    			@Override
    			protected void doInTransactionWithoutResult(TransactionStatus status) {
    				StringBuilder sql = new StringBuilder();
    				OperationType type = operationlog.type();
    				Object[] args = p.getArgs();
    				String logName = operationlog.name();
    				String logTable = operationlog.table();
    				String[] cloum = operationlog.cloum();
    				String operatorId = args[operationlog.operatorIdRef()].toString();
    				String operatorName = args[operationlog.operatorNameRef()].toString();
    
    				Map<String, Object> columnCommentMap = new HashMap<String, Object>();
    				List<ColumnComment> columnCommentList = operationLogMapper.selectColumnCommentByTable(logTable);
    				
    				for (ColumnComment cc : columnCommentList) {
    					columnCommentMap.put(cc.getColumn(), cc.getComment());
    				}
    				if (cloum.length == 0) {
    					Set<String> keySet = columnCommentMap.keySet();
    					List<String> list = new ArrayList<String>();
    					for (String o : keySet) {
    						list.add(o.toString());
    					}
    					cloum = list.toArray(new String[list.size()]);
    				}
    				sql.append("SELECT ");
    				for (int i = 0; i < cloum.length; i++) {
    					if (i == 0) {
    						sql.append("`" + cloum[i] + "` ");
    					} else {
    						sql.append(",`" + cloum[i] + "` ");
    					}
    				}
    				sql.append(" FROM " + logTable + " ORDER BY id DESC LIMIT 1");
    				Map<String, Object> oldMap = operationLogMapper.selectAnyTalbe(sql.toString());
    				try {
    					p.proceed();
    				} catch (Throwable e) {
    					throw new RuntimeException(e);
    				}
    				Map<String, Object> newMap = operationLogMapper.selectAnyTalbe(sql.toString());
    				if ((oldMap==null)||(!oldMap.get("id").toString().equals(newMap.get("id").toString()))) {
    					
    					OperationLog op = new OperationLog();
    					op.setName(logName);
    					op.setTableName(logTable);
    					op.setTableId("");
    					op.setType(type.getType());
    					op.setOperatorId(operatorId);
    					op.setOperatorName(operatorName);
    					op.setOperationTime(new Timestamp(System.currentTimeMillis()));
    					operationLogMapper.insertOperationLog(op);
    					List<OperationLogDetail> opds = new ArrayList<OperationLogDetail>();
    					for (String clm : cloum) {
    						Object oldclm = "";
    						Object newclm = newMap.get(clm);
    						OperationLogDetail opd = new OperationLogDetail();
    						opd.setOldString(oldclm.toString());
    						opd.setNewString(newclm.toString());
    						opd.setClmName(clm);
    						opd.setClmComment(columnCommentMap.get(clm).toString());
    						opd.setOperationLogId(op.getId());
    						opds.add(opd);
    					}
    					if (!opds.isEmpty()) {
    						operationLogDetailMapper.insertOperationLogDetail(opds);
    					}
    					
    				}
    			}
    		});
    	}
    
    	public void update(final ProceedingJoinPoint p,final com.csp.operationlog.aspect.annotation.OperationLog operationlog) {
    		txTemplate.execute(new TransactionCallbackWithoutResult() {
    			@Override
    			protected void doInTransactionWithoutResult(TransactionStatus status) {
    				StringBuilder sql = new StringBuilder();
    				OperationType type = operationlog.type();
    				Object[] args = p.getArgs();
    				String logName = operationlog.name();
    				String logTable = operationlog.table();
    				if (operationlog.idRef()==-1) {
    					throw new RuntimeException();
    				}
    				String id = args[operationlog.idRef()].toString();
    				String[] cloum = operationlog.cloum();
    				String operatorId = args[operationlog.operatorIdRef()].toString();
    				String operatorName = args[operationlog.operatorNameRef()].toString();
    
    				Map<String, Object> columnCommentMap = new HashMap<String, Object>();
    				List<ColumnComment> columnCommentList = operationLogMapper.selectColumnCommentByTable(logTable);
    				
    				for (ColumnComment cc : columnCommentList) {
    					columnCommentMap.put(cc.getColumn(), cc.getComment());
    				}
    				if (cloum.length == 0) {
    					Set<String> keySet = columnCommentMap.keySet();
    					List<String> list = new ArrayList<String>();
    					for (String o : keySet) {
    						list.add(o.toString());
    					}
    					cloum = list.toArray(new String[list.size()]);
    				}
    				sql.append("SELECT ");
    				for (int i = 0; i < cloum.length; i++) {
    					if (i == 0) {
    						sql.append("`" + cloum[i] + "` ");
    					} else {
    						sql.append(",`" + cloum[i] + "` ");
    					}
    				}
    				sql.append(" FROM " + logTable + " WHERE id=" + id);
    				Map<String, Object> oldMap = operationLogMapper.selectAnyTalbe(sql.toString());
    
    				try {
    					p.proceed();
    				} catch (Throwable e) {
    					throw new RuntimeException(e);
    				}
    
    				Map<String, Object> newMap = operationLogMapper.selectAnyTalbe(sql.toString());
    				if (oldMap!=null&&newMap!=null) {
    					OperationLog op = new OperationLog();
    					op.setName(logName);
    					op.setTableName(logTable);
    					op.setTableId(id);
    					op.setType(type.getType());
    					op.setOperatorId(operatorId);
    					op.setOperatorName(operatorName);
    					op.setOperationTime(new Timestamp(System.currentTimeMillis()));
    					operationLogMapper.insertOperationLog(op);
    					List<OperationLogDetail> opds = new ArrayList<OperationLogDetail>();
    					for (String clm : cloum) {
    						Object oldclm = oldMap.get(clm);
    						Object newclm = newMap.get(clm);
    						OperationLogDetail opd = new OperationLogDetail();
    						opd.setOldString(oldclm.toString());
    						opd.setNewString(newclm.toString());
    						opd.setClmName(clm);
    						opd.setClmComment(columnCommentMap.get(clm).toString());
    						opd.setOperationLogId(op.getId());
    						opds.add(opd);
    					}
    					if (!opds.isEmpty()) {
    						operationLogDetailMapper.insertOperationLogDetail(opds);
    					}
    				}
    			}
    		});
    	}
    }
    4 可以看出上面实现中用到了表对应的实体类,以及操作数据库的持久层mapper,还有一个数据对象
    我们提供一下,这里简单说明一下,我用的是mybatis,最后提供pom.xml
    package com.csp.operationlog.model;
    import java.sql.Timestamp;
    /**
     * 操作日志主信息模型
     * @author taoken
     */
    public class OperationLog {
    	/** 主键id */
    	private String id;
    	/** 操作业务名 */
    	private String name;
    	/** 操作表名 */
    	private String tableName;
    	/** 操作表id */
    	private String tableId;
    	/** 操作类型,(添加ADD,删除DELETE,修改UPDATE)' */
    	private String type;
    	/** 操作人id */
    	private String operatorId;
    	/** 操作人名 */
    	private String operatorName;
    	/** 操作时间 */
    	private Timestamp operationTime;
    	public String getId() {
    		return id;
    	}
    	public void setId(String id) {
    		this.id = id;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String getTableName() {
    		return tableName;
    	}
    	public void setTableName(String tableName) {
    		this.tableName = tableName;
    	}
    	public String getTableId() {
    		return tableId;
    	}
    	public void setTableId(String tableId) {
    		this.tableId = tableId;
    	}
    	public String getType() {
    		return type;
    	}
    	public void setType(String type) {
    		this.type = type;
    	}
    	public String getOperatorId() {
    		return operatorId;
    	}
    	public void setOperatorId(String operatorId) {
    		this.operatorId = operatorId;
    	}
    	public String getOperatorName() {
    		return operatorName;
    	}
    	public void setOperatorName(String operatorName) {
    		this.operatorName = operatorName;
    	}
    	public Timestamp getOperationTime() {
    		return operationTime;
    	}
    	public void setOperationTime(Timestamp operationTime) {
    		this.operationTime = operationTime;
    	}
    }
    
    package com.csp.operationlog.model;
    /**
     * 操作日志详情模型
     * @author taoken
     */
    public class OperationLogDetail {
    	/** 主键id */
    	private String id;
    	/** 操作日志id */
    	private String operationLogId;
    	/** 字段名 */
    	private String clmName;
    	/** 字段描述 */
    	private String clmComment;
    	/** 旧值 */
    	private String oldString;
    	/** 新值 */
    	private String newString;
    	
    	public String getId() {
    		return id;
    	}
    	public void setId(String id) {
    		this.id = id;
    	}
    	public String getOperationLogId() {
    		return operationLogId;
    	}
    	public void setOperationLogId(String operationLogId) {
    		this.operationLogId = operationLogId;
    	}
    	public String getClmName() {
    		return clmName;
    	}
    	public void setClmName(String clmName) {
    		this.clmName = clmName;
    	}
    	public String getClmComment() {
    		return clmComment;
    	}
    	public void setClmComment(String clmComment) {
    		this.clmComment = clmComment;
    	}
    	public String getOldString() {
    		return oldString;
    	}
    	public void setOldString(String oldString) {
    		this.oldString = oldString;
    	}
    	public String getNewString() {
    		return newString;
    	}
    	public void setNewString(String newString) {
    		this.newString = newString;
    	}
    }
    
    package com.csp.operationlog.mapper;
    import java.util.List;
    import java.util.Map;
    import org.apache.ibatis.annotations.InsertProvider;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Param;
    import com.csp.operationlog.model.OperationLogDetail;
    /**
     * 操作日志详情持久层
     * @author taoken
     */
    @Mapper
    public interface OperationLogDetailMapper {
    	public static class OperationLogDetailMapperProvider{
    		public String insertOperationLogDetailSQL(Map<String,List<OperationLogDetail>> map) {
    			List<OperationLogDetail> ops = map.get("ops");
    			StringBuilder sqlBuid = new StringBuilder("INSERT INTO operation_log_detail (operation_log_id,clm_name,clm_comment,old_string,new_string) VALUES ");
    			for (int i = 0; i < ops.size(); i++) {
    				OperationLogDetail o = ops.get(i);
    				if (i==0) {
    					sqlBuid.append(" ('"+o.getOperationLogId()+"','"+o.getClmName()+"','"+o.getClmComment()+"','"+o.getOldString()+"','"+o.getNewString()+"') ");
    				}else {
    					sqlBuid.append(" ,('"+o.getOperationLogId()+"','"+o.getClmName()+"','"+o.getClmComment()+"','"+o.getOldString()+"','"+o.getNewString()+"') ");
    				}
    			}
    			return sqlBuid.toString();
    		}
    	}
    	//批量添加操作详情
    	@InsertProvider( type=OperationLogDetailMapperProvider.class, method="insertOperationLogDetailSQL" )
    	public void insertOperationLogDetail(@Param("ops")List<OperationLogDetail> operationLogDetails);
    }
    
    package com.csp.operationlog.mapper;
    import java.util.List;
    import java.util.Map;
    import org.apache.ibatis.annotations.Insert;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Options;
    import org.apache.ibatis.annotations.Param;
    import org.apache.ibatis.annotations.Select;
    import org.apache.ibatis.annotations.SelectProvider;
    import com.csp.operationlog.dto.ColumnComment;
    import com.csp.operationlog.model.OperationLog;
    
    /**
     * 操作日志持久层
     * @author taoken
     */
    @Mapper
    public interface OperationLogMapper {
    	public static class OperationLogMapperProvider{
    		public String selectAnyTalbeSQL(Map<String,String> map) {
    			return map.get("sql");
    		}
    	}
    	//添加操作日志
    	@Insert("INSERT INTO operation_log (name,table_name,table_id,type,operator_id,operator_name,operation_time) VALUES (#{p.name},#{p.tableName},#{p.tableId},#{p.type},#{p.operatorId},#{p.operatorName},#{p.operationTime});")
    	@Options(useGeneratedKeys=true,keyColumn="id",keyProperty="p.id")
    	public void insertOperationLog(@Param("p")OperationLog operationLog);
    	
    	//查询任意sql
    	@SelectProvider(type=OperationLogMapperProvider.class,method="selectAnyTalbeSQL")
    	public Map<String,Object> selectAnyTalbe(@Param("sql")String sql);
    	
    	//查询任意表的字段与备注
    	@Select("SELECT COLUMN_NAME `column`,column_comment `comment` FROM INFORMATION_SCHEMA.Columns WHERE table_name=#{table}")
    	public List<ColumnComment> selectColumnCommentByTable(@Param("table")String tableName);
    }
    
    package com.csp.operationlog.dto;
    public class ColumnComment {
    	private String column;
    	private String comment;
    	public String getColumn() {
    		return column;
    	}
    	public void setColumn(String column) {
    		this.column = column;
    	}
    	public String getComment() {
    		return comment;
    	}
    	public void setComment(String comment) {
    		this.comment = comment;
    	}
    }
    
    package com.csp.operationlog.util;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    public class HumpUtil {
    	public static final char UNDERLINE = '_';
    	/**
    	 * (userId:user_id)
    	 * @param param
    	 * @return
    	 */
    	public static String camelToUnderline(String param) {
    		if (param == null || "".equals(param.trim())) {
    			return "";
    		}
    		int len = param.length();
    		StringBuilder sb = new StringBuilder(len);
    		for (int i = 0; i < len; i++) {
    			char c = param.charAt(i);
    			if (Character.isUpperCase(c)) {
    				sb.append(UNDERLINE);
    				sb.append(Character.toLowerCase(c));
    			} else {
    				sb.append(c);
    			}
    		}
    		return sb.toString();
    	}
    
    	/**
    	 * (user_id:userId)
    	 * @param param
    	 * @return
    	 */
    	public static String underlineToCamel(String param) {
    		if (param == null || "".equals(param.trim())) {
    			return "";
    		}
    		StringBuilder sb = new StringBuilder(param);
    		Matcher mc = Pattern.compile(UNDERLINE + "").matcher(param);
    		int i = 0;
    		while (mc.find()) {
    			int position = mc.end() - (i++);
    			String.valueOf(Character.toUpperCase(sb.charAt(position)));
    			sb.replace(position - 1, position + 1,
    					sb.substring(position, position + 1).toUpperCase());
    		}
    		return sb.toString();
    	}
    }
    
    package com.csp.operationlog.util;
    import java.beans.PropertyDescriptor;
    import java.util.HashMap;
    import java.util.Map;
    import org.springframework.beans.BeanWrapper;
    import org.springframework.beans.BeanWrapperImpl;
    public class ToMapUtil {
    	@SuppressWarnings({ "unchecked"})
    	public static <T> Map<String, Object> toMap(T bean) {
    		if (bean instanceof Map) {
    			return (Map<String, Object>)bean;
    		}
    		BeanWrapper beanWrapper = new BeanWrapperImpl(bean);
    		Map<String, Object> map = new HashMap<String, Object>();
    		PropertyDescriptor[] pds = beanWrapper.getPropertyDescriptors();
    		for (PropertyDescriptor pd : pds) {
    			if (!"class".equals(pd.getName())) {
    				map.put(pd.getName(),
    						beanWrapper.getPropertyValue(pd.getName()));
    			}
    		}
    		return map;
    	}
    }
    
    pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    
    	<groupId>com.csp.service</groupId>
    	<artifactId>service-operationlog</artifactId>
    	<version>1.0</version>
    	<packaging>jar</packaging>
    
    	<name>service-operationlog</name>
    	<description>service-operationlog project for Spring Boot</description>
    	
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>1.5.9.RELEASE</version>
    		<relativePath />
    	</parent>
    
    	<dependencies>
    		<!-- aop -->
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-aop</artifactId>
    		</dependency>
    		<!-- mybatis -->
    		<dependency>
    			<groupId>org.mybatis.spring.boot</groupId>
    			<artifactId>mybatis-spring-boot-starter</artifactId>
    			<version>1.3.2</version>
    		</dependency>
    		<!-- mysql -->
    		<dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    		</dependency>
    		<!--long3-->
    		<dependency>
    			<groupId>org.apache.commons</groupId>
    			<artifactId>commons-lang3</artifactId>
    			<version>3.3.2</version>
    		</dependency>
    	</dependencies>
    </project>
    

    开始测试

    创建springboot的测试demo项目

    1启动相关配置与启动类,这里模拟我们的真实项目
    pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>1.5.9.RELEASE</version>
    		<relativePath/> <!-- lookup parent from repository -->
    	</parent>
    	<groupId>com.example</groupId>
    	<artifactId>demo</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>demo</name>
    	<description>Demo project for Spring Boot</description>
    
    	<properties>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    		<dependency>
    			<groupId>com.csp.service</groupId>
    			<artifactId>service-operationlog</artifactId>
    			<version>1.0</version>
    		</dependency>
    		<!-- mybatis -->
    		<dependency>
    			<groupId>org.mybatis.spring.boot</groupId>
    			<artifactId>mybatis-spring-boot-starter</artifactId>
    			<version>1.3.2</version>
    		</dependency>
    		<!-- mysql -->
    		<dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>
    </project>
    
    package com.example.demo;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.ComponentScan;
    @SpringBootApplication
    @ComponentScan(basePackages = {"com.csp.**","com.example.**"})//这里是项目对SpringBean注入的扫描,前面是对operationlog项目中bean的扫描,后面是demo项目的bean的扫描
    @MapperScan({"com.csp.operationlog.mapper","com.example.demo.**.mapper"})//这里com.csp.**是扫描我的operationlog项目的mapper,而com.example.**扫描的是我的demo项目的mapper
    public class DemoApplication {
    	public static void main(String[] args) {
    		SpringApplication.run(DemoApplication.class, args);
    	}
    }
    
    2 我们使用一个账户表,用来测试操作账户,看看是否能够实现日志记录
    表创建:
    CREATE TABLE `account` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
      `account` int(10) DEFAULT NULL COMMENT '账户',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
    
    2 创建对应实体与mapper
    package com.example.demo.domain;
    import java.io.Serializable;
    public class Account implements Cloneable, Serializable {
    	private static final long serialVersionUID = 1L;
    	
    	private Integer id;
        private Integer account;
    
        public Account clone() {
            try {
                Account proto = (Account) super.clone();
                return proto;
            }catch (CloneNotSupportedException e){
                return null;
            }
        }
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public Integer getAccount() {
            return account;
        }
        public void setAccount(Integer account) {
            this.account = account;
        }
    }
    
    package com.example.demo.mapper;
    import com.example.demo.domain.Account;
    import org.apache.ibatis.annotations.*;
    @Mapper
    public interface AccountMapper {
        @Insert("INSERT INTO account (account) VALUES (#{a.account})")
        public void insertAccount(@Param("a") Account a);
        @Update("UPDATE account SET account=#{a.account} WHERE id=#{a.id}")
        public void updateAccount(@Param("a") Account a);
        @Select("DELETE FROM account WHERE id=#{id}")
        public void deleteAccountById(@Param("id") Integer id);
        @Select("SELECT id,account FROM account WHERE id=#{id}")
        public Account selectAccountById(@Param("id")Integer id);
    }
    
    3 后面是具体的业务代码
    package com.example.demo.service;
    import javax.annotation.Resource;
    import org.springframework.stereotype.Service;
    import com.csp.operationlog.aspect.annotation.OperationLog;
    import com.csp.operationlog.aspect.enums.OperationType;
    import com.csp.operationlog.service.OperationLogService;
    import com.example.demo.domain.Account;
    import com.example.demo.mapper.AccountMapper;
    @Service
    public class AccountService {
        @Resource
        AccountMapper accountMapper;
        @Resource
        OperationLogService operationLogService;
    
        //采用注解方式,实现操作日志的记录,适用于大多数简单服务,不涉及代码中多表更改的业务
        @OperationLog(name = "添加账户",type = OperationType.ADD,operatorIdRef = 0,operatorNameRef = 1,table = "account")
        public void addAccount(String operatorId,String operatorName){
            Account account = new Account();
            account.setAccount(181);
            accountMapper.insertAccount(account);
        }
    
        @OperationLog(name = "更新账户",type = OperationType.UPDATE,operatorIdRef = 0,operatorNameRef = 1,idRef = 2,table = "account")
        public void updateAccount(String operatorId,String operatorName,Integer accountId){
            Account account = new Account();
            account.setId(accountId);
            account.setAccount(1100);
            accountMapper.updateAccount(account);
        }
    
        @OperationLog(name = "删除账户",type = OperationType.DELETE,operatorIdRef = 0,operatorNameRef = 1,idRef = 2,table = "account")
        public void deleteAccount(String operatorId,String operatorName,Integer accountId){
            accountMapper.deleteAccountById(accountId);
        }
    
        //使用服务调用的方式,实现操作日志的记录,为了在注解无法解决业务代码中对多个表操作时的应对方法
        public void addAcccount2(){
            Account account=new Account();
            account.setAccount(181);
            accountMapper.insertAccount(account);
            operationLogService.logForAdd("添加账户","account","1","liutao",account);
        }
    
        public void updateAccount2(){
            Account account = accountMapper.selectAccountById(1);
            if (account!=null){
                Account accountOld = account.clone();
                account.setId(1);
                account.setAccount(0);
                accountMapper.updateAccount(account);
                operationLogService.logForUpd("更新账户","account",account.getId().toString(),"1","liutao",accountOld,account);
            }
        }
    
        public void deleteAccount2(){
            Account account = accountMapper.selectAccountById(1);
            if (account!=null){
                accountMapper.deleteAccountById(1);
                operationLogService.logForDel("删除账户","account",account.getId().toString(),"1","liutao",account);
            }
        }
    }
    4 为了方便测试,我们写几个controller进行测试,有页面调用,模拟实际业务操作
    package com.example.demo.controller;
    import javax.annotation.Resource;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import com.example.demo.service.AccountService;
    @Controller
    public class AccountControler {
        @Resource
        private AccountService accountService;
        //采用注解方式
        @RequestMapping("/t1")
        @ResponseBody
        public String addTest(){
            accountService.addAccount("1","liutao");
            return "ok";
        }
        @RequestMapping("/t2")
        @ResponseBody
        public String updateTest(){
            accountService.updateAccount("1","liutao",1);
            return "ok";
        }
        @RequestMapping("/t3")
        @ResponseBody
        public String deleteTest(){
            accountService.deleteAccount("1","liutao",1);
            return "ok";
        }
    
        //采用服务调用
        @RequestMapping("/s1")
        @ResponseBody
        public String addTest2(){
            accountService.addAcccount2();
            return "ok";
        }
        @RequestMapping("/s2")
        @ResponseBody
        public String updateTest2() {
            accountService.updateAccount2();
            return "ok";
        }
        @RequestMapping("/s3")
        @ResponseBody
        public String deleteTest2(){
            accountService.deleteAccount2();
            return "ok";
        }
    }
    
    配置文件application.yml
    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/demo?characterEncoding=utf-8&useSSL=false
        username: root
        password: root
    

    备注

    有了上面的基本实现,和测试demo,应该可以基本实现日志的记录,
    对于相关细节,我都放到备注中,
    1 apo实现,需要再建立在mysql事务级别在可重复读级别上(一般默认就是哈!)
    2 服务调用实现,可以异步处理啦,如果有为了效率可以再我备注的地方实现即可,自己选择mq实现就行了
    3 只能保证基本实现了,质量不保证,主要是提供思路和实现逻辑,有了思路,自己可以写的
    4 已经有了记录,具体的表查询的业务代码就可以自己查表了哈
    最后项目代码放到github: https://github.com/taopanwoaini/operation-log 自行下载吧,路过几点点个星,谢谢

    展开全文
  • Cadence 16.6基本操作技巧(一)

    千次阅读 2018-11-21 11:28:10
    都是工作上碰到的需要学习的知识,比较实用。 1、修改Pin脚网络 set up --user preference Editor Logic--net logic Option处选择网络,然后find处选择Pins,之后点击要修改网络的... 2、在使用测量工具的时候,...

    都是工作上碰到的需要学习的知识,比较实用。

    1、修改Pin脚网络

    set up --user preference Editor

    Logic--net logic

    Option处选择网络,然后find处选择Pins,之后点击要修改网络的Pin即可将原来的网络修改为所选择的网络。

    2、在使用测量工具的时候,在Find处选择对象就一定会吸附到该对象中心,否则就可以选择任意位置。

    3、交换两个器件的位置

         Place--Swap--Components

    4、走线的模式

           在走线状态下,option状态栏下的bubble选项:

           off--走线的时候基本使用这种模式。

            hug only 推挤走线的时候只是hug不会移动走线。

           shove preferred推挤走线的时候会移动已经走好的线,不推荐这种模式。

    5、改变飞线布线模式

    有jogged和straight模式。

    Jogged:当飞仙呈水平或者垂直时自动显示有拐角的线段。

    Straight:最短的直线段。

    (因为之前用的AD所以一直习惯直线段的飞线模式,但是后来习惯之后还是觉得jogged的模式更合理。)

    6、内电层敷铜

    叠层设置好之后,该层是没有铜皮的,需要自己敷。(AD是设置完叠层就有了)

    先画一块在route keepin层的铜皮,这相当于设置了可以布线的区域,之后画的铜皮都会在这个框里面,当然走线也不能超出这个框。

    具体流程:

          a、只打开board outline层

          b、shape --compose shape,options和find处设置如下图设置完之后直接画一个大于outline层的框即可。

    Find处只需要选择line,不需要选择其他。

    有时候你框选了但是route keepin的shape没有出来。是因为你的outline处于fix状态,解锁之后就可以了。

           c、选择外框,右键选择expand/contract,需要缩进20mil。

            d、之后设置层数和网络直接铺一整块铜皮即可。铜皮基本选择dynamic模式。

    7、绕T型等长

     A、打开CM进行如下设置

      

     选择F1_DQS,右键creat-pin pair,则出现右边的选项框。First pin可以理解为源端,second可以理解为负载端,在T形网络中, 一个源端最多可以对应四个负载端,等长即从源端到每个负载端的长度一样。

    设置好pin pair之后按ok会出现这个警告,意思是设置完pin pair之后必须马上设置规则,否则过一段时间,设置的pin pair会消失,得重新设置。

    B、将F0的DQS、DQSN、DQ0~7、RE、REN选择好pin pair之后,就可以设置match group。

    需要将每个pin pair选中之后再右键creat-match group。如下图。(不要直接点网络创建match group,一定要点pin pair)

    C、match group设置好之后,设置等长基准,这边以DQS为基准(选择其中一个即可),右键set as target。然后在其他单元格设置允许误差的范围,一般为0:100mil。然后后面红色的数据表示超出范围,绿色的数据表示在范围内。

    打开检查模式。Setup--constraint--modes

    这个一定要打开,不然规则里面relative delay出不来,即如下图所示3列是没法显示的。

    D、之后就手动绕等长。

    1)这个是走蛇形线。Options如下设置。(差分最好走5W线宽)

      2)状态条没有显示了(摘录自网上)

    https://gss0.baidu.com/-vo3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/4afbfbedab64034f3d875a7facc379310a551d04.jpg

    https://gss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/wh%3D600%2C800/sign=4041aac184d6277fe9473a3e18083308/7c1ed21b0ef41bd56a2ed68e52da81cb39db3d4e.jpg

     F 、T型第一根引出的线可以走的比较长,但是延展到其他四个端点的线最好能走直线不要绕。虽然延伸出去的线是高阻状态,           但是它会有反射,先越长反射越大,所以尽量走短线。。

    net schedule,点击这个,点击想要查看的网络,可以查看从s端到d端的飞线。

             顺序是先让T区两端的线保持一样长,总长误差5mil以内的,比如DQS和DQSN这两根线,两端线的误差就要在1mil以内。            总长误差在100mil以内的,两端线的误差可以适当长一点。

    可以点击 ,然后选择想要查看的对象,查看线长信息。

    绕的之后掌握的技巧:

    先看一下这一个match group里面的线差距怎么样,然后找一个适当的长度,将基准线调成这个长度,然后先将误差比较小的线完成,之后绕误差相对可以大一点的。(一开始先调了基准线导致后面有些线无法缩小,之后得将所有线整体饶长)

    G、饶等长比较方便的命令。

    Route--timing vision

    这个功能直接让比基准长的一种颜色,比基准短的一种颜色,绕好的显示一种颜色,直接绕就好了,不用去看规则管理器。

    Route--auto-interactive delay tune

    选择命令,然后框选想要等长的线就好了。

    H、最近画好的板子在仿真的时候知道,等长不是根据基准DQS绕的,是需要组内所有长度误差都在30ps以内,所以一开始可以根据上述步骤调试,之后再根据仿真结果调试。30ps约等于200mil(经验值),以这个值调整出来的不会差很多。

     

    8、关于规则的有关设置

    set up--Constraints--modes

    这几个参数都需要设置,具体看公司要求。

    sapcing mode都需要打开,假如有些可以忽略的再waive掉。

    相同网络的靠太近也会报错,这个也需要都打开。

    9、导出设置

    1)导出选项

     File→Export→Sub-Drawing

    在Find 窗口中选择需要导出的选项,可以是option里面的任何东西,比如Line/shape/cline。

    2)在命令窗口输入x 0 0  (导出文件的参考基准坐标,Compelet完直接按X就可以不用去选下面的窗口,如果X被快捷键占用则使用pick)

    输完坐标后,按回车,弹出保存CLP文件的窗口,将CLP文件命名保存。

    3)导入选项

    将CLP文件放到需要导入的文件的当前目录下

    File→import→Sub-drawing选中需要导入的CLP文件

    输入基准坐标(想导入到哪个坐标,就输入什么坐标,基本为    x 0 0)

    回车完成导入。

    PS:要在两个PCB中相互导入Line/shape/cline需要两个文件的叠层层数和各层的名字一致,一般的操作,会将导出的文件的叠层改成和要导入的文件一致,如果要导入via,还需要在要导入的PCB的中也有这个via的路径

    10、铜皮不能自动更新

    铜皮属性是dynamic copper,但是修改的过程中他不会自动更新。可以选择shape--global dynamic shape parameters(这边改动之后所有铜皮都会修改为相应的设置)

    将dynamic fill设置为smooth即可。

    11、修改Shape属性的outline

    首先关闭其他东西,直留一个outline。

    然后shape--decompose shape,在option那边选择board geometry --outline。

    最后框选住整个outline就会变成board geometry属性的outline了。

    12、铜皮显示修改

    调高之后就可以正常显示,上图我总觉得和静态铜皮一样。

    13、画弧形线

    Route--unsupported prototypes--auto-interactive convert corner

    然后点击需要变弧形的线就可以整一条画弧形。

    14、工程性问题

    PCB完成后需要检查一下NPTH(非金属化孔)是不是有金属连接,有金属连接都需要改成PTH(金属化孔)。另外,NPTH也需要加上solder mask,假如不加板厂默认是塞孔。

    在建通孔pad或者Via时也把公差加上都按+/-4mil就可以了,安装孔和插接孔,只能大不能少,避免因为公差原因无法安装。(在出NC drill那边修改)

    调整字符时需要打开对应层的Solder mask和焊盘,宁愿删除也不要压到Solder mask上,所有的封装制作时都需要对应的Assembly层丝印,以免删除Silkscreen后没有备用。

    15、snap pick to

    这是一个很好用的操作,先选择一个命令,比如移动或者复制,然后鼠标移动到想到操作的目标附近,右键选择snap pick to。  (segment vertext为线段顶端,比较常用)之后目标会吸附在光标上,将目标移动到相应位置,再右键选择snap pick to,至此操作完成。

    在shape edit boundary时也很有用,因为假如铜皮的端点不在格点上的话是选中不了的,这个时候就可以选择snap pick to--segment vertsxt,这样就可以很容易的选中铜皮的端点。

    16、更换via的网络

    需要使用EDA365 skill

    3、route tools--change via’s net

    出现以下对话框,点击pick

    然后点击相应网络,done。

    再选择select,点击相应过孔,done

    17、Waive DRC

    Waive DRC之后还会显示是因为waive掉的DRC是在show的状态下。

    选择display--waive DRCs--blank即可关闭。当然选择show可以开启,在最后检查的时候可以选择show再检查一遍waive掉的DRC是否没有影响。

    18、铜皮过BGA

    敷铜过bga的时候会遇到以下问题

    这样的铜皮比较参考性就不是很好了。可以设置以下参数,shape select--选中铜皮右键--parameters即可出现以下对话框。

    将红圈标注位置设置为3.5即可变成下图所示

    这样铜皮就相对比较完整。

    需要说明一下这边的参数是在规则管理器设置的参数上面再额外加的。

    比如假如在规则里面设置shape to via的间距为4mil,然后又在parameters 这边设置via的间距为4mil,那么实际上shape to via的间距会变为8mil。

    19、update to smooth

    有的时候不能update to smooth,因为只有一个外框但是没有填充的shape是删除不了的。这个时候可以关闭所有图层然后打开bound。

    点击out of data shape前面那个小框,会出现对应没删除铜皮的坐标,点击坐标即可跳转到相应的铜皮,删除即可。

    20、复用布局和走线

    选择placement edit模式

    选择除group之外其他的选项,框选需要复用的布局,右键(需要选中元器件右键)place replicate create,在空白处右键done,会自动跳出需要保存的文件,命名后保存即可。

    然后选择还未布局的元器件(划重点!必须是一模一样,有一点不一样都会导致复用布局出错),右键(需要选中元器件右键,其他位置右键不会出来相应选项)place replicate apply,选择刚才保存的文件即可。

    复用一遍之后有改动需要再次复用时,需要先在placement edit 模式下选择group,然后右键disband group。然后再按之前的步骤即可复用。

    这个技巧操作过程中可能会出挺多错,有时候也会有元器件对不上的情况,但是你多试几遍熟悉了之后就会觉得挺方便的。

    展开全文
  • Linux的基本操作——基本介绍

    万次阅读 2019-07-05 16:12:36
    打个广告,帮朋友卖点东西,东西超便宜的哟【衣服鞋子等】,厂家直接出货,绝对低于市场价!!!一般都比市场价便宜3—7折【都是牌子货】,如果您感...单机操作系统 : windows(dos 、ucdos、win95、win98、win20...

    打个广告,帮朋友卖点东西,东西超便宜的哟【衣服鞋子等】,厂家直接出货,绝对低于市场价!!! 一般都比市场价便宜3—7折【都是牌子货】,如果您感兴趣,可以扫描屏幕下方的二维码,感谢关注!!!

    微信

    一、概述

    1、常见操作系统

    服务端操作系统 : linux、unix、windows server 

    单机操作系统 : windows(dos 、ucdos、win95、win98、win2000、xp、vista、win7、win8)

                             MAC 、linux(ubuntu)

    移动操作系统 Android、IOS 、Windows phone

    2、linux操作系统介绍

            Linux是一种自由和开放源码的类UNIX操作系统,它具有开放性,多用户,多任务,丰富的网络功能,可靠的系统安全,良好的可移植性,良好的用户界面(命令界面,图形界面等),出色的速度性能等优点。现在主要用于:

    • 大部分服务端都采用linux ,JEE部署到服务器中
    • 一些企业和学校采用linux研发和教学
    • 很多嵌入式开发 用linux 
    • 云计算、大数据 是集群网  linux : centos 

    Linux组成为:

    • linux内核(linus 团队管理)
    • shell :用户与内核交互的接口
    • 文件系统 : ext3、ext4 等  windows 有 fat32  、ntfs 
    • 第三方应用软件 

    Linux操作系统版本由内核版本 (linus 团队管理)和发行版本组成 (一些软件公司以内核为基础,再添加一些软件和文档形成发行版本),常见的发行版本有:

       - red hat  : rhel ,centos

       - debian   : debian,ubuntu(桌面)

       - android

    二、Linux系统环境

           默认有6个命令交互通道和一个图形界面交互通道,默认进入到的是图形界面通道其中:

    • 命令交互模式切换:ctrl+alt+f1---f6
    • 图形交互界面 ctrl+alt+f7

    1、图形界面交互模式

    • terminal: 图形界面的命令终端,它是图形界面交互通道的延伸,要依赖于图形界面

    2、命令交互模式 

    • 命令提示符:

          shen@ubuntu:~$ 

            - shen:用户名

    - ubuntu :主机名

    - ~  :路径 ,假如当前的路径正好是 该用户存放数据的根目录 ,则显示~

    - $ :用户的类型  $代表普通用户  #  代表 超级用户

    三、常用命令

    (按tab建自动补全)

    1、注销、关机、重启

    • 注销 :logout(登出 )或者exit(退出)

     

    • 关机 :shutdown - h  时间

      - h :关机

      - 时间 :

        1. now :马上

        2. 12.30 :指定具体时间

        3. 3  :几分钟以后

     

    注意:关机并不是每个用户都可以完成的,需要超级用户或者被授权的用户来执行该命令,普通用户要由超级用户配置  sudo 命令才能执行关机操作(权限放在这里/etc/sudoers),当普通用户被授权后即可通过【sudo shutdown -h now】来完成操作,sudo表示用超级用户的权限(被赋予的)来执行某命令,类似window中的以管理员身份运行

     

    • 重启 :shutdown -r  时间(权限问题和上面类似)

    2、系统命令

    • passwd   :设置密码

     ubuntu默认 root账号是没有开启 ,只要设置root密码即可开启【sudo passwd root】

    • su  :切换用户

    如su root ,root用户切换到其他账号不需要密码

    • sudo apt-get update

    更新系统

    • who与whoami

    其中

    who : 查看在线的用户

    whoami :查看当前自己的用户,如

     其中tty2代表哪个窗口(ctrl+alt+f2),pts/1表示图形化界面中开启的终端。

    • hostname : 显示主机名
    • uname  :显示系统信息

            -a :显示完整的系统信息

    • top :显示当前耗时的进程(部分)的信息 ,每3秒刷新一次,类似windows的任务管理器 (cltr+c 中断 )
    • ps :显示当前进程(全部)的快照 

           - axu

    • df :磁盘使用情况(disk free)
    • ifconfig :查看或者配置网卡信息 ,好比windows 的ipconfig
    • ping  测试与目标主机连接情况

    如测试本机与虚拟机中的连接情况,(本机ip:169.254.64.182,虚拟机ip:172.25.0.95),在虚拟机终端中,测试

    ping 169.254.64.182【按Ctrl+c结束】,在本机(cmd)中 ping 172.25.0.95

    •   netstat:网络连接详细信息
    • clear:清除屏幕(windows: cls)  
    • man:帮助命令

    可以查看命令的参数,如man ls

    • kill:杀死进程(kill  pid )
    • useradd:添加用户 

    首先来查看用户信息,命令为 sudo cat /etc/passwd,以其中一个用户信息介绍

     hadoop:x:1000:1000:UbuntuA,,,:/home/hadoop:/bin/bash

      - hadoop:用户名

      - x :密码 :已经加密 ,密码存放在  /etc/shadow 

      - 1000: 账号id ,userId

      - 1000: 组id ,group id

              - UbuntuA,,,  :账号描述

              - /home/hadoop :该账号存放文件的默认位置  ~

      - /bin/bash:该用户的shell脚本的解析方式  ,sh 、bash、rbash

     

    然后再来创建用户(以创建"lijing"用户为例),步骤如下:

    1.创建 /home/lijing 目录(在home下创建“lijing”文件)

    2. 执行 useradd 命令

       -d :指定该用户的home 路径 

       - s :该用户的shell解析方式

    3. 用 passwd 设置密码

    4. su 切换用户

    展开全文
  • 原子操作

    千次阅读 2019-08-12 10:13:28
    现代操作系统中,一般都提供了原子操作来实现一些同步操作,所谓原子操作,也就是一个独立而不可分割的操作。在单核环境中,一般的意义下原子操作中线程不会被切换,线程切换要么在原子操作之前,要么在原子操作完成...
  • p/v操作

    千次阅读 2018-03-29 15:33:52
    PV操作原语和信号量sem是计算机操作系统进程和线程同步的核心手段,虽然说起来只有句话,但有几个点非常容易引起模糊。先把PV操作的说明如下: P操作原语: sem 减1 若sem 大于等于0,线程继续执行. 若sem &lt;...
  • 操作系统——PV操作

    万次阅读 2018-10-30 10:58:57
    PV操作概念:操作系统中的一种同步机制,实现对于并发进程中临界区的管理。 并发进程分为两种: ①无交互的并发进程:每个进程是相互独立的,谁也不影响谁,基本不会用到PV操作。 ②有交互的并发进程:多个进程...
  • Git撤销&回滚操作

    万次阅读 多人点赞 2019-11-26 11:15:23
    糟了,我刚把不想要的代码,commit到本地仓库中了,但是还没有做push操作! 场景二: 彻底完了,刚线上更新的代码出现问题了,需要还原这次提交的代码! 场景三: 刚才我发现之前的某次提交太愚蠢了,现在想要...
  • cmd命令行下常见的注册表操作

    万次阅读 2020-08-10 16:47:22
    hkey local machine,本地计算机的系统信息,包括硬件与操作系统信息等。 HKEY USERS ,包括计算机默认用户的信息,当前用户信息,还有软件的配置信息,这里面有一个子键default很重要,新建用户的配置就根据这个...
  • 计算机操作系统核心知识点总结&面试笔试要点

    万次阅读 多人点赞 2020-04-19 17:41:01
    操作系统之基础篇 一、 操作系统概述  1. 操作系统的演进   无操作系统:人工操作,用户独占,CPU等待人工操作,资源利用率很低。   批处理系统:批量输入任务,无需等待人工操作,资源利用率提升,提出多道...
  • 原文出处:http://blog.csdn.net/dba_huangzj/article/details/8491327问题: 经常看到有人误删数据,或者误操作,特别是update和delete的时候没有加where,然后就喊爹喊娘了。人非圣贤孰能无过,做错可以理解,但...
  • Linux系统编程——系统调用之 I/O 操作(文件操作

    万次阅读 多人点赞 2015-06-03 14:35:28
    O:output,输出),对文件进行相应的操作( open()、close()、write() 、read() 等)。 打开现存文件或新建文件时,系统(内核)会返回一个文件描述符,文件描述符用来指定已打开的文件。这个文件描述符相当于...
  • 文章目录一:什么是操作系统?操作系统的定义:操作系统的作用:二:操作系统的发展1.单道批处理系统:单道处理系统的特点:单道处理系统的缺点:2.多道批处理系统多道处理系统的特点:多道处理系统的缺点:3.分时...
  • 操作系统与操作系统内核

    万次阅读 多人点赞 2017-07-07 16:21:37
    总的说来,一个操作系统包含了内核(是一个提供硬件抽象层、磁盘及文件系统控制、多任务等功能的系统软件)以及其他计算机系统所必须的组件(如函数库、编译器、调式工具、文本编辑器、网站服务器,以及一个Unix的...
  • 3. Git与TortoiseGit基本操作

    万次阅读 多人点赞 2017-01-15 18:18:55
    本节先简单介绍 git 的使用与操作, 然后再介绍 TortoiseGit 的使用与操作.
  • 内存映射 在 Linux操作系统中非常重要,因为其涉及到高效的跨进程通信 &amp; 文件操作 今天,我将详细讲解操作系统中核心概念:内存映射 目录 1. 定义 关联 进程中的1个虚拟内存区域 &amp; 1个磁盘上的...
  • 操作系统】——PV操作

    万次阅读 多人点赞 2015-04-12 14:48:05
    大家都说操作系统中的PV操作部分看不懂,确实我在专业课中学习这门课时,PV操作被列为书中的重点和难点,就是因为它不好理解。当时自己听完课也是一头雾水,到期末考试结束,也没弄明白这是怎么一回事,更没有意识到...
  • 一、原子操作概述 原子操作可以保证指令以原子的方式执行——执行过程不被打断。众所周知,原子原本指的是不可分割的微粒,所以原子操作也就是不能够被分割的指令 Linux内核提供的原子接口 内核提供了两组原子...
  • 汇编语言指令的语法结构是操作码+操作数(也存在只有操作码没有操作数的指令)①。 操作码表示的是指令动作,操作数表示的是指令对象。操作码和操作数罗列在一起的语法,就是一个英文的指令文本。操作码是动词,...
  • 对国产操作操系统的一点看法

    万次阅读 2019-07-20 23:34:42
    最近Deepin国产操作系统团队CTO王勇发表离职声明,让大家对国产操作系统的信心再次遇冷。 最近一个月看了一些关于国产操作系统文章,谈一下自己的想法吧。 国产操作系统是真命题还是伪命题 看到这个标题,估计...
1 2 3 4 5 ... 20
收藏数 10,217,550
精华内容 4,087,020
关键字:

操作