当前位置: 首页>>代码示例>>Java>>正文


Java BoundSql.getSql方法代码示例

本文整理汇总了Java中org.apache.ibatis.mapping.BoundSql.getSql方法的典型用法代码示例。如果您正苦于以下问题:Java BoundSql.getSql方法的具体用法?Java BoundSql.getSql怎么用?Java BoundSql.getSql使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在org.apache.ibatis.mapping.BoundSql的用法示例。


在下文中一共展示了BoundSql.getSql方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Java代码示例。

示例1: intercept

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
@Override
public Object intercept(Invocation invocation) throws Throwable {
	RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget();
	StatementHandler delegate = (StatementHandler) ReflectUtil.getFieldValue(handler, "delegate");
	BoundSql boundSql = delegate.getBoundSql();
	Object obj = boundSql.getParameterObject();
	Page page = seekPage(obj);
	if (page != null) {
		MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getFieldValue(delegate, "mappedStatement");
		Connection connection = (Connection) invocation.getArgs()[0];
		String sql = boundSql.getSql();
		this.setTotalRecord(page, mappedStatement, connection);
		String pageSql = this.getPageSql(page, sql);
		ReflectUtil.setFieldValue(boundSql, "sql", pageSql);
	}
	return invocation.proceed();
}
 
开发者ID:lemon-china,项目名称:lemon-mybatis-plus,代码行数:18,代码来源:PageInterceptor.java

示例2: intercept

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
/**
 * 拦截后要执行的方法
 */
@Override
public Object intercept(Invocation invocation) throws Throwable {
    Page<?> page = PageThreadLocal.getThreadLocalPage();
    if (page == null) {
        return invocation.proceed();
    }
    PageThreadLocal.removeThreadLocalPage();
    RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget();
    // 通过反射获取到当前RoutingStatementHandler对象的delegate属性
    StatementHandler delegate = (StatementHandler) ReflectUtil.getFieldValue(handler, "delegate");
    BoundSql boundSql = delegate.getBoundSql();
    MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getFieldValue(delegate, "mappedStatement");
    // 获取当前要执行的Sql语句,也就是我们直接在Mapper映射语句中写的Sql语句
    String sql = boundSql.getSql();
    // 是否查询总页数和总数据 默认为TRUE
    if (page.getTotalFlag()) {
        // 给当前的page参数对象设置总记录数
        this.setTotalRecord(page, mappedStatement, boundSql, sql);
    }

    String pageSql = this.getPageSql(sql, page);
    // 利用反射设置当前BoundSql对应的sql属性为我们建立好的分页Sql语句
    ReflectUtil.setFieldValue(boundSql, "sql", pageSql);
    return invocation.proceed();
}
 
开发者ID:tonyruiyu,项目名称:dubbo-mock,代码行数:29,代码来源:PageInterceptor.java

示例3: intercept

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
@Override
public Object intercept(Invocation ivk) throws Throwable {
	if (ivk.getTarget().getClass()
			.isAssignableFrom(RoutingStatementHandler.class)) {
		final RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk
				.getTarget();
		final BaseStatementHandler delegate = (BaseStatementHandler) Reflection
				.getFieldValue(statementHandler, DELEGATE);
		final MappedStatement mappedStatement = (MappedStatement) Reflection
				.getFieldValue(delegate, MAPPED_STATEMENT);

		if (mappedStatement.getId().matches(SQL_PATTERN)) {
			// 拦截需要分页的SQL
			BoundSql boundSql = delegate.getBoundSql();
			// 分页SQL<select>中parameterType属性对应的实体参数,即Mapper接口中执行分页方法的参数,该参数不得为空
			Object parameterObject = boundSql.getParameterObject();
			if (null == parameterObject) {
				throw new NullPointerException("parameterObject尚未实例化!");
			} else {
				final Connection connection = (Connection) ivk.getArgs()[0];
				final String sql = boundSql.getSql();
				// 记录统计
				final int count = BaseParameter
						.getCount(sql, connection, mappedStatement,
								parameterObject, boundSql, DIALECT);
				Page page = null;
				page = convertParameter(parameterObject, page);
				page.init(count, page.getSize(), page.getLimit());
				String pagingSql = BaseParameter.generatePageSql(sql, page,
						DIALECT);
				// 将分页sql语句反射回BoundSql.
				Reflection.setFieldValue(boundSql, "sql", pagingSql);
			}
		}
	}
	return ivk.proceed();
}
 
