OpenStack对外提供REST API,那么REST API是如何建立起来的呢?

OpenStack用了一种叫WSGI(Web Service Gateway Interface)的东西,WSGI是Web服务器与Web应用程序或应用框架之间的一种低级别的接口。

下面是个简单的例子:

#!/usr/bin/env python

from wsgiref.simple_server import make_server  

def hello_world_app(environ, start_response):
status = '200 OK' # HTTP Status
headers = [('Content-type', 'text/plain')] # HTTP Headers
start_response(status, headers) # The returned object is going to be printed
return ["Hello World"] httpd = make_server('', 8088, hello_world_app)
print "Serving on port 8088..." # Serve until process is killed
httpd.serve_forever()

执行这段代码,然后浏览器访问http://localhost:8088就会出现Hello World页面。

大致流程如下:

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAeUAAABXCAIAAAC1J8r/AAAPw0lEQVR4nO2d21dTVx7H9/8RH+ApD3nXZ/6A6FteGOzMaJ1WOun0IlBjnWq9dLWGWtRehh6vwSCEi5eOhcYL1tZK6azFzIJl1AASAtjaVe1UGRFlHrbd7OxzciA5++ydc9b3u74Ph3Nn78/vey45ySGLEARBkBdEdO8ABEEQtCIhryEIgrwh5DUEQZA3hLyGIAjyhpDXEARB3tDyeT374PHZ4Xu7zk281n7rT0dGa1tH4NrWkReMkdfab+06N9H9w0+zDx4r6KqKFQgBIfYCIbIIscvriXtz75wZr09kdp4e+/RiLnF1umvwbu/38N3e7+92Dd5t+2bm04u53WfH6xOZv58evzHzUBLenhEIASH2AiFyCbHO64Wnz1qv5P9y/EZL32Tv4F14WR/sn9ycyBy8mJtfeOYC9hUnEFIeIYcuToEQuGxCLPL64eOFHWfGY13Z1LVZ7f+Dh9x1/e72nrFYd/b+oyduFoJ+gRAHhGS39YAQuExCxLxeePpsx5nxHb1jPYN34TK85+zE1u6sj8+hQIhDv3duItYDQuByCBHzuvVKfmtXtmdwFi7bb3dnW9I5KejncjlCSC63zNoMw4hEIlK2uKxAiHNv78keuCCHELNWCEMoFOrv73djB0CIe4QU5PXEvbmXTmQ6r830XJ+Fy3bXdzOvtGVGp39zjn4sFjPXHiGEkIKOo7E+PDzsfIv2AiGyCPnryZtSCDGLEMKCmILBxBNiGEYoFJK+dRDiKiEFZf/OmfH9X97pvj4LO/ShryabUlnn9PO1t7i4aBgGqz1hzkgkEovFnG/RXiCk0ggR1N/fz7MRCoVYRkciET6yXTrGgxBXCVnq2tkHj+vbMtr30jd+NXlz4t6cE/Rp7bGbIcPDwzS+aWoLM1uOlCsQUmmEmBWJRIrdDKH8GIbBxoRCIbnHeBDiNiFLFX7u3/d2nh7r+m4WluI9ZydODc46oT8Wi1lesVpGM61GV2+JgBC53nt24tT3jggxS0hkXua8LgZY2QIhbhOyVPa7zo1/nJ7Uvou+sXFpamuXowveYudKlnlNL29d+gSJCoRIJ2R775jEDrJngGIj3MKWe00GQtwmZKm3GjpvHx3Ia99F3/jk1emXT2Sc0F/scrVYmdmcW0kRCJHr41emX2lzRIgg+2ssQohw+BduuDkXCHGbkKWyfzmROfH1dOq7WViWa1tHnNBPCCk1r139yBGEyHXHtZkXDEeECKL5a5nX9MPGlc9fnkCI24QsdWFt60jq2iws0Q7zutLOr0FIpREiqNj5NQ1r83m09PNrEOI2IUJez8AS7bAaK+3+NQipNEIEWTIQi8WKhbL0+9cgxG1CCvK689oMLNEOq7HSng8BIZVGiFnmJ0BsqJD+fAgIcZsQ5LW6ti5Vls9fC2InUwqevwYhlUaIWfw1mfDlRvM3raQ/fw1C3CakMK+/nYEl2nk1rvwWh4LvN4KQCiREkPD9Rhu58f1GEOI2IQV53fHtDCzRzqvR8vdDzFLz+yEgpAIJMWuFx3g3fj8EhLhNCPJaXVuXIY2/zzc3/1R4RxEIqUBCzFL2+3wgRD0hBXl96psZWKLdqEZl+vHX+fXG6GcDeVaTIASE8AIh6glBXqtra2/px1/n6VtBWU2CEBDCC4SoJwR57W5b+8brjVEQAkJAiHpCiuZ1+zfTsETX+uLsqbZ1pLl/cuLeHAgBIbxAiHpCCvP66jQs0T6oRlqHdAwIASG8QIh6QgryOnl1GpZoT1fjw8cLwm+lgxAQwguEqCcEea2urb0uEAJC7AVC3CYEea2urb0uEAJC7AVC3CakIK9Pfj0NS7T/qlF7k/rMIAQuiRDktbq29rpACAixFwhxmxDktbq29rpACAixFwhxm5CCvG67Mg1LtP+qUXuT+swgBC6JkErM671HLhBC9h650HZluqm5nQ17zqhGGISo94GuHwghTc3tbHhTY7OUNW9qbCaEHOj6QRchBXmduJJX7Bcb4/wvqdORe46kCSF7jqQTV/JNzUk27Dn7rxrVtBvtdKp166Pa+xGErFBlE0J7fFV1UEqrtnQNEUKampNs+MXGuJQ107xq6RrSRYjOvF5VHWQZnfg9phOFeS1rQ1rKHtVYhoUj9Lr1UVp4vjQIoV5TE15TE5ZV9XxeO7TErJdCSGFeD+SV+fmRKjVknrTncJoQsudwWta2VlUH19VFVf531D6sRvcbbV1ddFV1UH1naTEISQzkW1JDNApk1SldYVM86XxVz/O6YggpyOsTA3llJoSsq4taTmJ5LQxTB6qD7GKZjaezfZQaYpM2NsbZeF4q/0fn1ajxfQVmqSFkXV2UdqXlVJveZ33dGE8GqoMCXQyJla/EE4RUlMojZGNjfE1NmA4IFRqoDjbGkxu5u6bCUnzJsy6jI9mffNcLvc9G0rN7fj2N8aWbcoSQQHWQjeTh5OfhmQlUBzc2xinMbHHnhOjJa9qgfCPytslrfinadvxsrCn5SbTtih0bXLXzarR8Hxh7jyp7AZiy94EpY4NYHc5X2PsnTJXPDuclrcQThFSUyiOERhvrAiH1eBLW1IRZ8LEQN3elTV4HqoP02EAXoWteUxNmMwuJLMQUP5Vuhe0b3XnhnID9aclzGYQU5PXxgbwa7z6cJoQ0xJM2U3cfTgvDGxvjgeogP2egOri2LirMRk0bS5hNsZ1XI7F6F18oFIpEIkJAq3nfrrKmY+c7rOOW7X0ep/2pIX7M2rromppwqSvxBCFmKXsfmFllEEKbfX9qiHUH7Smhd/iZWRoQQiy7Uuh9FgUN8SS/LUvTZVmS8DEirGFtXVRgiR8j7Ll55vII8VJer/394oJXsbzm28ujeU3fdS3cDKGvSR0eHhby2jAMsrIXY5ctlYRQ0x6nfVdS7x8fyK+pCfMAUNhKXUmFE2Ip/hjPLsWEC7JF1963W0YX80FGU5iPb75y+SA25zX90PJ48bw2L8LM3ySxXJaaz2u2OWHnLffcZtMlEVKY15fzyvy8Tqwm7TbShJDdRloYXlsXDVQFl12EOlAVZOvnh1XaYTXGYjGhoth9D3Nem8dIl2JCqGnCltr7xy/nG/Yl6YJ0KltbSSupcELMosd49ic9tNPhWCxGXL6HVgYh5sMnIWRjQ5xOFSp3f+cQIaRhX/L45fzGhjjrVurnAVo4G90EXaF5ETYDXdBmWR6q/Z1D/OaY+fULe15s06USUpDXxy7nlXl1TZgQYjlpl5EmhOwy0sLwhob4Shahpu3FtsWGVdphNUYiEeHClt30MKczLT/pV7i8FBNCTRO21N6npiM3NMRZ75exkkomxCwzM0yUGZ6QUCgk9x5aqYRs2ZckhHzYOcSPXF0Tpj1+rLCKjy2XBmzmDzuHCCFb9iUZBhsa4sU2R2dm/S4sG6gK0mXNO8zINLNq3nMb8EoipCCvj17OqzQ9lrI/mzuH6J/vGmlCyLtGWhimM6yuCbNFVteEzbNRB6qC4boomy1QFVT83x11XI1COfGnTpZn04QQwzCcbNFeagjh+5F264aGeKm9Tx2ui4brooGqIJtUxkoqmRCzbBgw57X5As6hSiVkdU2Y7wtqGm3NnUNHL+cDVUFCCCvkQFWQFTKdjQUI/ZMPii37kowoihAdZlvcsi9J1yxsgl82UBXk95DmNd03Hk42iV+QrZPtnnNCdOb10d/PspnoyGJ5zVqcibWOfV7T/iOEKE5th9VICOHzmi+2Ynnt6keOaghhnSV0cUm9z483d3pJK6lkQgTZX2MRQoR0lv6ZR0mECKkqjKc5SKs4zJ6K47qSBTTrSuGobJnXQu/zXc94MFPBUp7PazOrxfLnqFt5fSkPS7TE82sa0GbxFUgUnF/rblKfWW5eFzuKm1GhsvxA24mkExKoCob/ELWc9DwBdfegYkIK8vrIpTws0dLvXzPpun+tvUl9Zrl5TfO32EeI9GyaP6Lbz1+GpBNC89py0p8b4oQQ7T2omBDktbq2LlU2txd1PR+ivUl9ZgXn17xCoRBPlBvn13LbB3ltl9eHL+VhiXbj+WsqXc9fa29Sn1nl/evFxcVIJMLntRv3r7U3qc+MvNbW1mVo5bc41Hy/UXuT+syuPh9C45tNood//n6IG8+HaG9Sn9kur42LeViiXfr9ELOU/X6I9ib1md1+/pqeQTMJx343nr/W3qQ+M/JaW1uXoUr7fT7tTeozu/39Rhu59P1G7U3qM9vl9ecX87BEC209v/Ds59/mJZaHYoEQtwmRohXeQ3Pp90O0N6nPjLzW0NbzC8/O/+fnzYnMQOYXuRWiUiDEPUIkSu/v82lvUp/ZLq9bL+Rhia5tHWFJXds6Uts64vW81t6kPrP/rsC0N6nPjLxW2tZ/a79Jk9of1t6kPrP/rsC0N6nPjLxW2tb3Hz05cW3mj4dHcX4NWxKCKzDYnhC+hQvy+h8XpmCJZm3NUtvr1ai9SX1m/12BaW9Snxl5ra2t7z96kv/lf4rC1QWBEDcI8dkVmPYm9Znt8vqz9BQs0bUufPqvUSDEPUJ8cwWmvUl9ZuS1trb2ukCI24T44ApMe5P6zHZ5/Wl6CpZo/+W19ib1mUEIXBIhyGt1be11gRAQYi8Q4jYhS3m96diNlr7cJ+kpWJZ9Vo0gRLrrPh/V3asyBULcJmQpr9/suB3/551PvpqCpbjly9ymYzeUl4yLAiFy/eH5yfq2jO5elSkQ4jYhS3m948zYnjMTH381BUvxB1/caeq6rbxkXBQIkU7Itp4x3b0qUyDEbUKW8rr7Xz9tTY1p30XfeGsqm7w+q7xkXBQIkU3IWPsgCIFLIGQpr2cfPN6cyGjfRd84evLmjZmHykvGRYEQuX4VhMAlElLw0+Zv947t7B0/1D8FO/Tu0xNvdtxSWywqBEIkErIFhMAlElKQ1zdmHr50InOwL6d9Xz3tg325+kRmOPdfhWWiSCBEFiGvtIEQuGRCxFcHHbo01dBx+2D/FFy2Gztuv3/+jqoCUS0Q4txvpbIgBC6DEDGv5xeexbqzW1NZ7XvsUW/rGnv91K25+adKSkODQIhDb+8efwOEwGURYvFqzvuPnjR1ZRs6brf05Q70T8ErdEtfrrHz9uunbt1/9MT9otApEFI2IU2p7BsgBC6XEOtXKc/NP/0oPbk5kdnZO36gbwpe1rtOT9S3Zd4/f8fH5028QEg5hCRACOyIEOu8phqd/q0xla1PZN7qzO49e+eDLyY/+jLX0jcFU3/wxeR7Z+80dY5FT958s+OWLz8+shcIASH2AiFyCbHLa6qJe3Onvp/d1jNW35ZZb+h/gUWFuO7z0fq2zLaesfbBWZ89RVuqQAgIsRcIkUXI8nkNQRAEVYKQ1xAEQd4Q8hqCIMgbQl5DEAR5Q8hrCIIgbwh5DUEQ5A39HxJvUhNachWNAAAAAElFTkSuQmCC" alt="" />

