第九章 Odoo 15开发之外部 API - 集成第三方系统

Odoo 服务端提供有外部 API,可供网页客户端和其它客户端应用使用。本章中我们将学习如何Odoo 的外部 API来实现将其Odoo服务端作为后端的外部应用。

可通过编写脚本来加载或修改Odoo数据,或是集成Odoo现有的业务应用,作为对Odoo应用一种补充。

我们将描述如何使用Odoo RPC调用,然后根据所学知识使用 Python为图书应用创建一个简单的命令行应用。

本章的主要内容有:

  • 介绍学习项目:图书目录的客户端应用
  • 在客户端机器上配置 Python
  • 探索Odoo的外部API
  • 实现客户端应用的XML-RPC接口
  • 实现客户端应用的用户界面
  • 使用OdooRPC库

学完本章后,读者可以创建一个简单的Python应用,使用Odoo作为后端进行查询和数据存储。

开发准备

本文基于第三章 Odoo 15开发之创建第一个 Odoo 应用创建的代码,具体代码请参见 GitHub 仓库。应将library_app模块放在addons路径下并进行安装。为保持前后一致,我们将使用第二章 Odoo 15开发之开发环境准备中的安装操作。本章完成后的代码请参见 GitHub 仓库。

学习项目-图书目录客户端

本文中,我们将开发一个简单的客户端应用来管理图书目录。这是一个命令行接口(CLI) 应用,使用 Odoo 来作为后端。应用的功能很基础,核心放在用于与 Odoo服务端交互的技术。

这个简单CLI应用可以完成如下功能:

  • 通过标题搜索并列出图书
  • 向目录添加新书籍
  • 编辑图书标题

我们的主要目标是使用Odoo对外API,因此不希望引用其它读者可能不太熟悉的编程语言。有了这一出发点,最好的方式是就是使用Python来实现客户端应用。不过只要掌握了一种语言的XML-RPC库,相关处理RPC的技术同样适用于其它语言。

这个应用是一个 Python 脚本,等待输入命令来执行操作。示例如下:

$ python3 library.py add "Moby-Dick"
$ python3 library.py list "moby"
60 Moby-Dick
$ python3 library.py set 60 "Moby Dick"

这个示例会话演示了如何使用客户端应用添加、列出及修改图书标题。

该客户端应用通过Python运行,在开始编写客户端应用代码之前,应确保在客户端机器上安装有Python。

在客户端机器上安装 Python

Odoo API 可以在外部通过两种协议访问:XML-RPC和JSON-RPC。任何外部程序,只要是能实现其中一种协议的客户端,就可以与 Odoo 服务端进行交互。为避免引入其它编程语言,我们将保持使用 Python 来探讨外部 API。

到目前为止我们仅在服务端运行了 Python 代码。现在我们要在客户端上使用 Python,所以你可能需要在电脑上做一些额外设置。

要学习本文的示例,你需要能在操作电脑上运行 Python 3 代码。如果在前面已按前面章节配置过开发环境,应该已经就绪了,否则请安装Python。

可通过在命令行终端运行python3 --version命令来进行确认。如果没有安装,请参考官方网站找到所使用的平台的安装包。

Ubuntu中通常预安装了 Python 3,如果没有安装,可通过以下命令进行安装:

sudo apt-get install python3 python3-pip

如果你使用的是 Windows 10,可通过微软应用商店进行安装。

在PowerShell中运行python3会直接引导你去相应的下载页面(这算是龟叔去微软后增加的福利吗?)。

通过一键安装包安装了Odoo的Windows用户可能会奇怪为什么Python解释器没有准备就绪。这时需要进行额外的安装。简单地说是因为 Odoo一键安装包内置了Python解析器,在操作系统层面无法直接使用。

现在读者已经安装好了Python,就可以开始使用Odoo对外API了。

学习Odoo外部 API

在实现客户端应用前应当先熟悉下Odoo外部API。以下小节中使用Python解释器一探XML-RPC API。

使用XML-RPC连接 Odoo API

访问Odoo服务最简单的方法是使用XML-RPC,我们可以使用 Python 标准库中的xmlrpclib来实现。

不要忘记我们是要编写客户端程序连接服务端,因此需运行 Odoo 服务端实例来供连接。本例中我们假设 Odoo 服务端实例在同一台机器上运行,http://localhost:8069 ,但读者可以使用任意运行着服务的其它机器,只需能连接其IP地址或服务器名。

Odoo的 xmlrpc/2/common端点暴露了公共方法,无需登录即可访问。可用于查看服务端版本及检测登录信息。我们使用xmlrpc库来研究对外可访问的Odoo API common

首先打开 Python 3终端并输入如下代码:

>>> from xmlrpc import client
>>> srv = "http://localhost:8069"
>>> common = client.ServerProxy("%s/xmlrpc/2/common" % srv)
>>> common.version()
{'server_version': '15.0', 'server_version_info': [15, 0, 0, 'final', 0, ''], 'server_serie': '15.0', 'protocol_version': 1}

以上代码导入了xmlrpc库,然后创建了一个包含服务端地址和监听端口信息的变量。请根据自身状况进行修改(如 Alan 使用srv = 'http://192.168.0.12:8069')。

下一步访问服务端公共服务(无需登录),在 /xmlrpc/2/common 端点上暴露。其中一个可用方法是version(),用于查看服务端版本。我们使用它来确认可与服务端进行通讯。

另一个公共方法是authenticate()。该方法确认用户名和密码可被接受,返回的用户 ID可用于后续请求。示例如下:

>>> db, user, password = "odoo-dev", "admin", "admin"
>>> uid = common.authenticate(db, user, password, {})
>>> print(uid)
2

authenticate()方法接收4个参数:数据库名、用户名、密码以及user agent。些前的代码通过变量存储这些信息,然后将使用这些变量传参。

ODOO 14中发生的改变

Odoo 14支持API密钥,可使用它来获取Odoo API外部访问权限。API密钥可在用户的首选项(Preferences)表单中进行设置,位于账号安全(Account Security)标签下。

用户代理(User Agent)环境用于提供有关客户端的元信息。为必填项,至少应传一个空字典 {}

若验证失败,返回值为False

common公共端点内容非常有限,要访问ORM API或是其它端点则需要先进行账号验证。

[图片上传失败...(image-ff9331-1669801418781)]

使用XML-RPC运行服务器端方法

要访问Odoo的模型及方法,需要使用xmlrpc/2/object。该端点要求先登录才能请求。

这个端点暴露了一个通用的execute_kw方法,接收模型名称、要调用的方法以及传递给方法的参数列表。

下面有一个演示execute_kw的示例。它调用了search_count方法,返回匹配域过滤器的记录数:

>>> api = client.ServerProxy('%s/xmlrpc/2/object' % srv)
>>> api.execute_kw(db, uid, password, 'res.users', 'search_count', [[]])
3

此处我们使用了xmlrpc/2/endpoint对象访问服务端 API。调用的方法名为execute_kw(),接收如下参数:

  • 连接的数据库名
  • 连接用户ID
  • 用户密码(或API密钥)
  • 目标模型名称
  • 调用的方法
  • 位置参数列表
  • 可选的关键字参数字典(本例中未使用)

可调用所有的模型方法,以下划线(_)开头的除外,这些是私有方法。有些的方法的返回值如果无法通过XML-RPC发送,则无法使用XML-RPC协议调用。browse()方法就属于这种情况,它返回的是一个记录集对象。使用XML-RPC调用browse()会返回TypeError: cannot marshal objects的报错。在进行XML-RPC调用时应将browse()换成read或是search_read,所返回的数据格式可通过XML-RPC协议发送给客户端。

下面我们就来看看如何通过searchread查询Odoo数据。

使用API方法searchread

Odoo的服务端使用browse来查询记录。在RPC客户端中无法使用它,因为记录集对象无法通过RPC协议进行传输。这时应当使用read方法。