开发者ID:jiangzongyao,项目名称:kettle_support_kettle8.0,代码行数:38,代码来源:PreparePaginationInterceptor.java

示例4: intercept

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
/**
   * Physical Pagination Interceptor for all the queries with parameter {@link org.apache.ibatis.session.RowBounds}
   */
  public Object intercept(Invocation invocation) throws Throwable {
      StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
      MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
      // 先判断是不是SELECT操作
      MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
      if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
          return invocation.proceed();
      }
      RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
      /* 不需要分页的场合 */
      if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
          return invocation.proceed();
      }
      BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
      String originalSql = boundSql.getSql();
      Connection connection = (Connection) invocation.getArgs()[0];
      DBType dbType = JdbcUtils.getDbType(connection.getMetaData().getURL());
      if (rowBounds instanceof Pagination) {
          Pagination page = (Pagination) rowBounds;
          if (page.isSearchCount()) {
              this.queryTotal(JsqlParserUtils.jsqlparserCount(originalSql), mappedStatement, boundSql, page, connection);
              if (page.getTotal() <= 0) {
                  return invocation.proceed();
              }
          }
          originalSql = DialectFactory.buildPaginationSql(page, originalSql, dbType, null);
      } else {
          // support physical Pagination for RowBounds
          originalSql = DialectFactory.buildPaginationSql(rowBounds, originalSql, dbType, null);
      }

/*
       * <p> 禁用内存分页 </p> <p> 内存分页会查询所有结果出来处理(这个很吓人的),如果结果变化频繁这个数据还会不准。</p>
 */
      metaStatementHandler.setValue("delegate.boundSql.sql", originalSql);
      metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
      metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
      return invocation.proceed();
  }
 
开发者ID:Caratacus,项目名称:mybatis-plus-mini,代码行数:43,代码来源:PaginationInterceptor.java

示例5: changeDataSource

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
private void changeDataSource(BoundSql boundSql) {
      String sql = boundSql.getSql();
/*if(sql.startsWith(SELECT)){
	//获取读集群的数据源
	DataSourceHolder.setSlave();
}else if(sql.startsWith(INSERT)||
		sql.startsWith(UPDATE)||
		sql.startsWith(DELETE)){
	//获取主库数据源
	DataSourceHolder.setMaster();
}*/
  }
 
开发者ID:geeker-lait,项目名称:tasfe-framework,代码行数:13,代码来源:WrInterceptor.java

示例6: getNamespaceSql

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
/**
 * 通过命名空间方式获取sql
 * @param session
 * @param namespace
 * @param params
 * @return
 */
public static String getNamespaceSql(SqlSession session, String namespace, Object params) {
    Configuration configuration = session.getConfiguration();
    MappedStatement mappedStatement = configuration.getMappedStatement(namespace);
    TypeHandlerRegistry typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
    BoundSql boundSql = mappedStatement.getBoundSql(params);
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    String sql = boundSql.getSql();
    if (parameterMappings != null) {
        for (int i = 0; i < parameterMappings.size(); i++) {
            ParameterMapping parameterMapping = parameterMappings.get(i);
            if (parameterMapping.getMode() != ParameterMode.OUT) {
                Object value;
                String propertyName = parameterMapping.getProperty();
                if (boundSql.hasAdditionalParameter(propertyName)) {
                    value = boundSql.getAdditionalParameter(propertyName);
                } else if (params == null) {
                    value = null;
                } else if (typeHandlerRegistry.hasTypeHandler(params.getClass())) {
                    value = params;
                } else {
                    MetaObject metaObject = configuration.newMetaObject(params);
                    value = metaObject.getValue(propertyName);
                }
                JdbcType jdbcType = parameterMapping.getJdbcType();
                if (value == null && jdbcType == null) jdbcType = configuration.getJdbcTypeForNull();
                sql = replaceParameter(sql, value, jdbcType, parameterMapping.getJavaType());
            }
        }
    }
    return sql;
}
 
开发者ID:itfsw,项目名称:mybatis-generator-plugin,代码行数:39,代码来源:SqlHelper.java

示例7: prepareStatement

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
  Statement stmt;
  BoundSql boundSql = handler.getBoundSql();
  String sql = boundSql.getSql();
  if (hasStatementFor(sql)) {
    stmt = getStatement(sql);
    applyTransactionTimeout(stmt);
  } else {
    Connection connection = getConnection(statementLog);
    stmt = handler.prepare(connection, transaction.getTimeout());
    putStatement(sql, stmt);
  }
  handler.parameterize(stmt);
  return stmt;
}
 