(1)Client(上例中浏览器)发送请求到Server。

(2)Server转发请求给Application(上例中hello_world_app)。注:Server和Application之间还有middleware,此处省略。

(3)Application进行操作后将相应发送给Server。

(4)Server再将相应转发给Client。

OpenStack使用WSGI的一个工具包paste来配置WSGI appliaction和server的系统,它的好处是将配置和代码分离。python代码写好后如果想要修改页面到app的映射关系,只需要修改配置文件即可。

用一个简单的例子来示范paste.deploy的工作机制:

pastedeploy.ini

[composite:test_composite]
use=egg:Paste#urlmap
/:root
[pipeline:root]
pipeline = logrequest showversion
[filter:logrequest]
username = root
password = root123
paste.filter_factory = pastedeploylab:LogFilter.factory
[app:showversion]
version = 1.0.0
paste.app_factory = pastedeploylab:ShowVersion.factory

app:表示它定义了一个wsgi的application,是一个callable对象。paste. app_factory返回值是一个application对象

filter:表示这个段定义了一个filter,filter需要完成的工作是将application包装成另一个application(“过滤”),并返回这个包装后的application。

pipeline:Pipeline 由一些列的filter组成,最后一个是应用,即将前面的fiiter应用到application。

composite:自己不处理请求,根据映射关系把请求分发到filter、app或者pipeline。/:root就是表示访问url根目录的请求全部分发到root这个pipeline处理

