基础业务集成开发平台(BusinessWorks) - 业务开发篇

简介: BusinessWorks目前以二方包的形式提供给已有业务系统用来满足平台化建设,适应业务快速开发需要。在这边ATA中,我们会介绍我们代码的组织结构和基本实现, 然后会针对交易领域简化开发一个订单下单的例子,来阐述如何进行业务的模块化开发,实现业务隔离。

BusinessWorks目前以二方包的形式提供给已有业务系统用来满足平台化建设,适应业务快速开发需要。在这边ATA中,我们会介绍我们代码的组织结构和基本实现, 然后会针对交易领域简化开发一个订单下单的例子,来阐述如何进行业务的模块化开发,实现业务隔离。

1. 代码结构

ab15

  • businessworks-platform 是业务基础集成的平台实现

    • platform-common 提供平台的一些底层基础类库实现,包括对guice的扩展实现
    • platform-core 提供平台的一些核心功能实现,比如配置,jndi注册等。
    • platform-integration 提供apache camel的集成功能
    • platform-runtime 平台的运行期容器,负责启动平台容器,对容器内被管理对象进行生命周期管理
    • platform-web 提供平台的元数据已经运行监控的web功能。
  • businessworks-trade 是交易业务领域的demo实现

    • trade-domain 提供交易对象的demo实现,显现订单对象。
    • trade-toc 对订单提供超时功能扩展
    • trade-ump 对订单提供优惠功能扩展
  • businessworks-extension是业务方的扩展实现

    • trade-lifeservice-rest 提供生活服务业务的rest扩展
    • trade-lifeservice-toc 提供生活服务业务的超时实现
    • trade-lifeservice-ump 提供生活服务业务的优惠实现

目前businessworks-trade和businessworks-extension是业务开发的一个demo实现,用来阐述如果利用businessworks进行业务的扩展隔离开发。

2. 核心功能实现介绍

2.1 IAdaptable 接口扩展实现
a16

这三个接口: IAdapabable, IAdapatableFactory, IAdaptableManager 《从Eclipse平台看交易平台化》设计到的接口扩展实现。

2.2 Guice Module的定制实现

ab17

在Guice module基础上增加了模块的元数据信息,以及模块组装的一些实现。 比如ModuleBuiler,提供了模块组织在一起构建的builder类。

package com.taobao.businessworks.common.inject;

import com.google.common.collect.Lists;

import java.util.Iterator;
import java.util.List;

public class ModulesBuilder implements Iterable<Module> {

private final List<Module> modules = Lists.newArrayList();

public ModulesBuilder add(Module... modules) {
    for (Module module : modules) {
        add(module);
    }
    return this;
}

public ModulesBuilder add(Module module) {
    modules.add(module);
    if (module instanceof SpawnModules) {
        Iterable<? extends Module> spawned = ((SpawnModules) module).spawnModules();
        for (Module spawn : spawned) {
            add(spawn);
        }
    }
    return this;
}

@Override
public Iterator<Module> iterator() {
    return modules.iterator();
}

public Injector createInjector() {
    Modules.processModules(modules);
    Injector injector = Guice.createInjector(modules);
    Injectors.cleanCaches(injector);
    // in ES, we always create all instances as if they are eager singletons
    // this allows for considerable memory savings (no need to store construction info) as well as cycles
    ((InjectorImpl) injector).readOnlyAllSingletons();
    return injector;
}

public Injector createChildInjector(Injector injector) {
    Modules.processModules(modules);
    Injector childInjector = injector.createChildInjector(modules);
    Injectors.cleanCaches(childInjector);
    // in ES, we always create all instances as if they are eager singletons
    // this allows for considerable memory savings (no need to store construction info) as well as cycles
    ((InjectorImpl) childInjector).readOnlyAllSingletons();
    return childInjector;
}
}

2.3 Camel的guice集成

ab18
通过guice集成camel提供的流程编排功能,并且可以以guice模块的形式注册新的流程实现。

2.4 平台的启动
ab19