开发者ID:yuexiahandao,项目名称:MybatisCode,代码行数:16,代码来源:ReuseExecutor.java

示例8: doUpdate

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
@Override
public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {
  final Configuration configuration = ms.getConfiguration();
  final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
  final BoundSql boundSql = handler.getBoundSql();
  final String sql = boundSql.getSql();
  final Statement stmt;
  if (sql.equals(currentSql) && ms.equals(currentStatement)) {
    int last = statementList.size() - 1;
    stmt = statementList.get(last);
    applyTransactionTimeout(stmt);
   handler.parameterize(stmt);//fix Issues 322
    BatchResult batchResult = batchResultList.get(last);
    batchResult.addParameterObject(parameterObject);
  } else {
    Connection connection = getConnection(ms.getStatementLog());
    stmt = handler.prepare(connection, transaction.getTimeout());
    handler.parameterize(stmt);    //fix Issues 322
    currentSql = sql;
    currentStatement = ms;
    statementList.add(stmt);
    batchResultList.add(new BatchResult(ms, sql, parameterObject));
  }
// handler.parameterize(stmt);
  handler.batch(stmt);
  return BATCH_UPDATE_RETURN_VALUE;
}
 
开发者ID:yuexiahandao,项目名称:MybatisCode,代码行数:28,代码来源:BatchExecutor.java

示例9: interceptQuery

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
public Object interceptQuery(Invocation invocation) throws Throwable {
    /** statement is new Object with different memory address */
    StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
    BoundSql boundSql = statementHandler.getBoundSql();
    String sql = boundSql.getSql();
    System.out.println(statementHandler.getClass());
    System.out.println("sql->" + sql);
    ISqlParser iSqlParser = new DruidSqlParser();
    iSqlParser.init(sql);
    iSqlParser.setTableName("fuck");

    String masterColumn = "id";
    if (boundSql.getParameterObject() instanceof MapperMethod.ParamMap) {
        MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap) boundSql.getParameterObject();
        Object masterValue = paramMap.get(masterColumn);
        System.out.println("param-> " + masterValue);
    }

    String sqlResult = iSqlParser.toSql();
    System.out.println("sqlResult->" + sqlResult);

    Statement statement = (Statement) invocation.getArgs()[0];
    ReflectionUtils.setDeclaredFieldValue(boundSql, "sql", sqlResult);

    Object h = ReflectionUtils.getFieldValue(statement, "h");
    if (h instanceof PreparedStatementLogger) {
        PreparedStatementLogger preparedStatementLogger = (PreparedStatementLogger) h;
        PreparedStatement preparedStatement = preparedStatementLogger.getPreparedStatement();
    }
    System.out.println(statement.getClass().getName());
    System.out.println("sta-> " + statementHandler);
    return invocation.proceed();
}
 
开发者ID:maniaclee,项目名称:shardy,代码行数:34,代码来源:ShardInterceptor.java

示例10: getBoundSql

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
@Override
public BoundSql getBoundSql(Object parameterObject) {
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    /** thread local to transfer the value, for multi invoke */
    try {
        ReflectionUtils.setDeclaredFieldValue(boundSql, "sql", Transfer.getSqlShard());
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
        throw new ShardException("error setting the sql result for sql:" + boundSql.getSql());
    }
    return boundSql;
}
 
开发者ID:maniaclee,项目名称:shardy,代码行数:13,代码来源:ExtendedSqlSource.java