pastedeploy.py

import os
import webob
from webob import Request
from webob import Response
from paste.deploy import loadapp
from wsgiref.simple_server import make_server
#Filter
class LogFilter():
def __init__(self,app):
self.app = app
pass
def __call__(self,environ,start_response):
print "filter:LogFilter is called."
return self.app(environ,start_response)
@classmethod
def factory(cls, global_conf, **kwargs):
print "in LogFilter.factory", global_conf, kwargs
return LogFilter
class ShowVersion():
def __init__(self):
pass
def __call__(self,environ,start_response):
start_response("200 OK",[("Content-type", "text/plain")])
return ["Paste Deploy LAB: Version = 1.0.0",]
@classmethod
def factory(cls,global_conf,**kwargs):
print "in ShowVersion.factory", global_conf, kwargs
return ShowVersion()
if __name__ == '__main__':
configfile="pastedeploy.ini"
appname="test_composite"
wsgi_app = loadapp("config:%s" % os.path.abspath(configfile), appname)
server = make_server('localhost',8080,wsgi_app)
server.serve_forever()
pass

执行命令python pastedeploy.py,然后在浏览器中输入http://localhost:8080/就可以在网页输出Paste Deploy LAB: Version = 1.0.0

下面讲解一下工作流程,运行pastedeploy.py文件,首先会调用loadapp函数加载运用,在配置文件pastedeploy.ini找到appname为test_composite,test_composite是一个composite,然后找到pipeline root,根据pipeline找到filter logrequest和app showversion,logrequest和showversion各自用factory生成callable对象。加载完应用后调用make_server启动服务。