Bootstrap会启动一个Node作为运行时容器, 在这个node容器内,所有的模块会被组装运行起来,包括通过插件方式提供的模块实现。
ab20

        ModulesBuilder modules = Platform.getSystemModulesBuilder();
        modules.add(new Version.Module(version));
        modules.add(new PageCacheRecyclerModule(settings));
        modules.add(new PluginsModule(settings, pluginsService)); //插件管理模块
        modules.add(new SettingsModule(settings)); //配置模块
        modules.add(new NodeModule(this));//运行node模块
        modules.add(new NetworkModule()); //网络模块
        modules.add(new MonitorModule(settings));//监控模块
        modules.add(new JolokiaServerModule(settings));//Jolokia JMX模块
        modules.add(new EnvironmentModule(environment));//环境模块
        modules.add(new NodeEnvironmentModule(nodeEnvironment));//node环境模块
        modules.add(new ThreadPoolModule(settings));//线程池模块
        modules.add(new RestModule(settings)); //REST模块
        modules.add(new TransportModule(settings));//传输层实现模块

        if (settings.getAsBoolean(HTTP_ENABLED, true)) {
            modules.add(new HttpServerModule(settings)); //http服务模块
        }

        modules.add(new RegistryModule(settings)); //注册模块
        modules.add(new CamelRoutesModule()); //camel route管理模块
        modules.add(new RoutesModule());
        modules.add(new ActionModule(false));
        modules.add(new NodeClientModule());
        modules.add(new ExtensionsModule(settings));
        injector = modules.createInjector();

在 modules.add(new PluginsModule(settings, pluginsService)); //插件管理模块中, 这个模块会按照一定的规范把所有的第三方插件提供的模块加入到这个模块组里。从而达到系统功能,业务功能扩展的目的。 具体如何实现可以在后续实例。

3. Businessworks接入已有系统