示例11: intercept

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
@Override
    public Object intercept(Invocation ivk) throws Throwable {
        if (ivk.getTarget().getClass().isAssignableFrom(RoutingStatementHandler.class)) {
            final RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk.getTarget();
            final BaseStatementHandler delegate = (BaseStatementHandler) Reflections.getFieldValue(statementHandler, DELEGATE);
            final MappedStatement mappedStatement = (MappedStatement) Reflections.getFieldValue(delegate, MAPPED_STATEMENT);

//            //拦截需要分页的SQL
////            if (mappedStatement.getId().matches(_SQL_PATTERN)) { 
//            if (StringUtils.indexOfIgnoreCase(mappedStatement.getId(), _SQL_PATTERN) != -1) {
                BoundSql boundSql = delegate.getBoundSql();
                //分页SQL<select>中parameterType属性对应的实体参数,即Mapper接口中执行分页方法的参数,该参数不得为空
                Object parameterObject = boundSql.getParameterObject();
                if (parameterObject == null) {
                    log.error("参数未实例化");
                    throw new NullPointerException("parameterObject尚未实例化!");
                } else {
                    final Connection connection = (Connection) ivk.getArgs()[0];
                    final String sql = boundSql.getSql();
                    //记录统计
                    final int count = SQLHelper.getCount(sql, connection, mappedStatement, parameterObject, boundSql, log);
                    Page<Object> page = null;
                    page = convertParameter(parameterObject, page);
                    page.setCount(count);
                    String pagingSql = SQLHelper.generatePageSql(sql, page, DIALECT);
                    if (log.isDebugEnabled()) {
                        log.debug("PAGE SQL:" + pagingSql);
                    }
                    //将分页sql语句反射回BoundSql.
                    Reflections.setFieldValue(boundSql, "sql", pagingSql);
                }
                
                if (boundSql.getSql() == null || "".equals(boundSql.getSql())){
                    return null;
                }
                
            }
//        }
        return ivk.proceed();
    }
 
开发者ID:EleTeam,项目名称:Shop-for-JavaWeb,代码行数:41,代码来源:PreparePaginationInterceptor.java

示例12: intercept

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
/**
 * Physical Pagination Interceptor for all the queries with parameter
 * {@link org.apache.ibatis.session.RowBounds}
 */
@Override
public Object intercept(Invocation invocation) throws Throwable {

    Object target = invocation.getTarget();
    if (target instanceof StatementHandler) {
        return super.intercept(invocation);
    } else {
        RowBounds rowBounds = (RowBounds) invocation.getArgs()[2];
        if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
            return invocation.proceed();
        }
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        Executor executor = (Executor) invocation.getTarget();
        Connection connection = executor.getTransaction().getConnection();
        Object parameterObject = invocation.getArgs()[1];
        BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
        String originalSql = boundSql.getSql();
        if (rowBounds instanceof Pagination) {
            Pagination page = (Pagination) rowBounds;
            if (page.isSearchCount()) {
                SqlInfo sqlInfo = SqlUtils.getCountOptimize(sqlParser, originalSql);
                super.queryTotal(overflowCurrent, sqlInfo.getSql(), mappedStatement, boundSql, page, connection);
                if (page.getTotal() <= 0) {
                    return invocation.proceed();
                }
            }
        }
    }
    return invocation.proceed();
}
 
开发者ID:baomidou,项目名称:mybatis-plus,代码行数:35,代码来源:CachePaginationInterceptor.java

示例13: intercept

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
@Override
public Object intercept(Invocation invocation) throws Throwable {
	final MappedStatement mappedStatement = (MappedStatement) invocation
			.getArgs()[0];
	// 拦截需要分页的SQL
	if (mappedStatement.getId().matches(SQL_PATTERN)) {
		Object parameter = invocation.getArgs()[1];
		BoundSql boundSql = mappedStatement.getBoundSql(parameter);
		String originalSql = boundSql.getSql().trim();
		if (null == boundSql.getSql() || "".equals(boundSql.getSql()))
			return null;
		// 分页参数--上下文传参
		Page page = null;
		PageContext context = PageContext.getPageContext();
		// map传参每次都将currentPage重置,先判读map再判断context
		if (null != parameter && null == context) {
			page = convertParameter(parameter, page);
		}
		// 分页参数--context参数里的Page传参
		if (null == page) {
			page = context;
		}

		if (null != page) {
			int totalPage = page.getTotal();
			// 得到总记录数
			if (totalPage == 0) {
				Connection connection = mappedStatement.getConfiguration()
						.getEnvironment().getDataSource().getConnection();
				totalPage = BaseParameter.getCount(originalSql, connection,
						mappedStatement, parameter, boundSql, DIALECT);
			}
			// 分页计算
			page.init(totalPage, page.getSize(), page.getLimit());
			invocation.getArgs()[2] = new RowBounds(
					RowBounds.NO_ROW_OFFSET, RowBounds.NO_ROW_LIMIT);
			BoundSql newBoundSql = new BoundSql(
					mappedStatement.getConfiguration(),
					BaseParameter.generatePageSql(originalSql, page,
							DIALECT), boundSql.getParameterMappings(),
					boundSql.getParameterObject());
			MappedStatement newMs = copyFromMappedStatement(
					mappedStatement, new BoundSqlSqlSource(newBoundSql));
			invocation.getArgs()[0] = newMs;
		}
	}
	PageContext.clear();
	return invocation.proceed();
}
 