在浏览器输入http://localhost:8080/就会根据urlmap将请求分发到pipeline root,调用LogFilter的__call__方法,其中app就是ShowVersion,然后调用ShowVersion的__call__方法返回消息。

以下写一个简单的OpenStack WSGI实例,参考了臭蛋的博客,臭蛋写的和OpenStack源码很一致。

其中用到的一些python库:

1. paste.deploy 配置WSGI appliaction和server

2. webob 用来对http请求和响应进行封装

3. routes 实现URL映射

4. eventlet.wsgi 或者 wsgiref.simple_server,提供wsgi server功能,后者更简单。

首先建立一个test包,然后在test包里面建立如下文件:

test-paste.ini

[composite:test_composite]
use=egg:Paste#urlmap
/v1:testapp [app:testapp]
paste.app_factory = test.router:API.factory

server.py

import os
import logging
import sys
from paste import deploy
from wsgiref.simple_server import make_server LOG = logging.getLogger(__name__) module_dir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
os.pardir,os.pardir)) sys.path.insert(0,module_dir) bind_host = "127.0.0.1"
bind_port = 8088 def server(app_name, conf_file):
print "server"
app = load_paste_app(app_name,conf_file)
serve = make_server(bind_host,bind_port,app)
serve.serve_forever() def load_paste_app(app_name, conf_file):
print "load_paste_app"
LOG.debug("Loading %(app_name) from %(conf_file)",
{'app_name':app_name, 'conf_file':conf_file}) try:
app = deploy.loadapp("config:%s" % os.path.abspath(conf_file), name=app_name)
return app
except (LookupError, ImportError) as e:
LOG.error(str(e))
raise RuntimeError(str(e)) if __name__ == '__main__':
app_name = "test_composite"
conf_file = "test-paste.ini"
server(app_name,conf_file)