对于目前存在的业务系统,如果想使用Businessworks平台提供的平台化功能,需要做一下步骤:

  1. 引入二方包依赖

    <dependency>
        <groupId>com.taobao.businessworks</groupId>
        <artifactId>platform-runtime</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>
            
  2. 如果是个web系统,可以增加一个ServletContextListener,用来在web启动时,启动Businessworks容器。
    public class BusinessworksListener implements ServletContextListener{

    /**

    • 配置Businessworks
      */

    @Override
    public void contextInitialized(ServletContextEvent sce) {

    String home = sce.getServletContext().getRealPath("/");
    System.setProperty("user.dir", home);
    System.setProperty("bw.foreground", "yes");
    Bootstrap.main(null);

    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {

    Bootstrap.close(null);    

    }
    }

Businessworks对guava,log4j有版本要求,需要注意升级到对应版本。
这样,你的业务系统就具有平台化的功能了。

4. 简单交易下单业务开发示例

首先描述下我们要开发的业务场景, 我们首先会在Businessworks的平台上开发一个简易下单功能。 然后我们会逐步扩展这个下单功能,增加订单超时,订单优惠功能,最后我们会以生活服务lifeservice业务方为例,提供lifeservice的特定实现。

4.1 交易领域开发

trade-domain 插件:

ab21

首先开发业务功能,我们需要定义业务领域对象, 这里我们会用IOrder接口来实现。

package com.taobao.businessworks.domain.order;

import java.util.List;

import com.taobao.businessworks.common.adaptable.IAdaptable;

public interface IOrder extends IAdaptable {
public void addItem(DrinkType drinkType, int shots, boolean iced);
public List<OrderItem> getItems();
public void putAttribute(String key, Object value);
public String getType();
public Object getAttribute(String key);
}

可以看到这个IOrder接口扩展了一个IAdaptable接口,后续我们可以看到这个接口的功能作用。 在看IOrder的具体实现类,我们可以发现他集成了PlatformObject这个抽象类,在这个类中有IAdaptable接口的实现。 这样Order对象就自动实现了IAdaptable。

package com.taobao.businessworks.domain.order;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.google.common.collect.Maps;
import com.taobao.businessworks.common.adaptable.PlatformObject;

public class Order extends PlatformObject implements IOrder{

private List<OrderItem> orderItems = new ArrayList<OrderItem>();

private int number;

private String type;

private float price;

private final Map<String, Object> attributes = Maps.newHashMap();

public Order(String type, int number) {
    this.type= type;
    this.number = number;
}

public String getType() {
    return type;
}

public void putAttribute(String key, Object value) {
    this.attributes.put(key, value);
}

public Object getAttribute(String key) {
    return this.attributes.get(key);
}

public void addItem(DrinkType drinkType, int shots, boolean iced) {
    this.orderItems.add(new OrderItem(this, drinkType, shots, iced));
}

public int getNumber() {
    return number;
}

public List<OrderItem> getItems() {
    return this.orderItems;
}

public float getPrice() {
    return price;
}

public void setPrice(float price) {
    this.price = price;
}

}

PlatformObject:

public abstract class PlatformObject implements IAdaptable {
/**
 * Constructs a new platform object.
 */
public PlatformObject() {
    super();
}

/**
 * Returns an object which is an instance of the given class
 * associated with this object. Returns <code>null</code> if
 * no such object can be found.
 * <p>
 * This implementation of the method declared by <code>IAdaptable</code>
 * passes the request along to the platform's adapter manager; roughly
 * <code>Platform.getAdapterManager().getAdapter(this, adapter)</code>.
 * Subclasses may override this method (however, if they do so, they
 * should invoke the method on their superclass to ensure that the
 * Platform's adapter manager is consulted).
 * </p>
 *
 * @param adapter the class to adapt to
 * @return the adapted object or <code>null</code>
 * @see IAdaptable#getAdapter(Class)
 */
public Object getAdapter(Class adapter) {
    return AdapterManager.getDefault().getAdapter(this, adapter);
}
}

将这个简单的订单模型加入到平台很简单,在实现一个插件类: 

package com.taobao.businessworks.domain;

import java.util.ArrayList;
import java.util.Collection;

import com.taobao.businessworks.common.inject.Module;
import com.taobao.businessworks.plugins.AbstractPlugin;
public class DomainPlugin extends AbstractPlugin {
public DomainPlugin() {
}

@Override
public String name() {
    return "trade-domain";
}

@Override
public String description() {
    return "trade domain Plugin";
}

@Override
public Collection<Class<? extends Module>> modules() {
    Collection<Class<? extends Module>> modules = new ArrayList<Class<? extends Module>>();
    modules.add(DomainModule.class);
    return modules;
}
}

这个plugin会被平台调用,通过modules()方法,将整个jar和包括的模块引入businessworks平台。
这样平台就具有了IOrder等模型的实现。

4.2 如何扩展开发领域功能

建设我们的简易下单系统需要增加超时功能和优惠功能。 按照我们以前的做法,我们会去IOrder接口里增加和超时或者 优惠相关的接口方法。这样带来的问题是我们的IOrder接口会随着业务功能的增加而膨胀,而且接口作为协议,已经对外暴露了,对基础接口的修改会导致依赖这个接口的上层代码的修改。 我们都知道作为核心类,应该尽可能保持它的稳定,这对业务系统的稳定和健壮也有很大的好处。

IAdaptable提供了一个优雅的实现让我们可以不改变IOrder接口,却可以给IOrder接口增加扩展的功能。

我们会以trade-toc这个项目为示例实现,来演示如果给交易这个领域增加超时功能。

ab23

首先我们会定义一个Toc接口,定义超时相关的功能:

public interface Toc extends TocComponent {

void setOrderConsignmentTimeout(IOrder order);    

void setOrderConfirmTimeout(IOrder order);    

int getOrderConsignmentTimeout(IOrder order);    

int getOrderConfirmTimeout(IOrder order);    

}

很简单,就是定义对订单设置确认收货超时和发货超时。

然后我们实现一个TocAdapterFactory工厂类,用来向平台注册IOrder的TOC扩展

package com.taobao.businessworks.toc;

import com.taobao.businessworks.common.adaptable.IAdapterFactory;
import com.taobao.businessworks.common.adaptable.IAdapterManager;
import com.taobao.businessworks.common.inject.Inject;
import com.taobao.businessworks.core.config.Platform;
import com.taobao.businessworks.domain.order.IOrder;
public class TocAdapterFactory implements IAdapterFactory {

private final TocsService tocsService;
@Inject
public TocAdapterFactory(TocsService tocsService) {
    this.tocsService = tocsService;
    IAdapterManager manager = Platform.getAdapterManager();
    manager.registerAdapters(this, IOrder.class);
    
}

@Override
public Object getAdapter(Object adaptableObject, Class adapterType) {
    if (adapterType == Toc.class) {
        IOrder order = (IOrder) adaptableObject;
        Toc toc = tocsService.toc(order.getType());
        if (toc== null) {
            toc = tocsService.toc("general");
        }
        return toc;
     }
    return null;
}

@Override
public Class[] getAdapterList() {
    return new Class[] { Toc.class };
}

}

这个类会将Toc接口注册到AdapterManger里,这样IOrder就可以通过getAdapter方法得到toc相关的功能。

接着我们将继续把toc相关的功能都在TOC模块中封装实现:
TocsModule:

public class TocsModule extends AbstractModule {

private final Settings settings;

private Map<String, Class<? extends Module>> tocTypes = Maps.newHashMap();

@Inject
public TocsModule(Settings settings) {
    this.settings = settings;
    registerToc("general", GeneralTocModule.class);
    registerToc("virtual", VirtualTocModule.class);
}

/**
 * Registers a custom river type name against a module.
 *
 * @param type   The type
 * @param module The module
 */
public void registerToc(String type, Class<? extends Module> module) {
    tocTypes.put(type, module);
}

@Override
protected void configure() {
    bind(TocsService.class).asEagerSingleton();
    bind(TocAdapterFactory.class).asEagerSingleton();
    bind(TocsTypesRegistry.class).toInstance(new TocsTypesRegistry(ImmutableMap.copyOf(tocTypes)));
}

}

这个类有如下功能:

  1. 绑定了TocAdapterFactory实现,注册toc对IOrder的扩展。
  2. 提供了一个toc超时业务子模块的注册机制。 从代码可以看到,我们默认提供了GeneralTocModule, VirtualTocModule两个缺省实现。
  3. 提供了一个TocsService辅助服务类,用来将toc模块的功能以service方式提供。

这种可扩展的模块机制,是我们业务扩展和隔离的基础,新的业务对应的接口实现,可以通过提供业务超时子模块的方式注册到超时富模块。

我们可以看一个GeneralTocModule的实现:

public class GeneralTocModule extends AbstractModule {

public GeneralTocModule() {
    super();
}

@Override
protected void configure() {
    bind(Toc.class).to(GeneralToc.class).asEagerSingleton();
}

}

在这里, 平台提供了超时的一个缺省实现GernalToc,

public class GeneralToc extends AbstractTocComponent implements Toc{

final TocSettings settings;

@Inject
public GeneralToc(TocName tocName, TocSettings settings) {
    super(tocName, settings);
    this.settings = settings;
}

@Override
public void setOrderConsignmentTimeout(IOrder order) {
    order.putAttribute("consignment_timeout", 100);
}

@Override
public int getOrderConsignmentTimeout(IOrder order) {
    return 100;
}

@Override
public void setOrderConfirmTimeout(IOrder order) {
    order.putAttribute("confirm_timeout", 200);
}

@Override
public int getOrderConfirmTimeout(IOrder order) {
    return 200;
}

最后通过TocPlugin这个类,将TocsModule注册到平台内,从而让订单具有了超时功能扩展。


public class TocPlugin extends AbstractPlugin {
public TocPlugin() {
}

@Override
public String name() {
    return "trade-toc";
}

@Override
public String description() {
    return "trade toc Plugin";
}

@Override
public Collection<Class<? extends Module>> modules() {
    Collection<Class<? extends Module>> modules = new ArrayList<Class<? extends Module>>();
    modules.add(TocsModule.class);
    return modules;
}
}

在extension-route这个插件里,我们注册扩展了两个restful api用来模拟下单的入口和实现:
http://localhost:9200/buy_general 代表生成一个general的订单,
http://localhost:9200/buy_virtual 代表生成一个virtual的订单,


public class RestBuyNowAction extends BaseRestHandler {

private final Version version;
private final CamelContext camelContext;

@Inject
public RestBuyNowAction(Settings settings, Version version, RestController controller, Client client, CamelContext camelContext) {
    super(settings, controller, client);
    this.version = version;
    this.camelContext = camelContext;
    controller.registerHandler(GET, "/buy_general", this);
    controller.registerHandler(HEAD, "/buy_general", this);
}

@Override
public void handleRequest(final RestRequest request, RestChannel channel, final Client client) throws Exception {

    RestStatus status = RestStatus.OK;
    if (request.method() == RestRequest.Method.HEAD) {
        channel.sendResponse(new BytesRestResponse(status));
        return;
    }

    XContentBuilder builder = channel.newBuilder();

    // Default to pretty printing, but allow ?pretty=false to disable
    if (!request.hasParam("pretty")) {
        builder.prettyPrint().lfAtEnd();
    }

    Order order = new Order("general",1);
    Toc toc = (Toc)order.getAdapter(Toc.class);
    if (toc!=null) {
        toc.setOrderConfirmTimeout(order);
        toc.setOrderConsignmentTimeout(order);
    }
    
    Ump ump = (Ump)order.getAdapter(Ump.class);
    if (ump!=null) {
        ump.setOrderPromation(order);
    }
    
    int consignment_timeout = toc.getOrderConsignmentTimeout(order);
    int confirm_timeout = toc.getOrderConfirmTimeout(order);
    
    float promotion = ump.getOrderPromation(order);
    
    builder.startObject();
    if (settings.get("name") != null) {
        builder.field("name", settings.get("name"));
    }
    builder.startObject("version")
            .field("confignment_timeout", consignment_timeout)
            .field("confirm_timeout",confirm_timeout)
            .field("promotion",promotion)
            .endObject();
    builder.endObject();

    channel.sendResponse(new BytesRestResponse(status, builder));
}

}

这个代码里:

    Toc toc = (Toc)order.getAdapter(Toc.class);

toc接口功过order的getAdapter的方式返回,在上面toc模快里TocAdapterFactory里, 解释了会根据order的type类型,返回对应的实现,这里会返回GenrealToc的实现。

我们可以通过在浏览器里输入url得到对应业务的toc和ump实现。

另外一乐buy_virtual的实现在类RestBuyVirtualAction中, 通过这两个实现对比,我们可以根据业务类型驱动平台调用对应的业务的超时和ump实现。

4.3 业务开发

下面我们再假设有个生活服务业务,需要对下单进行定制扩展, 生活服务订单会有自己特定的超时和ump优惠实现。 我们如何支持这个行业务呢:

第一步,实现一个extension-lifeservice-toc插件,里面会提供一个新的超时模块,注册对应的业务类型是“lifeservice”。

ab24

生活服务业务方会实现一个自己的Toc超时接口实现, 然后通过模块的形式封装,最后提供一个plugin实现类,将这个模块注册成为TocsModule的业务子模块:

public class LifeserviceTocPlugin extends AbstractPlugin {
public LifeserviceTocPlugin() {
}

@Override
public String name() {
    return "lifeservice toc";
}

@Override
public String description() {
    return "lifeservice toc extension Plugin";
}

public void onModule(TocsModule module) {
    module.registerToc("lifeservice", LifeserviceTocModule.class);
}

}

通过这个方式,生活服务对Toc超时的实现就已经注册到平台里,可以被使用了。

类似的方式我们可以开发生活服务的Ump模块。

最后我们开发一个restful API用来测试生活服务下单
http://localhost:9200/buy_lifeservice

ab25

public class RestLifeserviceBuyNowAction extends BaseRestHandler {

private final Version version;
private final CamelContext camelContext;

@Inject
public RestLifeserviceBuyNowAction(Settings settings, Version version, RestController controller, Client client, CamelContext camelContext) {
    super(settings, controller, client);
    this.version = version;
    this.camelContext = camelContext;
    controller.registerHandler(GET, "/buy_lifeservice", this);
    controller.registerHandler(HEAD, "/buy_lifeservice", this);
}

@Override
public void handleRequest(final RestRequest request, RestChannel channel, final Client client) throws Exception {

    RestStatus status = RestStatus.OK;
    if (request.method() == RestRequest.Method.HEAD) {
        channel.sendResponse(new BytesRestResponse(status));
        return;
    }

    XContentBuilder builder = channel.newBuilder();

    // Default to pretty printing, but allow ?pretty=false to disable
    if (!request.hasParam("pretty")) {
        builder.prettyPrint().lfAtEnd();
    }

    Order order = new Order("lifeservice",1);
    Toc toc = (Toc)order.getAdapter(Toc.class);
    toc.setOrderConfirmTimeout(order);
    toc.setOrderConsignmentTimeout(order);
    
    Ump ump = (Ump)order.getAdapter(Ump.class);
    ump.setOrderPromation(order);

    int consignment_timeout = toc.getOrderConsignmentTimeout(order);
    int confirm_timeout = toc.getOrderConfirmTimeout(order);
    
    float promotion = ump.getOrderPromation(order);
    
    builder.startObject();
    if (settings.get("name") != null) {
        builder.field("name", settings.get("name"));
    }
    builder.startObject("version")
            .field("confignment_timeout", consignment_timeout)
            .field("confirm_timeout",confirm_timeout)
            .field("promotion",promotion)
            .endObject();
    builder.endObject();
    channel.sendResponse(new BytesRestResponse(status, builder));
}
}

5. 总结

这边主要是针对业务开发和接入的实例性文档,在下一篇,会继续介绍业务流程的注册开发。同时也会对平台的一些基础功能模块做进一步介绍。

目录
相关文章
|
16天前
|
JavaScript 前端开发 持续交付
Prettier 高级应用:集成 CI/CD 流水线与插件开发
【10月更文挑战第18天】Prettier 是一款流行的代码格式化工具,它能够自动将代码格式化成一致的风格,从而提高代码的可读性和维护性。对于希望进一步发挥 Prettier 潜力的高级用户而言,将 Prettier 集成到持续集成(CI)和持续部署(CD)流程中,确保每次提交的代码都符合团队标准,是非常重要的。此外,通过开发自定义插件来支持更多语言或扩展 Prettier 的功能也是值得探索的方向。本文将详细介绍这两方面的内容。
35 2
|
23天前
|
数据采集 DataWorks 数据管理
DataWorks不是Excel,它是一个数据集成和数据管理平台
【10月更文挑战第10天】随着大数据技术的发展,企业对数据处理的需求日益增长。阿里云推出的DataWorks是一款强大的数据集成和管理平台,提供从数据采集、清洗、加工到应用的一站式解决方案。本文通过电商平台案例,详细介绍了DataWorks的核心功能和优势,展示了如何高效处理大规模数据,帮助企业挖掘数据价值。
73 1
|
29天前
|
数据采集 SQL DataWorks
DataWorks不是Excel,它是一个数据集成和数据管理平台
【10月更文挑战第5天】本文通过一家电商平台的案例,详细介绍了阿里云DataWorks在数据处理全流程中的应用。从多源数据采集、清洗加工到分析可视化,DataWorks提供了强大的一站式解决方案,显著提升了数据分析效率和质量。通过具体SQL示例,展示了如何构建高效的数据处理流程,突显了DataWorks相较于传统工具如Excel的优势,为企业决策提供了有力支持。
75 3
|
1月前
|
人工智能 自然语言处理 关系型数据库
阿里云云原生数据仓库 AnalyticDB PostgreSQL 版已完成和开源LLMOps平台Dify官方集成
近日,阿里云云原生数据仓库 AnalyticDB PostgreSQL 版已完成和开源LLMOps平台Dify官方集成。
|
22天前
|
Dart Android开发
鸿蒙Flutter实战:03-鸿蒙Flutter开发中集成Webview
本文介绍了在OpenHarmony平台上集成WebView的两种方法:一是使用第三方库`flutter_inappwebview`,通过配置pubspec.lock文件实现;二是编写原生ArkTS代码,自定义PlatformView,涉及创建入口能力、注册视图工厂、处理方法调用及页面构建等步骤。
41 0
|
26天前
|
开发框架 监控 搜索推荐
GoFly快速开发框架集成ZincSearch全文搜索引擎 - Elasticsearch轻量级替代为ZincSearch全文搜索引擎
本文介绍了在项目开发中使用ZincSearch作为全文搜索引擎的优势,包括其轻量级、易于安装和使用、资源占用低等特点,以及如何在GoFly快速开发框架中集成和使用ZincSearch,提供了详细的开发文档和实例代码,帮助开发者高效地实现搜索功能。
108 0
|
3月前
|
前端开发 Linux API
无缝融入,即刻智能[一]:Dify-LLM大模型平台,零编码集成嵌入第三方系统,42K+星标见证专属智能方案
【8月更文挑战第3天】无缝融入,即刻智能[一]:Dify-LLM大模型平台,零编码集成嵌入第三方系统,42K+星标见证专属智能方案
无缝融入,即刻智能[一]:Dify-LLM大模型平台,零编码集成嵌入第三方系统,42K+星标见证专属智能方案
|
2月前
|
编解码 Linux 开发工具
Linux平台x86_64|aarch64架构RTMP推送|轻量级RTSP服务模块集成说明
支持x64_64架构、aarch64架构(需要glibc-2.21及以上版本的Linux系统, 需要libX11.so.6, 需要GLib–2.0, 需安装 libstdc++.so.6.0.21、GLIBCXX_3.4.21、 CXXABI_1.3.9)。
|
3月前
|
Java API 数据中心
百炼平台Java 集成API上传文档到数据中心并添加索引
本文主要演示阿里云百炼产品,如何通过API实现数据中心文档的上传和索引的添加。
|
2月前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
148 0