开发者ID:jiangzongyao,项目名称:kettle_support_kettle8.0,代码行数:50,代码来源:PaginationInterceptor.java

示例14: intercept

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
@Override
public Object intercept(Invocation invocation) throws Throwable {
    Object[] queryArgs = invocation.getArgs();
    Object parameter = queryArgs[PARAMETER_INDEX];

    //在参数中获取分页的信息
    Pageable pageable = PaginationHelper.findObjectFromParameter(parameter, Pageable.class);
    Sort sort = PaginationHelper.findObjectFromParameter(parameter, Sort.class);
    if (pageable == null && sort == null) {
        //无需分页
        return invocation.proceed();
    }

    final MappedStatement ms = (MappedStatement) queryArgs[MAPPED_STATEMENT_INDEX];
    final BoundSql boundSql = ms.getBoundSql(parameter);
    String sql = boundSql.getSql();

    if (pageable == null) {
        // 仅排序
        String orderSql = PaginationHelper.applySortSql(sql, sort);
        queryArgs[MAPPED_STATEMENT_INDEX] = PaginationHelper.copyFromNewSql(ms, boundSql, orderSql);

        return invocation.proceed();
    }

    int total = PaginationHelper.queryForTotal(sql, ms, boundSql);

    //参数sort优先于pageable中的sort
    if (sort == null && pageable.getSort() != null) {
        sort = pageable.getSort();
    }
    if (sort != null) {
        sql = PaginationHelper.applySortSql(sql, sort);
    }

    //分页语句
    String pageSql = PaginationHelper.getPageSql(sql, ms, pageable.getOffset(), pageable.getPageSize());

    queryArgs[ROWBOUNDS_INDEX] = new RowBounds(RowBounds.NO_ROW_OFFSET, RowBounds.NO_ROW_LIMIT);
    queryArgs[MAPPED_STATEMENT_INDEX] = PaginationHelper.copyFromNewSql(ms, boundSql, pageSql);

    Object ret = invocation.proceed();
    Page<?> pi = new PageImpl<>((List<?>) ret, pageable, total);

    List<Page<?>> result = new ArrayList<>(1);
    result.add(pi);

    return result;
}
 
开发者ID:lodsve,项目名称:lodsve-framework,代码行数:50,代码来源:PaginationInterceptor.java

示例15: intercept

import org.apache.ibatis.mapping.BoundSql; //导入方法依赖的package包/类
@Override
public Object intercept(Invocation invocation) throws Throwable {
	
	String tenant = TenantContextHolder.getTenant();
	
	if(tenant == null || tenant == "") {
		System.out.println("tenant 为空,不需要改写sql语句");
		return invocation.proceed();
	}

	if (invocation.getTarget() instanceof RoutingStatementHandler) {

		System.out.println("aaaaaaa");
		RoutingStatementHandler statementHandler = (RoutingStatementHandler) invocation
				.getTarget();
		StatementHandler delegate = (StatementHandler) ReflectHelper
				.getFieldValue(statementHandler, "delegate");
		BoundSql boundSql = delegate.getBoundSql();
		Object obj = boundSql.getParameterObject();
		
		
		// 通过反射获取delegate父类BaseStatementHandler的mappedStatement属性
		MappedStatement mappedStatement = (MappedStatement) ReflectHelper
				.getFieldValue(delegate, "mappedStatement");
		// 拦截到的prepare方法参数是一个Connection对象
		Connection connection = (Connection) invocation.getArgs()[0];
		// 获取当前要执行的Sql语句,也就是我们直接在Mapper映射语句中写的Sql语句
		String sql = boundSql.getSql();
		// 给当前的page参数对象设置总记录数
		System.out.println("处理之前" + sql);
		//对 sql 增加 mycat 注解
		
		
		sql = "/*!mycat:schema=" + tenant + " */" + sql;
		
		System.out.println("加入处理后:" + sql);
		
		
		
		ReflectHelper.setFieldValue(boundSql, "sql", sql);
		
	}
	return invocation.proceed();
}
 
开发者ID:dingwpmz,项目名称:Mycat-Demo,代码行数:45,代码来源:TenantInterceptor.java


注:本文中的org.apache.ibatis.mapping.BoundSql.getSql方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。