wsgi.py

import logging
import routes.middleware
import webob.dec
import webob.exc class Router(object): def __init__(self, mapper=None):
print "Router.__init__"
self.map = mapper
self._router = routes.middleware.RoutesMiddleware(self._dispatch,
self.map)
@classmethod
def factory(cls, global_conf, **local_conf):
print "Router.__factory__"
return cls() @webob.dec.wsgify
def __call__(self,req):
print "Router.__call__"
return self._router @staticmethod
@webob.dec.wsgify
def _dispatch(req):
print "Router._dispatch"
# TODO
match = req.environ['wsgiorg.routing_args'][1]
if not match:
return webob.exc.HTTPNotFound()
app = match['controller']
return app

router.py

import routes

from test import wsgi
from test import versions class API(wsgi.Router): def __init__(self, mapper=None):
print "API.__init__"
if(mapper == None):
mapper = routes.Mapper() versions_resource = versions.create_resource()
mapper.connect("/test",controller=versions_resource,
action="index")
super(API,self).__init__(mapper)

versions.py

import httplib
import json
import webob.dec
from test import wsgi
from webob import Response class Controller(object):
def __init__(self):
print "Controller.__init__"
# TODO
self.version = "0.1" def index(self,req):
print "Controller.index"
response = Response(request=req,
status=httplib.MULTIPLE_CHOICES,
content_type='application/json')
response.body = json.dumps(dict(versions=self.version))
return response @webob.dec.wsgify
def __call__(self, request):
print "Controller.__call__"
# TODO
return self.index(request) def create_resource():
print "create_resource"
return Controller()

@webob.dec.wsgify 装饰器将一个普通函数转变成WSGI应用程序

执行python server.py , 然后在浏览器输入http://localhost:8088/v1/test 就会出现相关页面。

由于在函数中加了打印语句,启动时会输出:

server
load_paste_app
Router.__factory__
API.__init__
create_resource
Controller.__init__
Router.__init__

访问页面会输出:

Router.__call__
Router._dispatch
Controller.__call__
Controller.index

这是一个OpenStack WSGI原型,还需完善,比如在router.py文件中,/test并没有和index方法绑定,只是在Controller.__call__方法中静态的调用了index方法。