read([, [])browse方法类似,但它返回的不是记录集,而是记录列表。每条记录都是包含请求字段及数据的字典。

下面来看如何通过read() 从Odoo获取数据:

>>> api = client.ServerProxy("%s/xmlrpc/2/object" % srv)
>>> api.execute_kw(db, uid, password, "res.users", "read", [2, ["login", "name", "company_id"]])
[{'id': 2, 'login': 'admin', 'name': 'Mitchell Admin', 'company_id': [1, 'YourCompany']}]

上例对res.users模型调用了read方法,传入了两个位置参数:记录ID 2 (也可以使用ID列表)以及获取字段的列表 ["login", "name", "company_id"],没传递关键字参数。

得到结果是一个字典列表,其中每个字典对应一条记录。对多字段的值有一种具体的表现形式。由记录ID和记录显示名组成的一对。例如,上例中返回的company_id的值为 [1, 'YourCompany']

可能会不知道记录ID,这时需要使用search调用来查找到匹配域过滤器的那些记录ID。

例如,想要查找管理员用户时,可使用 [("login", "=", "admin")]。这一RPC调用如下:

>>> domain = [("login", "=", "admin")]
>>> api.execute_kw(db, uid, password, "res.users", "search", [domain])
[2]

其结果是仅有一个元素(2)的列表,元素为admin用户的ID。

经常会使用search结合read方法查找符合域过滤器条件的ID,然后再获取它们的数据。在客户端应用中,这会反复调用服务端。可通过search_read方法进行简化,它可以一步就执行以上两个操作。

下例为使用search_read来查找admin用户并返回其名称:

>>> api.execute_kw(db, uid, password, "res.users", "search_read", [domain, ["login", "name"]])
[{'id': 2, 'login': 'admin', 'name': 'Mitchell Admin'}]

这个search_read方法使用了两个位置参数:包含域过滤器的列表,以及另一个包含需获取字段的列表。

search_read的参数如下:

  • domain: 域过滤器表达式列表
  • fields: 待获取字段名称列表
  • offset: 跳过的记录数或用于分页
  • limit: 返回的最大记录数
  • order: 用于ORDER BY语句的字符串

readsearch_readfields均为可选参数。如未提供,会获取所有的模型字段。但这可能会使用到大开销的字段计算并且会返回大量无需使用的数据。因此建议显式地提供字段列表。

execute_kw调用既可使用位置参数也可使用关键字参数。以下是把位置参数换成关键字参数的示例:

>>> api.execute_kw(db, uid, password, "res.users", "search_read", [], {"domain": domain, "fields": ["login", "name"]})
[{'id': 2, 'login': 'admin', 'name': 'Mitchell Admin'}]

获取数据时最常使用的就是search_read,但还存在其它方法用于写入数据或触发其它业务逻辑。

调用其它API方法

所有的其它模型方法也通过RPC对外暴露,那以下划线开头的私有方法除外。也就是说可以调用createwriteunlink来修改服务端的数据。

我们来看一个例子。以下代码新建一条partner记录,然后修改记录,再读取记录确定是否写入了修改,最后进行了删除:

>>> x = api.execute_kw(db, uid, password, "res.partner",
... "create",
... [{'name': 'Packt Pub'}])
>>> print(x)
63
>>> api.execute_kw(db, uid, password, "res.partner",
... "write",
... [[x], {'name': 'Packt Publishing'}])
True
>>> api.execute_kw(db, uid, password, "res.partner",
... "read",
... [[x], ["name"]])
[{'id': 63, 'name': 'Packt Publishing'}]
>>> api.execute_kw(db, uid, password, "res.partner",
... "unlink",
... [[x]])
True
>>> api.execute_kw(db, uid, password, "res.partner",
... "read",
... [[x]])
[]

XML-RPC的一个限制是它不支持None值。有一个XML-RPC插件可支持None值,但这取决于客户端使用的XML-RPC库。没有返回值的方法可能无法使用XML-RPC,因为这些方法隐式地返回None。这也是为什么方法的最佳实践要求有返回值,至少应返回True。另一个选择是使用JSON-RPC。OdooRPC库支持该协议,本文的使用OdooRPC库一节中会用到它。

模型中以下划线开头的方法被看作私有方法,无法通过XML-RPC对外暴露。

小贴士:通常客户端应用希望复制用户在Odoo表单中输入的内容。调用create()方法可能还不够,因为表单可能会使用onchange方法自动化操作一些字段,这通过表单交互触发,没经过create()。解决方案是在Odoo中创建一个自定义方法,其中使用create()方法并运行onchange方法中的操作。

有必须反复说明一下,Odoo的对外API大部分编程语言都可以使用。官方文档中包含有Ruby、PHP和Java使用示例。

至此,我们已学习到如何使用XML-RPC协议调用Odoo方法。接下来我们使用它来构建图书目录客户端应用。

实现图书客户端XML-RPC 接口

下面就来实现图书目录客户端应用。

可分为两个文件:一个是包含服务端后台的Odoo后台接口,library_xmlrpc.py,另一个用于用户界面,library.py。这让我们可以对后台接口使用替代的实现。

先从Odoo后台组件开始,LibraryAPI 类用于配置与Odoo服务端之间连接,以支持与Odoo交互所需的方法。所要实现的方法有:

  • search_read()</strong> 通过标题查找图书数据</li> <li> <strong>create(<title>)</strong> 使用指定标题创建图书</li> <li> <strong>write(<id>, <title>)</strong> 使用图书ID更新书名</li> <li> <strong>unlink(<id>)</strong> 使用ID删除图书</li> </ul> <p>在电脑上选择一个目录存放应用文件,并创建<strong>library_xmlrpc.py</strong>文件。先添加类的构造方法,如下:</p> <pre><code>import xmlrpc.client class LibraryAPI: def __init__(self, host, port, db, user, pwd): common = xmlrpc.client.ServerProxy( "http://%s:%d/xmlrpc/2/common" % (host, port)) self.api = xmlrpc.client.ServerProxy( "http://%s:%d/xmlrpc/2/object" % (host, port)) self.uid = common.authenticate(db, user, pwd, {}) self.pwd = pwd self.db = db self.model = "library.book" </code></pre> <p>类中存储了执行对目标模块调用所需的所有信息:API XML-RPC引用、<strong>uid</strong>、密码、数据库名以及模型名。</p> <p>对Odoo的RPC调用会使用相同的<strong>execute_kw</strong> RPC方法。下面对其添加一层封装,放在<strong>_execute()</strong> 私有方法中。它利用对象存储的数据提供更小的函数签名,如以下代码所示:</p> <pre><code> def _execute(self, method, arg_list, kwarg_dict=None): return self.api.execute_kw( self.db, self.uid, self.pwd, self.model, method, arg_list, kwarg_dict or {}) </code></pre> <p><strong>_execute()</strong> 私有方法用于让更高阶的方法实现更简洁。</p> <p>第一个公有方法是<strong>search_read()</strong>。它接收 一个可选字符串用于搜索书名。如未提供标题,则会返回所有记录。相应的实现如下:</p> <pre><code> def search_read(self, title=None): domain = [("name", "ilike", title)] if title else [] fields = ["id", "name"] return self._execute("search_read", [domain, fields]) </code></pre> <p><strong>create()</strong> 方法用于按给定书名创建新书并返回所创建记录的 ID:</p> <pre><code> def create(self, title): vals = {"name": title} return self._execute("create", [vals]) </code></pre> <p><strong>write()</strong> 方法中传入新书名和图书 ID 作为参数,对该书执行写操作:</p> <pre><code> def write(self, id, title): vals = {"name": title} return self._execute("write", [[id], vals]) </code></pre> <p>最后<strong>unlink()</strong> 方法用于删除给定ID的图书:</p> <pre><code> def unlink(self, id): return self._execute("unlink", [[id]]) </code></pre> <p>在该Python文件最后添加一段测试代码在运行时执行:</p> <pre><code>if __name__ == "__main__": # 测试配置 host, port, db = "localhost", 8069, "odoo-dev" user, pwd = "admin", "admin" api = LibraryAPI(host, port, db, user, pwd) from pprint import pprint pprint(api.search_read()) </code></pre> <p>如果执行以上 Python 脚本,我们可以打印出图书的内容:</p> <pre><code>$ python3 library_xmlrpc.py [{'id': 3, 'name': 'Brave New World'}, {'id': 2, 'name': 'Odoo 11 Development Cookbook'}, {'id': 1, 'name': 'Odoo Development Essentials 11'}] </code></pre> <p>现在已经有了对 Odoo 后台的简单封装,下面就可以处理命令行用户接口了。</p> <h2>实现客户端用户接口</h2> <p>我的目标是学习如何写外部应用和 Odoo 服务之间的接口,前面已经实现了。但不能止步于此,我们再为这个最小化客户端应用构建一个用户接口。</p> <p>为保持尽量简单,我们使用简单的命令行用户接口并避免使用其它依赖。那我们可以使用Python 内置功能和<strong>ArgumentParser</strong>库来实现这个命令行应用。代码如下:</p> <pre><code>from argparse import ArgumentParser from library_xmlrpc import LibraryAPI </code></pre> <p>下面我们来看看参数解析器接收的命令,有以下四条命令:</p> <ul> <li> <strong>list</strong> 搜索并列出图书</li> <li> <strong>add</strong> 添加图书</li> <li> <strong>set</strong> 修改书名</li> <li> <strong>del</strong> 删除图书</li> </ul> <p>实现以上命令的命令行解析代码如下:</p> <pre><code>parser = ArgumentParser() parser.add_argument( "command", choices=["list", "add", "set", "del"]) parser.add_argument("params", nargs="*") # 可选参数 args = parser.parse_args() </code></pre> <p>这里的args对象表示用户传入的参数。<strong>args.command</strong>是所用到的命令,在给定<strong>args.params</strong>时,其存储的是命令所使用的其它参数。</p> <p>如果未传参数或参数错误,参数解析器会进行处理,提示用户应该输入的内容。有关argparse更完整的说明,请参考官方文档。</p> <p>下一步是执行操作响应用户输入的命令。我们先创建一个<strong>LibraryAPI</strong>实例。这需要提供详细的Odoo连接信息,在我们的简单实现中采用了硬编码,代码如下:</p> <pre><code>host, port, db = "localhost", 8069, "odoo-dev" user, pwd = "admin", "admin" api = LibraryAPI(host, port, db, user, pwd) </code></pre> <p>第一行代码设置服务实例的一些固定参数以及要连接的数据库。本例中,我们连接本地 Odoo 服务(localhost),监听<strong>8069</strong>默认端口,并使用 <strong>odoo-dev</strong>数据库。如需连接其它服务器和数据库,请对参数进行相应调整。</p> <p>还需要添加代码处理每条命令。我们先从返回图书列表的<strong>list</strong>命令开始:</p> <pre><code>if args.command == "list": title = args.params[:1] if len(title) != 0: title = title[0] books = api.search_read(title) for book in books: print("%(id)d %(name)s" % book) </code></pre> <p>这里我们使用了<strong>LibraryAPI.search_read()</strong> 来从服务端获取图书记录列表。然后遍历列表中每个元素并打印。</p> <p>下面添加add命令:</p> <pre><code>if args.command == "add": title = args.params[0] book_id = api.create(title) print("Book added with ID %d for title %s." % (book_id, title)) </code></pre> <p>因为主要的工作已经在<strong>LibraryAPI</strong> 对象中完成,我们只要调用<strong>create()</strong> 方法并向终端用户显示结果即可。</p> <p><strong>set</strong>命令允许我们修改已有图书的书名,应传入两个参数,新书名和图书的 ID:</p> <pre><code>if args.command == "set": if len(args.params) != 2: print("set command requires a Title and ID.") else: book_id, title = int(args.params[0]), args.params[1] api.write(book_id, title) print("Title of Book ID %d set to %s." % (book_id, title)) </code></pre> <p>最终我们要实现 <strong>del</strong> 命令来删除图书记录。实现方式和之前并没有什么差别:</p> <pre><code>if args.command == "del": book_id = int(args.params[0]) api.unlink(book_id) print("Book with ID %s was deleted." % book_id) </code></pre> <p>客户端应用至此已完成,可以尝试使用一些命令。应该可以执行本文开头的那些命令。</p> <blockquote> <p>小贴士:在Linux系统中,可通过执行<strong>chmod +x library.py</strong>命令并在文件的首行添加<strong>#!/usr/bin/env python3</strong>来让<strong>library.py</strong>文件变为可执行。之后就可以在命令行中运行了<strong>./library.py</strong>。</p> </blockquote> <p>这是一个非常基础的应用,还有很多改进的方式。我们的目的是使用Odoo RPC API构建一个最小可用应用。</p> <p>[图片上传失败...(image-d08b9d-1669801418781)]</p> <h2>使用OdooRPC库</h2> <p>另一个可以考虑的客户端库是<strong>OdooRPC</strong>。它是一个完整的客户端库,把XML-RPC协议换成了JSON-RPC 协议。事实上 Odoo 官方客户端使用的就是JSON-RPC,XML-RPC更多是用于支持向后兼容性。</p> <blockquote> <p>ℹ️OdooRPC库现在由 OCA 管理和持续维护。了解更多请参见OCA。</p> </blockquote> <p><strong>OdooRPC</strong>库可通过PyPI安装:</p> <pre><code>pip3 install odoorpc </code></pre> <p><strong>OdooRPC</strong> 在新建 <strong>odoorpc.ODOO</strong> 对象时配置了服务端连接。此时我们应使用<strong>ODOO.login()</strong> 方法创建一个用户会话。和服务端一样,会员有一个包含会话环境的<strong>env</strong>属性,包括用户ID、<strong>uid</strong> 和上下文。</p> <p><strong>OdooRPC</strong>库可用于对服务端的<strong>library_xmlrpc.py</strong>接口提供一个替代实现。功能相同,只是把XML-RPC换成了JSON-RPC。</p> <p>创建<strong>library_odoorpc.py</strong> Python模块来对<strong>library_xmlrpc.py</strong>模块进行修改。新建的<strong>library_odoorpc.py</strong>文件中加入如下代码:</p> <pre><code>import odoorpc class LibraryAPI(): def __init__(self, host, port, db, user, pwd): self.api = odoorpc.ODOO(host, port=port) self.api.login(db, user, pwd) self.uid = self.api.env.uid self.model = "library.book" self.Model = self.api.env[self.model] def _execute(self, method, arg_list, kwarg_dict=None): return self.api.execute( self.model, method, *arg_list, **kwarg_dict) </code></pre> <p><strong>OdooRPC</strong>库实现<strong>Model</strong>和<strong>Recordset</strong>对象来模拟服务端对应的功能。目标是在客户端编程与服务端编程应基本一致。客户端使用的方法利用这点并在<strong>self.Mode</strong>l属性中存储对<strong>library.book</strong>模型引用,通过OdooRPC的<strong>env["library.book"]</strong>调用提供。</p> <p>这里同样实现了<strong>_execute()</strong>方法,可与XML-RPC版本进行对比。OdooRPC库中的<strong>execute()</strong>方法可运行指定的Odoo模型方法。</p> <p>下面我们来实现<strong>search_read(</strong>), <strong>create()</strong>, <strong>write()</strong>和<strong>unlink()</strong>这些客户端方法。在相同文件的<strong>LibraryAPI()</strong>类中添加如下方法:</p> <pre><code> def search_read(self, title=None): domain = [("name", "ilike", title)] if title else [] fields = ["id", "name"] return self.Model.search_read(domain, fields) def create(self, title): vals = {"name": title} return self.Model.create(vals) def write(self, id, title): vals = {"name": title} self.Model.write(id, vals) def unlink(self, id): return self.Model.unlink(id) </code></pre> <p>注意这段代码和 Odoo 服务端代码极其相似。</p> <p>可使用<strong>LibraryAPI</strong>对象替换<strong>library_xmlrpc.py</strong>。可通过编辑<strong>library.py</strong>文件将<strong>from library_xmlrpc import LibraryAPI</strong>一行替换为<strong>from library_odoorpc import LibraryAPI</strong>将其用作RPC连接层。然后对<strong>library.py</strong>客户端应用进行测试,执行效果应该是和之前一样的。</p> <h2>了解ERPpeek客户端</h2> <p>ERPpeek是一个多功能工具,既可以作为交互式命令行接口(CLI)也可以作为 Python库,它提供了比xmlrpc库更便捷的 API。它在PyPi索引中,可通过如下命令安装:</p> <pre><code>pip3 install erppeek </code></pre> <p>ERPpeek不仅可用作 Python 库,它还可作为 CLI 来在服务器上执行管理操作。Odoo shell 命令在主机上提供了一个本地交互式会话功能,而erppeek库则为网络上的客户端提供了一个远程交互式会话。打开命令行,通过以下命令可查看能够使用的选项:</p> <pre><code>erppeek --help </code></pre> <p>下面一起来看看一个示例会话:</p> <pre><code>$ erppeek --server='http://127.0.0.1:8069' -d odoo-dev -uadmin Usage (some commands): models(name) # List models matching pattern model(name) # Return a Model instance ... Password for 'admin': Logged in as 'admin' odoo-dev >>> model('res.users').count() 3 odoo-dev >>> rec = model('res.partner').browse(14) odoo-dev >>> rec.name 'Azure Interior' </code></pre> <p>如上所见,建立了服务端的连接,执行上下文引用了model() 方法来获得模型实例并对其进行操作。连接使用的erppeek.Client实例也可通过客户端变量来使用。 值得一提的是它可替代网页客户端来管理所安装的插件模块:</p> <ul> <li>client.modules()列出可用或已安装模块</li> <li>client.install()执行模块安装</li> <li>client.upgrade()执行模块升级</li> <li>client.uninstall()卸载模块</li> </ul> <p>因此ERPpeek可作为 Odoo 服务端远程管理的很好的服务。有关ERPpeek的更多细节请见 GitHub。</p> <p>[图片上传失败...(image-2b3826-1669801418781)]</p> <h2>小结</h2> <p>本文的目标是学习外部 API 如何运作以及它们能做些什么。一开始我们通过一个简单的Python XML-RPC客户端来进行探讨,但外部 API 也可用于其它编程语言。事实上官方文档中包含了Java, PHP和Ruby的代码示例。</p> <p>然后我们学习了如何使用XML-RPC调用搜索、读取数据,以及如何调用其它方法。比如我们可以创建、更新和删除记录。</p> <p>接着我们介绍了OdooRPC库。它在RPC基础库(XML-RPC 或 JSON-RPC) 上提供了一层,用于提供类似服务端API的本地API。这降低了学习曲线,减少了编程失误并且让在服务端和客户端之间拷贝代码变得更容易。</p> <p>以上我们就完结了本文有关编程 API 和业务逻辑的学习。是时候深入视图和用户界面了。在下一篇文章中,我们进一步学习后台视图以及web客户端提供的开箱即用的用户体验。</p> <h2>扩展阅读</h2> <p>以下参考资料可用于补充本文所学习的内容:</p> <ul> <li>Odoo web服务的官方文档中包含了Python以外编程语言的代码示例。</li> <li>OdooRPC文档</li> <li>ERPpeek文档</li> </ul> </article> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1713510933030055936"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(第九章 Odoo 15开发之外部 API - 集成第三方系统)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1902659669063692288.htm" title="《React开发实践:掌握Redux与Hooks应用》——开启你的前端进阶之旅" target="_blank">《React开发实践:掌握Redux与Hooks应用》——开启你的前端进阶之旅</a> <span class="text-muted">JJCTO袁龙</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a> <div>文章标题《React开发实践:掌握Redux与Hooks应用》——开启你的前端进阶之旅在前端开发的浪潮中,React.js已经成为开发者们不可或缺的利器。它以其高效、灵活的特性,成为构建现代Web应用的首选框架之一。然而,随着项目复杂度的增加,如何更好地管理状态、优化性能、提升代码可维护性,成为每个开发者必须面对的挑战。幸运的是,我最近出版的《React开发实践:掌握Redux与Hooks应用》这</div> </li> <li><a href="/article/1902659415811616768.htm" title="批量请求微信小程序封禁状态的C++代码示例" target="_blank">批量请求微信小程序封禁状态的C++代码示例</a> <span class="text-muted">安丨</span> <a class="tag" taget="_blank" href="/search/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">微信小程序</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">小程序</a> <div>概述:此C++代码示例将展示如何批量请求指定API接口,检查微信小程序是否被封禁。根据返回的code值,我们可以判断小程序是否被封禁,code为0时表示小程序被封禁,code为1表示正常。代码介绍:目标:通过C++编写批量请求的代码,检查多个小程序的封禁状态。使用的库:使用libcurl库来发送HTTP请求。libcurl是一个强大的库,广泛用于在C++中进行网络请求。API接口:https://</div> </li> <li><a href="/article/1902659416839221248.htm" title="Rust语言介绍和猜数字游戏的实现" target="_blank">Rust语言介绍和猜数字游戏的实现</a> <span class="text-muted">栖林_</span> <a class="tag" taget="_blank" href="/search/Rust/1.htm">Rust</a><a class="tag" taget="_blank" href="/search/rust/1.htm">rust</a><a class="tag" taget="_blank" href="/search/%E6%B8%B8%E6%88%8F/1.htm">游戏</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>文章目录Rust语言介绍和猜数字游戏的实现cargo是什么使用Rust编写猜数字Rust语言介绍和猜数字游戏的实现Rust语言是一种系统编程语言,核心强调安全性、并发性以及高性能,由类似于C/C++的底层控制能力,性能也非常接近,Rust有一些特性所有权系统,这个可以自动管理内存,无需垃圾回收器,保证数据的安全零成本抽象,高层抽象不会带来运行时的开销,运行时的效率会很高线程安全,在编译阶段就能防止</div> </li> <li><a href="/article/1902659037737054208.htm" title="Webpack常见面试题总结" target="_blank">Webpack常见面试题总结</a> <span class="text-muted">xiangzhihong8</span> <a class="tag" taget="_blank" href="/search/React/1.htm">React</a><a class="tag" taget="_blank" href="/search/Native/1.htm">Native</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/webpack/1.htm">webpack</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>一、谈谈你对Webpack的理解1.1背景Webpack的目标是实现前端项目的模块化,从而更高效地管理和维护项目中的每一个资源。在早期的前端项目中,我们通过文件划分的形式来实现模块化,也就是将每个功能及其相关状态数据各自单独放到不同的JS文件中。约定每个文件是一个独立的模块,然后再将这些js文件引入到页面,一个script标签对应一个模块,然后再调用模块化的成员。比如:但这种模块化开发的弊端也十分</div> </li> <li><a href="/article/1902658407022784512.htm" title="计算机专业毕业设计指南" target="_blank">计算机专业毕业设计指南</a> <span class="text-muted">晴天毕设</span> <a class="tag" taget="_blank" href="/search/%E8%AF%BE%E7%A8%8B%E8%AE%BE%E8%AE%A1/1.htm">课程设计</a><a class="tag" taget="_blank" href="/search/%E6%AF%95%E4%B8%9A%E8%AE%BE%E8%AE%A1/1.htm">毕业设计</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>毕业设计是计算机专业学生展示综合能力的重要环节,它不仅是对所学知识的总结,也是进入职场或深造前的实战演练。本文将为你提供一份详细的毕业设计指南,帮助你从选题到答辩顺利完成毕业设计。如果有什么问题可以点击文章末尾名片咨询哦一、毕业设计流程概述毕业设计通常包括以下几个阶段:选题需求分析系统设计编码实现测试与优化论文撰写答辩准备每个阶段都有其重要性,下面将逐一详细说明。二、详细步骤1.选题选题是毕业设计</div> </li> <li><a href="/article/1902657776501452800.htm" title="初级面试题:数据类型面试题大揭秘" target="_blank">初级面试题:数据类型面试题大揭秘</a> <span class="text-muted">佩奇的技术笔记</span> <a class="tag" taget="_blank" href="/search/Java%E9%9D%A2%E8%AF%95%E5%B0%8F%E5%86%8C/1.htm">Java面试小册</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>一、引言在Java开发的面试中,数据类型相关的问题经常出现。面试官通过这些问题考察候选人对Java基础的理解程度以及在实际开发中对数据类型的运用能力。本文将深入剖析常见的数据类型面试题,帮助读者全面掌握这些知识点。二、基本数据类型与引用数据类型面试题:int和Integer的区别是什么?答案:int是基本数据类型,占用4个字节内存,直接存储数值;Integer是int对应的引用数据类型,即包装类,</div> </li> <li><a href="/article/1902657272673267712.htm" title="qt-5.15.2 源码编译 Linux" target="_blank">qt-5.15.2 源码编译 Linux</a> <span class="text-muted">weixin_40857106</span> <a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/1.htm">运维</a> <div>QT官方源码下载地址:https://download.qt.io/archive/qt/5.15/5.15.12/single/qt-everywhere-opensource-src-5.15.12.tar.xz安装Qt所需的依赖:sudoaptinstallbuild-essentiallibgl1-mesa-devlibxkbcommon-devlibnss3-devlibdbus-1-d</div> </li> <li><a href="/article/1902656013656453120.htm" title="最完整的webpack Dll打包与采坑总结" target="_blank">最完整的webpack Dll打包与采坑总结</a> <span class="text-muted">仰望星空的代码</span> <a class="tag" taget="_blank" href="/search/Vue.js%E8%B8%A9%E5%9D%91%E8%AE%B0/1.htm">Vue.js踩坑记</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/webpack/1.htm">webpack</a><a class="tag" taget="_blank" href="/search/dll%E6%89%93%E5%8C%85/1.htm">dll打包</a><a class="tag" taget="_blank" href="/search/%E6%89%93%E5%8C%85%E4%BC%98%E5%8C%96/1.htm">打包优化</a> <div>webpack已经成为前端主流的项目打包工具,对于前端开发必不可少。在前端项目依赖第三方库过多,项目比较大文件比较多时,webpack打包的速度也会被拖成蜗牛,是时候优化一下webapck的打包速度了。在优化打包速度方面有不少方法方式,其中一个比较重要的方式是DllPlugin。DllPlugin把第三方库打包成动态链接库(动态链接库:windows系统中库文件概念,这里是借用了这一概念。),Dl</div> </li> <li><a href="/article/1902654501781827584.htm" title="Hugging Face 模型格式全解析:从 PyTorch 到 GGUF" target="_blank">Hugging Face 模型格式全解析:从 PyTorch 到 GGUF</a> <span class="text-muted">mingo_敏</span> <a class="tag" taget="_blank" href="/search/Deep/1.htm">Deep</a><a class="tag" taget="_blank" href="/search/Learning/1.htm">Learning</a><a class="tag" taget="_blank" href="/search/pytorch/1.htm">pytorch</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a> <div>HuggingFace模型格式全解析:从PyTorch到GGUFHuggingFace生态支持多种模型格式,以满足不同场景下的存储、部署和推理需求。以下是主流格式的技术解析与演进脉络:1.PyTorch原生格式(.pt/.pth)特性:直接保存PyTorch的state_dict(模型参数)或完整模型(含结构)。兼容性强,与PyTorch训练/推理流程深度集成。文件体积较大,加载速度较慢,存在安全</div> </li> <li><a href="/article/1902653616892735488.htm" title="python练习3:输入某年某月某日,判断这一天是这一年的第几天?" target="_blank">python练习3:输入某年某月某日,判断这一天是这一年的第几天?</a> <span class="text-muted">柯.姐姐</span> <a class="tag" taget="_blank" href="/search/python/1.htm">python</a> <div>#输入某年某月某日,判断这一天是这一年的第几天?list=[0,31,59,90,120,151,181,212,243,273,304,334]year=int(input('请输入年份:'))month=int(input('请输入月份:'))day=int(input('请输入天:'))ifmonth>0andmonth2:result=result+1print("这是第%d天"%resu</div> </li> <li><a href="/article/1902653238423908352.htm" title="Java WebSocket与项目页面(通常是HTML + JavaScript)之间建立连接并传输数据" target="_blank">Java WebSocket与项目页面(通常是HTML + JavaScript)之间建立连接并传输数据</a> <span class="text-muted">hh_fine</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/websocket/1.htm">websocket</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a> <div>JavaWebSocket与项目页面(通常是HTML+JavaScript)之间建立连接并传输数据1.创建JavaWebSocket服务器:使用JavaWebSocketAPI创建一个WebSocket服务器端点。2.在HTML页面中使用JavaScript连接WebSocket:通过JavaScript的WebSocketAPI与JavaWebSocket服务器建立连接。3.双向数据传输:实现服</div> </li> <li><a href="/article/1902653112125026304.htm" title="RuoYi框架连接SQL Server时解决“SSL协议不支持”和“加密协议错误”" target="_blank">RuoYi框架连接SQL Server时解决“SSL协议不支持”和“加密协议错误”</a> <span class="text-muted">专注代码十年</span> <a class="tag" taget="_blank" href="/search/ssl/1.htm">ssl</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE/1.htm">网络协议</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a> <div>RuoYi框架连接SQLServer时解决“SSL协议不支持”和“加密协议错误”在使用RuoYi框架进行开发时,与SQLServer数据库建立连接可能会遇到SSL协议相关的问题。以下是两个常见的错误信息及其解决方案。错误信息1com.zaxxer.hikari.pool.HikariPool$PoolInitializationException:Failedtoinitializepool;'e</div> </li> <li><a href="/article/1902652985838727168.htm" title="SGM61230 同步降压转换器技术文档" target="_blank">SGM61230 同步降压转换器技术文档</a> <span class="text-muted">慎独yfs</span> <a class="tag" taget="_blank" href="/search/%E7%94%B5%E5%AD%90%E5%85%83%E5%99%A8%E4%BB%B6/1.htm">电子元器件</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA/1.htm">单片机</a><a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%A1%AC%E4%BB%B6/1.htm">嵌入式硬件</a> <div>第一章概述SGM61230是一款宽输入电压范围(4.5V至28V)的同步降压转换器,可提供高达3A的输出电流。该器件集成功率开关和峰值电流模式控制补偿电路,采用6引脚TSOT-23封装,内置5ms软启动功能以抑制浪涌电流。关键特性:-**智能保护机制**:逐周期峰值电流限制、输出过压保护(OVP)、带自动恢复的热关断-**高效模式切换**:轻载时进入脉冲跳过模式(PSM),重载时自动切换至PWM模</div> </li> <li><a href="/article/1902650969435467776.htm" title="Lodash源码分析-every,some,size,includes" target="_blank">Lodash源码分析-every,some,size,includes</a> <span class="text-muted">初学者7.</span> <a class="tag" taget="_blank" href="/search/Loadsh%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/1.htm">Loadsh源码分析</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>collection相关的函数,collection指的是一组用于处理集合(如数组或对象)的工具函数。lodash源码研读之every,some,size,includes一、源码地址GitHub地址:GitHub-lodash/lodash:AmodernJavaScriptutilitylibrarydeliveringmodularity,performance,&extras.官方文档地址</div> </li> <li><a href="/article/1902650717357797376.htm" title="Lodash源码分析-uniq,uniqBy,uniqWith" target="_blank">Lodash源码分析-uniq,uniqBy,uniqWith</a> <span class="text-muted">初学者7.</span> <a class="tag" taget="_blank" href="/search/Loadsh%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/1.htm">Loadsh源码分析</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>lodash源码研读之uniq,uniqBy,uniqWith一、源码地址GitHub地址:GitHub-lodash/lodash:AmodernJavaScriptutilitylibrarydeliveringmodularity,performance,&extras.官方文档地址:Lodash官方文档二、结构分析uniq,uniqBy,uniqWith基于baseUniq模块。三、函数介</div> </li> <li><a href="/article/1902650591079886848.htm" title="H5语音识别功能(Web Speech API+科大讯飞)" target="_blank">H5语音识别功能(Web Speech API+科大讯飞)</a> <span class="text-muted">辣辣1</span> <a class="tag" taget="_blank" href="/search/%E8%AF%AD%E9%9F%B3%E8%AF%86%E5%88%AB/1.htm">语音识别</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>H5语音识别效果图:方案一:WebSpeechAPI(免费,IE浏览器可用,谷歌浏览器不可用)方案一:WebSpeechAPI开始停止识别结果:{{finalTranscript}}{{interimTranscript}}import{ref,onMounted,onBeforeUnmount}from"vue";constisSupported=ref(false);constisRecord</div> </li> <li><a href="/article/1902650464785199104.htm" title="CUDA编程基础" target="_blank">CUDA编程基础</a> <span class="text-muted">清 澜</span> <a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95%E9%9D%A2%E8%AF%95/1.htm">算法面试</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/nvidia/1.htm">nvidia</a><a class="tag" taget="_blank" href="/search/cuda%E7%BC%96%E7%A8%8B/1.htm">cuda编程</a> <div>一、快速理解CUDA编程1.1CUDA简介CUDA(ComputeUnifiedDeviceArchitecture)是由NVIDIA推出的并行计算平台和应用程序接口模型。它允许开发者利用NVIDIAGPU的强大计算能力来加速通用计算任务,而不仅仅是图形渲染。通过CUDA,开发者可以编写C、C++或Fortran代码,并将其扩展以在GPU上运行,从而显著提高性能,特别是在处理大规模数据集和复杂算法</div> </li> <li><a href="/article/1902649582874062848.htm" title="《Flutter从入门到实战:手把手构建跨平台应用(万字深度解析)》" target="_blank">《Flutter从入门到实战:手把手构建跨平台应用(万字深度解析)》</a> <span class="text-muted">前端极客探险家</span> <a class="tag" taget="_blank" href="/search/flutter/1.htm">flutter</a> <div>目录标题前言:为什么选择Flutter?一、Flutter基础篇:环境搭建与核心概念1.1开发环境配置1.2项目结构深度解析二、核心机制:Widget与渲染原理2.1Widget树构建原理2.2状态管理方案对比三、企业级开发实战3.1工程化架构设计3.2典型功能实现四、进阶开发技巧4.1性能优化方案4.2平台特定代码集成五、项目实战:开发企业级Todo应用(深度扩展版)5.1项目初始化与工程化配置</div> </li> <li><a href="/article/1902649330234355712.htm" title="AI编程的心得体会" target="_blank">AI编程的心得体会</a> <span class="text-muted">猜测7</span> <a class="tag" taget="_blank" href="/search/AI%E7%BC%96%E7%A8%8B/1.htm">AI编程</a><a class="tag" taget="_blank" href="/search/chatgpt/1.htm">chatgpt</a> <div>最近使用了三款AI软件进行编程,真的是一款比一款好用,很大程度提高了写代码的效率,真的非常方便。首先是豆包的插件Marscode,我知道它B站首页曾经见到一个推荐,标题大意是不写一行代码开发出一个打砖块的游戏。我对着视频试了一遍,在VSCode中可以直接搜索安装Marscode,用的phython写的小游戏,结果发现其实最核心的架构玩法其实都在它clonegithub那步,就是把已经能运行的游戏拿</div> </li> <li><a href="/article/1902648321994977280.htm" title="推荐一个开源的高效头像生成工具,支持API调用" target="_blank">推荐一个开源的高效头像生成工具,支持API调用</a> <span class="text-muted">计算机小手</span> <a class="tag" taget="_blank" href="/search/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/1.htm">经验分享</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E6%BA%90%E8%BD%AF%E4%BB%B6/1.htm">开源软件</a> <div>一、简介集成多种头像生成方案,包括:ugly-avatar、multiavatar、jdenticon、facesjs、dicebear等支持docker部署,支持API调用项目开源地址:GitHub-luler/hello_avatar:轻松搭建生成简易头像的api服务二、安装准备好docker、docker-compose环境新建docker-compose.yml,配置内容如下:versio</div> </li> <li><a href="/article/1902648322510876672.htm" title="SAP-ABAP:SAP工厂(Plant)与公司代码(Company Code)关联查询指南" target="_blank">SAP-ABAP:SAP工厂(Plant)与公司代码(Company Code)关联查询指南</a> <span class="text-muted">爱喝水的鱼丶</span> <a class="tag" taget="_blank" href="/search/SAP/1.htm">SAP</a><a class="tag" taget="_blank" href="/search/ABAP/1.htm">ABAP</a><a class="tag" taget="_blank" href="/search/ERP/1.htm">ERP</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%BF%90%E7%BB%B4/1.htm">开发运维</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/1.htm">运维</a> <div>SAP工厂(Plant)与公司代码(CompanyCode)关联查询指南一、核心查询方法对比方法类型事务码/表名响应速度适用场景权限要求配置界面查询OX18快单工厂详细信息查看S_TCODE(OX18)数据表直查T001W/T001K极快批量导出或多系统对接S_TABU_DIS(T001W/T001K)组织结构浏览PPOME中企业架构全景分析S_TCODE(PPOME)二、详细操作指南方法1:配置</div> </li> <li><a href="/article/1902647440083841024.htm" title="Trae AI 上新 SSHremote:服务器 Python 接口日志排查实战指南" target="_blank">Trae AI 上新 SSHremote:服务器 Python 接口日志排查实战指南</a> <span class="text-muted">芯作者</span> <a class="tag" taget="_blank" href="/search/DD%EF%BC%9A%E6%97%A5%E8%AE%B0/1.htm">DD:日记</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a> <div>在当今的软件开发中,服务器端的稳定性和可靠性至关重要。然而,生产环境中的问题往往难以预测,尤其是接口返回502错误却无日志记录的情况,更是让开发者头疼不已。幸运的是,字节跳动推出的AI原生IDE——Trae,近期上线的SSHremote功能,为远程服务器日志排查提供了全新的解决方案。本文将结合实战案例,深入探讨如何利用TraeAI的SSHremote功能高效排查Python接口日志问题,并分享创新</div> </li> <li><a href="/article/1902646935689424896.htm" title="保姆级 STM32 HAL 库外部中断教学" target="_blank">保姆级 STM32 HAL 库外部中断教学</a> <span class="text-muted">CircuitWizard</span> <a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA/1.htm">单片机</a><a class="tag" taget="_blank" href="/search/stm32/1.htm">stm32</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA/1.htm">单片机</a><a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%A1%AC%E4%BB%B6/1.htm">嵌入式硬件</a> <div>1.外部中断概述为什么用外部中断?当按键按下时,CPU无需轮询检测引脚状态,而是通过中断机制立即响应,提高效率,适用于实时性要求高的场景。关键概念EXTI(ExternalInterrupt/EventController):STM32的外设,负责管理外部中断/事件。NVIC(NestedVectoredInterruptController):管理中断优先级和使能。GPIO与EXTI的映射:每个</div> </li> <li><a href="/article/1902646431789936640.htm" title="前端开发:Webpack的使用总结" target="_blank">前端开发:Webpack的使用总结</a> <span class="text-muted">三掌柜666</span> <a class="tag" taget="_blank" href="/search/web%E5%89%8D%E7%AB%AF%E7%9F%A5%E8%AF%86%E6%B1%87%E6%80%BB/1.htm">web前端知识汇总</a><a class="tag" taget="_blank" href="/search/webpack/1.htm">webpack</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>前言在前端开发过程中,尤其是现在前端框架的频繁使用的当下,作为前端开发者想必对于Webpack并不陌生,尤其是在使用Vue框架做前端开发的时候,打包时候必用Webpack。还有就是在前端求职面试的时候,Webpack相关的知识点也是面试官必定考察的,那么本篇博文就来分享一下关于Webpack使用相关的知识点,记录下来,方便后期查阅使用。Webpack概念Webpack其实是一个前端资源加载/打包工</div> </li> <li><a href="/article/1902646305474277376.htm" title="Python后端学习系列(10):分布式系统与数据一致性(使用分布式锁、分布式事务等)" target="_blank">Python后端学习系列(10):分布式系统与数据一致性(使用分布式锁、分布式事务等)</a> <span class="text-muted">DoYangTan</span> <a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%B8%83%E5%BC%8F/1.htm">分布式</a> <div>Python后端学习系列(10):分布式系统与数据一致性(使用分布式锁、分布式事务等)前言随着业务规模的不断扩大以及对系统性能、可扩展性的更高要求,后端应用往往会朝着分布式系统的方向发展。然而,分布式系统带来诸多优势的同时,也面临着如数据一致性等复杂的挑战。本期我们就聚焦于分布式系统中的关键问题——数据一致性,深入探讨分布式锁、分布式事务等相关知识以及保障数据一致性的策略与实践,让我们一起深入学习</div> </li> <li><a href="/article/1902646178659495936.htm" title="泛目录程序:2025快云站群程序的SEO优化功能" target="_blank">泛目录程序:2025快云站群程序的SEO优化功能</a> <span class="text-muted">云惠科技</span> <a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/%E6%B3%9B%E7%9B%AE%E5%BD%95/1.htm">泛目录</a> <div>快云站群程序的SEO优化功能围绕搜索引擎算法设计,具体包含以下核心模块:1.关键词智能布局密度检测与优化:自动分析内容关键词密度,建议合理区间(2%-8%),避免堆砌或遗漏;多词策略支持:可针对单篇内容设置主关键词+长尾词组合,覆盖更多搜索场景;标题/摘要自动生成:根据关键词智能生成高点击率的标题和Meta描述,提升搜索展示效果。2.内链自动化系统内容关联推荐:基于语义分析,自动在文章中插入相关内</div> </li> <li><a href="/article/1902646179129257984.htm" title="如何使用C# 读写西门子PLC" target="_blank">如何使用C# 读写西门子PLC</a> <span class="text-muted">A_nanda</span> <a class="tag" taget="_blank" href="/search/%E8%A5%BF%E9%97%A8%E5%AD%90/1.htm">西门子</a> <div>在C#WPF应用程序中,与西门子S7系列PLC进行通信是一个常见的需求,尤其是在工业自动化领域。以下是三种实现WPF上位机与西门子S7系列PLC通信同步的方式,每种方式都提供了代码实例、优缺点和使用场景。1.使用S7.Net库代码示例://创建PLC连接varplc=newS7.Net.Plc(CpuType.S71500,"192.168.1.10",0,1);plc.Open();//读取PL</div> </li> <li><a href="/article/1902645926619574272.htm" title="《壹起航:15 年助力中国工厂海外获客,开启全球化新篇》" target="_blank">《壹起航:15 年助力中国工厂海外获客,开启全球化新篇》</a> <span class="text-muted">yiqijianzhan</span> <a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a> <div>在全球化的汹涌浪潮中,无数中国工厂渴望在海外市场一展宏图。然而,一系列棘手的问题摆在他们面前:怎样成功塑造品牌形象?怎样稳定获取询盘?怎样合理控制营销成本?壹起航,凭借15年深厚的行业积累,整合外贸建站、搜索引擎优化(SEO)以及海外短视频营销等多元服务,为中国工厂开辟出一条轻松拓展海外市场、赢得更多精准订单的便捷之路。一、外贸独立站——企业出海的关键起点在海外市场这片广阔天地里,企业官网不仅是展</div> </li> <li><a href="/article/1902644790525227008.htm" title="掌握C#企业级应用的数据一致性与分布式事务:从基础到高级的全面解析" target="_blank">掌握C#企业级应用的数据一致性与分布式事务:从基础到高级的全面解析</a> <span class="text-muted">墨夶</span> <a class="tag" taget="_blank" href="/search/C%23%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%991/1.htm">C#学习资料1</a><a class="tag" taget="_blank" href="/search/c%23/1.htm">c#</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%B8%83%E5%BC%8F/1.htm">分布式</a><a class="tag" taget="_blank" href="/search/wpf/1.htm">wpf</a> <div>在当今的企业级应用开发中,确保数据的一致性是至关重要的。尤其是在涉及分布式系统时,如何处理跨服务、跨数据库的操作以保证数据的一致性和可靠性成为了一个复杂但必须解决的问题。本文将深入探讨使用C#进行企业级应用开发时的数据一致性和分布式事务管理,提供详细的代码示例和最佳实践。第一部分:理解数据一致性与分布式事务的基础知识1.1数据一致性的重要性在企业级应用中,数据一致性是指关联数据之间的逻辑关系是否正</div> </li> <li><a href="/article/1902644538216869888.htm" title="主流区块链平台对 EVM 的依赖情况分类说明" target="_blank">主流区块链平台对 EVM 的依赖情况分类说明</a> <span class="text-muted">倒霉男孩</span> <a class="tag" taget="_blank" href="/search/%E5%8C%BA%E5%9D%97%E9%93%BE%E7%9F%A5%E8%AF%86/1.htm">区块链知识</a><a class="tag" taget="_blank" href="/search/%E5%8C%BA%E5%9D%97%E9%93%BE/1.htm">区块链</a> <div>文章目录概要1.EVM兼容链BinanceSmartChain(BSC)Polygon(PoS链)AvalancheC-ChainFantomOptimism/Arbitrum2.非EVM链3.混合型链AvalanchePolygonSupernetsBNBChain概要1.EVM兼容链这些链直接支持以太坊虚拟机,开发者可用Solidity编写合约,并复用以太坊工具链:BinanceSmartCh</div> </li> <li><a href="/article/82.htm" title="java类加载顺序" target="_blank">java类加载顺序</a> <span class="text-muted">3213213333332132</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>package com.demo; /** * @Description 类加载顺序 * @author FuJianyong * 2015-2-6上午11:21:37 */ public class ClassLoaderSequence { String s1 = "成员属性"; static String s2 = "</div> </li> <li><a href="/article/209.htm" title="Hibernate与mybitas的比较" target="_blank">Hibernate与mybitas的比较</a> <span class="text-muted">BlueSkator</span> <a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a><a class="tag" taget="_blank" href="/search/%E6%A1%86%E6%9E%B6/1.htm">框架</a><a class="tag" taget="_blank" href="/search/ibatis/1.htm">ibatis</a><a class="tag" taget="_blank" href="/search/orm/1.htm">orm</a> <div>第一章     Hibernate与MyBatis Hibernate 是当前最流行的O/R mapping框架,它出身于sf.net,现在已经成为Jboss的一部分。 Mybatis 是另外一种优秀的O/R mapping框架。目前属于apache的一个子项目。 MyBatis 参考资料官网:http:</div> </li> <li><a href="/article/336.htm" title="php多维数组排序以及实际工作中的应用" target="_blank">php多维数组排序以及实际工作中的应用</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a><a class="tag" taget="_blank" href="/search/usort/1.htm">usort</a><a class="tag" taget="_blank" href="/search/uasort/1.htm">uasort</a> <div>自定义排序函数返回false或负数意味着第一个参数应该排在第二个参数的前面, 正数或true反之, 0相等usort不保存键名uasort 键名会保存下来uksort 排序是对键名进行的 <!doctype html> <html lang="en"> <head> <meta charset="utf-8&q</div> </li> <li><a href="/article/463.htm" title="DOM改变字体大小" target="_blank">DOM改变字体大小</a> <span class="text-muted">周华华</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml&q</div> </li> <li><a href="/article/590.htm" title="c3p0的配置" target="_blank">c3p0的配置</a> <span class="text-muted">g21121</span> <a class="tag" taget="_blank" href="/search/c3p0/1.htm">c3p0</a> <div>c3p0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。c3p0的下载地址是:http://sourceforge.net/projects/c3p0/这里可以下载到c3p0最新版本。 以在spring中配置dataSource为例: <!-- spring加载资源文件 --> <bean name="prope</div> </li> <li><a href="/article/717.htm" title="Java获取工程路径的几种方法" target="_blank">Java获取工程路径的几种方法</a> <span class="text-muted">510888780</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>第一种: File f = new File(this.getClass().getResource("/").getPath()); System.out.println(f); 结果: C:\Documents%20and%20Settings\Administrator\workspace\projectName\bin 获取当前类的所在工程路径; 如果不加“</div> </li> <li><a href="/article/844.htm" title="在类Unix系统下实现SSH免密码登录服务器" target="_blank">在类Unix系统下实现SSH免密码登录服务器</a> <span class="text-muted">Harry642</span> <a class="tag" taget="_blank" href="/search/%E5%85%8D%E5%AF%86/1.htm">免密</a><a class="tag" taget="_blank" href="/search/ssh/1.htm">ssh</a> <div>1.客户机     (1)执行ssh-keygen -t rsa -C "xxxxx@xxxxx.com"生成公钥,xxx为自定义大email地址     (2)执行scp ~/.ssh/id_rsa.pub root@xxxxxxxxx:/tmp将公钥拷贝到服务器上,xxx为服务器地址     (3)执行cat</div> </li> <li><a href="/article/971.htm" title="Java新手入门的30个基本概念一" target="_blank">Java新手入门的30个基本概念一</a> <span class="text-muted">aijuans</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/java+%E5%85%A5%E9%97%A8/1.htm">java 入门</a><a class="tag" taget="_blank" href="/search/%E6%96%B0%E6%89%8B/1.htm">新手</a> <div>在我们学习Java的过程中,掌握其中的基本概念对我们的学习无论是J2SE,J2EE,J2ME都是很重要的,J2SE是Java的基础,所以有必要对其中的基本概念做以归纳,以便大家在以后的学习过程中更好的理解java的精髓,在此我总结了30条基本的概念。  Java概述:  目前Java主要应用于中间件的开发(middleware)---处理客户机于服务器之间的通信技术,早期的实践证明,Java不适合</div> </li> <li><a href="/article/1098.htm" title="Memcached for windows 简单介绍" target="_blank">Memcached for windows 简单介绍</a> <span class="text-muted">antlove</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/windows/1.htm">windows</a><a class="tag" taget="_blank" href="/search/cache/1.htm">cache</a><a class="tag" taget="_blank" href="/search/memcached/1.htm">memcached</a> <div>1. 安装memcached server a. 下载memcached-1.2.6-win32-bin.zip b. 解压缩,dos 窗口切换到 memcached.exe所在目录,运行memcached.exe -d install c.启动memcached Server,直接在dos窗口键入 net start "memcached Server&quo</div> </li> <li><a href="/article/1225.htm" title="数据库对象的视图和索引" target="_blank">数据库对象的视图和索引</a> <span class="text-muted">百合不是茶</span> <a class="tag" taget="_blank" href="/search/%E7%B4%A2%E5%BC%95/1.htm">索引</a><a class="tag" taget="_blank" href="/search/oeacle%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">oeacle数据库</a><a class="tag" taget="_blank" href="/search/%E8%A7%86%E5%9B%BE/1.htm">视图</a> <div>  视图     视图是从一个表或视图导出的表,也可以是从多个表或视图导出的表。视图是一个虚表,数据库不对视图所对应的数据进行实际存储,只存储视图的定义,对视图的数据进行操作时,只能将字段定义为视图,不能将具体的数据定义为视图       为什么oracle需要视图;    &</div> </li> <li><a href="/article/1352.htm" title="Mockito(一) --入门篇" target="_blank">Mockito(一) --入门篇</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/%E6%8C%81%E7%BB%AD%E9%9B%86%E6%88%90/1.htm">持续集成</a><a class="tag" taget="_blank" href="/search/mockito/1.htm">mockito</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/1.htm">单元测试</a> <div>        Mockito是一个针对Java的mocking框架,它与EasyMock和jMock很相似,但是通过在执行后校验什么已经被调用,它消除了对期望 行为(expectations)的需要。其它的mocking库需要你在执行前记录期望行为(expectations),而这导致了丑陋的初始化代码。  &nb</div> </li> <li><a href="/article/1479.htm" title="精通Oracle10编程SQL(5)SQL函数" target="_blank">精通Oracle10编程SQL(5)SQL函数</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/plsql/1.htm">plsql</a> <div>/* * SQL函数 */ --数字函数 --ABS(n):返回数字n的绝对值 declare v_abs number(6,2); begin v_abs:=abs(&no); dbms_output.put_line('绝对值:'||v_abs); end; --ACOS(n):返回数字n的反余弦值,输入值的范围是-1~1,输出值的单位为弧度</div> </li> <li><a href="/article/1606.htm" title="【Log4j一】Log4j总体介绍" target="_blank">【Log4j一】Log4j总体介绍</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/log4j/1.htm">log4j</a> <div>Log4j组件:Logger、Appender、Layout   Log4j核心包含三个组件:logger、appender和layout。这三个组件协作提供日志功能: 日志的输出目标 日志的输出格式 日志的输出级别(是否抑制日志的输出)  logger继承特性 A logger is said to be an ancestor of anothe</div> </li> <li><a href="/article/1733.htm" title="Java IO笔记" target="_blank">Java IO笔记</a> <span class="text-muted">白糖_</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div> public static void main(String[] args) throws IOException { //输入流 InputStream in = Test.class.getResourceAsStream("/test"); InputStreamReader isr = new InputStreamReader(in); Bu</div> </li> <li><a href="/article/1860.htm" title="Docker 监控" target="_blank">Docker 监控</a> <span class="text-muted">ronin47</span> <a class="tag" taget="_blank" href="/search/docker%E7%9B%91%E6%8E%A7/1.htm">docker监控</a> <div>         目前项目内部署了docker,于是涉及到关于监控的事情,参考一些经典实例以及一些自己的想法,总结一下思路。 1、关于监控的内容 监控宿主机本身 监控宿主机本身还是比较简单的,同其他服务器监控类似,对cpu、network、io、disk等做通用的检查,这里不再细说。 额外的,因为是docker的</div> </li> <li><a href="/article/1987.htm" title="java-顺时针打印图形" target="_blank">java-顺时针打印图形</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>一个画图程序 要求打印出: 1.int i=5; 2.1 2 3 4 5 3.16 17 18 19 6 4.15 24 25 20 7 5.14 23 22 21 8 6.13 12 11 10 9 7. 8.int i=6 9.1 2 3 4 5 6 10.20 21 22 23 24 7 11.19</div> </li> <li><a href="/article/2114.htm" title="关于iReport汉化版强制使用英文的配置方法" target="_blank">关于iReport汉化版强制使用英文的配置方法</a> <span class="text-muted">Kai_Ge</span> <a class="tag" taget="_blank" href="/search/iReport%E6%B1%89%E5%8C%96/1.htm">iReport汉化</a><a class="tag" taget="_blank" href="/search/%E8%8B%B1%E6%96%87%E7%89%88/1.htm">英文版</a> <div>对于那些具有强迫症的工程师来说,软件汉化固然好用,但是汉化不完整却极为头疼,本方法针对iReport汉化不完整的情况,强制使用英文版,方法如下: 在 iReport 安装路径下的 etc/ireport.conf 里增加红色部分启动参数,即可变为英文版。   # ${HOME} will be replaced by user home directory accordin</div> </li> <li><a href="/article/2241.htm" title="[并行计算]论宇宙的可计算性" target="_blank">[并行计算]论宇宙的可计算性</a> <span class="text-muted">comsci</span> <a class="tag" taget="_blank" href="/search/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/1.htm">并行计算</a> <div>       现在我们知道,一个涡旋系统具有并行计算能力.按照自然运动理论,这个系统也同时具有存储能力,同时具备计算和存储能力的系统,在某种条件下一般都会产生意识......       那么,这种概念让我们推论出一个结论     &nb</div> </li> <li><a href="/article/2368.htm" title="用OpenGL实现无限循环的coverflow" target="_blank">用OpenGL实现无限循环的coverflow</a> <span class="text-muted">dai_lm</span> <a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/coverflow/1.htm">coverflow</a> <div>网上找了很久,都是用Gallery实现的,效果不是很满意,结果发现这个用OpenGL实现的,稍微修改了一下源码,实现了无限循环功能 源码地址: https://github.com/jackfengji/glcoverflow public class CoverFlowOpenGL extends GLSurfaceView implements GLSurfaceV</div> </li> <li><a href="/article/2495.htm" title="JAVA数据计算的几个解决方案1" target="_blank">JAVA数据计算的几个解决方案1</a> <span class="text-muted">datamachine</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a><a class="tag" taget="_blank" href="/search/%E8%AE%A1%E7%AE%97/1.htm">计算</a> <div>老大丢过来的软件跑了10天,摸到点门道,正好跟以前攒的私房有关联,整理存档。 -----------------------------华丽的分割线-------------------------------------     数据计算层是指介于数据存储和应用程序之间,负责计算数据存储层的数据,并将计算结果返回应用程序的层次。J  &nbs</div> </li> <li><a href="/article/2622.htm" title="简单的用户授权系统,利用给user表添加一个字段标识管理员的方式" target="_blank">简单的用户授权系统,利用给user表添加一个字段标识管理员的方式</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/yii/1.htm">yii</a> <div>怎么创建一个简单的(非 RBAC)用户授权系统 通过查看论坛,我发现这是一个常见的问题,所以我决定写这篇文章。 本文只包括授权系统.假设你已经知道怎么创建身份验证系统(登录)。 数据库 首先在 user 表创建一个新的字段(integer 类型),字段名 'accessLevel',它定义了用户的访问权限 扩展 CWebUser 类 在配置文件(一般为 protecte</div> </li> <li><a href="/article/2749.htm" title="未选之路" target="_blank">未选之路</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/%E8%AF%97/1.htm">诗</a> <div>作者:罗伯特*费罗斯特   黄色的树林里分出两条路, 可惜我不能同时去涉足, 我在那路口久久伫立, 我向着一条路极目望去, 直到它消失在丛林深处.   但我却选了另外一条路, 它荒草萋萋,十分幽寂; 显得更诱人,更美丽, 虽然在这两条小路上, 都很少留下旅人的足迹.   那天清晨落叶满地, 两条路都未见脚印痕迹. 呵,留下一条路等改日再</div> </li> <li><a href="/article/2876.htm" title="Java处理15位身份证变18位" target="_blank">Java处理15位身份证变18位</a> <span class="text-muted">蕃薯耀</span> <a class="tag" taget="_blank" href="/search/18%E4%BD%8D%E8%BA%AB%E4%BB%BD%E8%AF%81%E5%8F%9815%E4%BD%8D/1.htm">18位身份证变15位</a><a class="tag" taget="_blank" href="/search/15%E4%BD%8D%E8%BA%AB%E4%BB%BD%E8%AF%81%E5%8F%9818%E4%BD%8D/1.htm">15位身份证变18位</a><a class="tag" taget="_blank" href="/search/%E8%BA%AB%E4%BB%BD%E8%AF%81%E8%BD%AC%E6%8D%A2/1.htm">身份证转换</a> <div>  15位身份证变18位,18位身份证变15位 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 蕃薯耀 201</div> </li> <li><a href="/article/3003.htm" title="SpringMVC4零配置--应用上下文配置【AppConfig】" target="_blank">SpringMVC4零配置--应用上下文配置【AppConfig】</a> <span class="text-muted">hanqunfeng</span> <a class="tag" taget="_blank" href="/search/springmvc4/1.htm">springmvc4</a> <div>从spring3.0开始,Spring将JavaConfig整合到核心模块,普通的POJO只需要标注@Configuration注解,就可以成为spring配置类,并通过在方法上标注@Bean注解的方式注入bean。   Xml配置和Java类配置对比如下: applicationContext-AppConfig.xml   <!-- 激活自动代理功能 参看:</div> </li> <li><a href="/article/3130.htm" title="Android中webview跟JAVASCRIPT中的交互" target="_blank">Android中webview跟JAVASCRIPT中的交互</a> <span class="text-muted">jackyrong</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/%E8%84%9A%E6%9C%AC/1.htm">脚本</a> <div>  在android的应用程序中,可以直接调用webview中的javascript代码,而webview中的javascript代码,也可以去调用ANDROID应用程序(也就是JAVA部分的代码).下面举例说明之: 1 JAVASCRIPT脚本调用android程序    要在webview中,调用addJavascriptInterface(OBJ,int</div> </li> <li><a href="/article/3257.htm" title="8个最佳Web开发资源推荐" target="_blank">8个最佳Web开发资源推荐</a> <span class="text-muted">lampcy</span> <a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98/1.htm">程序员</a> <div>Web开发对程序员来说是一项较为复杂的工作,程序员需要快速地满足用户需求。如今很多的在线资源可以给程序员提供帮助,比如指导手册、在线课程和一些参考资料,而且这些资源基本都是免费和适合初学者的。无论你是需要选择一门新的编程语言,或是了解最新的标准,还是需要从其他地方找到一些灵感,我们这里为你整理了一些很好的Web开发资源,帮助你更成功地进行Web开发。 这里列出10个最佳Web开发资源,它们都是受</div> </li> <li><a href="/article/3384.htm" title="架构师之面试------jdk的hashMap实现" target="_blank">架构师之面试------jdk的hashMap实现</a> <span class="text-muted">nannan408</span> <a class="tag" taget="_blank" href="/search/HashMap/1.htm">HashMap</a> <div>1.前言。   如题。 2.详述。   (1)hashMap算法就是数组链表。数组存放的元素是键值对。jdk通过移位算法(其实也就是简单的加乘算法),如下代码来生成数组下标(生成后indexFor一下就成下标了)。 static int hash(int h) { h ^= (h >>> 20) ^ (h >>></div> </li> <li><a href="/article/3511.htm" title="html禁止清除input文本输入缓存" target="_blank">html禁止清除input文本输入缓存</a> <span class="text-muted">Rainbow702</span> <a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/%E7%BC%93%E5%AD%98/1.htm">缓存</a><a class="tag" taget="_blank" href="/search/input/1.htm">input</a><a class="tag" taget="_blank" href="/search/%E8%BE%93%E5%85%A5%E6%A1%86/1.htm">输入框</a><a class="tag" taget="_blank" href="/search/change/1.htm">change</a> <div>多数浏览器默认会缓存input的值,只有使用ctl+F5强制刷新的才可以清除缓存记录。 如果不想让浏览器缓存input的值,有2种方法: 方法一: 在不想使用缓存的input中添加 autocomplete="off";  <input type="text" autocomplete="off" n</div> </li> <li><a href="/article/3638.htm" title="POJO和JavaBean的区别和联系" target="_blank">POJO和JavaBean的区别和联系</a> <span class="text-muted">tjmljw</span> <a class="tag" taget="_blank" href="/search/POJO/1.htm">POJO</a><a class="tag" taget="_blank" href="/search/java+beans/1.htm">java beans</a> <div>POJO 和JavaBean是我们常见的两个关键字,一般容易混淆,POJO全称是Plain Ordinary Java Object / Pure Old Java Object,中文可以翻译成:普通Java类,具有一部分getter/setter方法的那种类就可以称作POJO,但是JavaBean则比 POJO复杂很多, Java Bean 是可复用的组件,对 Java Bean 并没有严格的规</div> </li> <li><a href="/article/3765.htm" title="java中单例的五种写法" target="_blank">java中单例的五种写法</a> <span class="text-muted">liuxiaoling</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E4%BE%8B/1.htm">单例</a> <div>/** * 单例模式的五种写法: * 1、懒汉 * 2、恶汉 * 3、静态内部类 * 4、枚举 * 5、双重校验锁 */ /** * 五、 双重校验锁,在当前的内存模型中无效 */ class LockSingleton { private volatile static LockSingleton singleton; pri</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html>