OpenStack点滴02-WSGI的更多相关文章

  1. OpenStack中给wsgi程序写单元測试的方法

    在 OpenStack 中, 针对web应用, 有三种方法来写单元測试 1) 使用webob生成模拟的request from __future__ import print_function imp ...

  2. OpenStack点滴03-Neutron

    OpenStack Neutron是一个比较复杂的组件,如果说OpenStack安装部署过程哪一个组件最麻烦,那就肯定是网络组件Neutron了. 因为我对OpenStack网络这块也不是很熟,就把我 ...

  3. OpenStack点滴01-概览

    OpenStack项目由Rackspace和NASA(美国国家航空航天局)共同发起,它是一个旨在为公共及私有云的建设与管理提供软件的开源项目. 作为一个开源云平台,OpenStack的首要任务是简化云 ...

  4. OpenStack Trove组件WSGI和RPC调用流程(参考调用的整个过程)

    参考博文:https://blog.csdn.net/bill_xiang_/article/details/72909927

  5. python wsgi

    什么是wsgi? wsgi是一个web组件的接口防范,wsgi将web组件分为三类:web服务器,web中间件,web应用程序 wsgi基本处理模式为:wsgi Server -> wsgi m ...

  6. openstack学习笔记一 虚拟机启动过程代码跟踪

    openstack学习笔记一 虚拟机启动过程代码跟踪 本文主要通过对虚拟机创建过程的代码跟踪.观察虚拟机启动任务状态的变化,来透彻理解openstack各组件之间的作用过程. 当从horizon界面发 ...

  7. openstack学习心得:keystone 架构、概念、访问流程

    1.keystone 介绍及其组成 OpenStack Identity 服务提供了一个单一的功能集合,包括管理认证,授权和服务目录. Identity 服务通常作为和用户第一个交互的服务.一旦认证成 ...

  8. keystone WSGI流程

    作为OpenStack两种基本的通信方式(RESTful API与消息总线)之中的一个.理解RESTful API的设计思路和运行过程,有助于我们对OpenStack有更好的理解.RESTful仅仅是 ...

  9. Ubuntu16手动安装OpenStack——nova篇。。转

    前言: 本文转自https://www.voidking.com/dev-ubuntu16-manual-openstack-nova/ ,过程非常的详细,作者也说本实验最终失败,因为课程要求我们只要 ...

随机推荐

  1. xamarin提供在线检查.net代码是否支援xamarin,ios,android

    大概是多少比你想的更多的移动.我们很高兴地宣布一个新的在线服务Xamarin NET移动扫描仪-扫描您的编译.NET代码的兼容性与Xamarin.iOSXamarin.Android是,Windows ...

  2. Java---常用基础面试知识点

    综合网上的一点资源,给大家整理了一些Java常用的基础面试知识点,希望能帮助到刚开始学习或正在学习的学员. 1.抽象 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方 ...

  3. 使用Windows驱动的虚拟打印机,打印Excel表格无表格线问题解决(2)

    测试: 经前天的测试,最终还是没有明显的定夺到底是驱动的问题,还是打印机的问题.但是按照可能性来排查,最明显的一点就是其他测试环境不变的情况下增加一张图片,就可以打印出表格线,我始终觉得这里是突破点, ...

  4. 设计模式学习--复合模式(Compound Pattern)

    设计模式学习--复合模式(Compound Pattern) 概述 ——————————————————————————————————————————————————— 2013年8月4日<H ...

  5. yii2使用Gii生成代码

    本章节将介绍怎样使用 Gii 去自己主动生成 Web 网站经常使用功能的代码.使用 Gii 生成代码很easy,仅仅要依照 Gii 页面上的介绍输入正确的信息就可以. 贯穿本章节,你将会学到: 在你的 ...

  6. [Javascript] Intro to Recursion - Refactoring to a Pure Function

    Previous post: http://www.cnblogs.com/Answer1215/p/4990418.html let input, config, tasks; input = [' ...

  7. Unix C++(boost) 线程同步和线程组

    #include <boost/thread.hpp> #include <iostream> #include <vector> #include <cst ...

  8. MFC中全局变量的定义及使用

    用MFC制作的工程由很多文件构成,它不能象一般C++程序那样随意在类外定义全局变量,在这里要想定义能被工程内多个文件共享的全局变量和函数必须用一些特殊方法才行.实际上有多种方法可以实现,这里只介绍两种 ...

  9. MediaPlayer+SurfaceView 视频播放 示例

    SurfaceView的原理         SurfaceView在视频播放中起到显示画面的作用,而视频的播放主要通过MediaPlayer来控制.         SurfaceView 允许我们 ...

  10. Java数据库连接之配置ODBC数据源

    java使用JDBC-ODBC桥接连接SQLServer数据库需要配置ODBC数据源,配置步骤如下: 1.进入控制面板,找到管理工具 2.看到ODBC数据源,有64位和32位的,如果你的数据库是64位 ...