首页 文章 精选 留言 我的

精选列表

搜索[Rust构建],共10000篇文章
优秀的个人博客,低调大师

Python Django(WEB电商项目构建)

(坚持每一天,就是成功) Python Django Web框架,Django是一个开放源代码的Web应用框架,由Python写成。采用了MTV的框架模式,即模型M,模板T和视图V组成。 安装Python 和 Django可以自己查阅资料 此文均在Pycharm下进行需要下载可加群:607021567找群主,本文主要介绍电商产品。所以可自行学习,创造自己的网站。 1、Django架构设计: Django是一个基于 MVC构造的框架。但是在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),称为 MTV模式。它们各自的职责如下: 层次 职责 模型(Model),即数据存取层 处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。 模板(Template),即业务逻辑层 处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。 视图(View),即表现层 存取模型及调取恰当模板的相关逻辑。模型与模板的桥梁。 2、工作机制: (这里的文件顺序或包含文件夹并不相同,我是为了介绍各个文件,所以拼接到一起。) 1.用manage .py runserver 启动Django服务器时就载入了在同一目录下的settings .py。这里的settings.py文件内包含着数据库信息的设置,静态文件的设置,静态文件指(js,css,html,images)等,settings.py文件是我们django框架的核心文件之一。该文件包含了项目中的配置信息,如前面讲的URLConf等,其中最重要的配置就是ROOT_URLCONF,它告诉Django哪个Python模块应该用作本站的URLConf,默认的是urls .py。 2.当访问url的时候,Django会根据ROOT_URLCONF的设置来装载URLConf。 3.然后按顺序逐个匹配URLConf里的URLpatterns。如果找到则会调用相关联的视图函数(index.py),并把HttpRequest对象作为第一个参数(通常是request)(函数的参数是request)。 4.最后该view函数负责返回一个HttpResponse对象(html网页)。 这里的核心文件已经介绍完,剩下的文件可以在我们熟悉django框架后在认识,所以不一一介绍了! 3、部署: Django可以运行在Apache,Nginx上,也可以运行在支持WSGI,FastCGI的服务器上。支持多种数据库,已经支持Postgresql,MySql, Sqlite3,Oracle。Google App Engine也支持Django的某些部分,国内支持的平台有(SAE)Sina App Engine,(BAE)百度应用引擎。 4、管理文件夹 接下来介绍核心文件夹,这里是分类清楚我们的文件该怎么去管理: (一)、这里的文件夹名字可以自己任意去命名,第一行是我们的django项目的主文件夹名字,默认主文件夹下可以自己创建自己的py文件的文件夹,不过pycharm自动创建了py文件的文件夹,命名规则是以主文件夹命名。 (二)、第二行就是我们的py文件所在的文件夹,这些py文件主要是我们操作前端到后台所需要的。 (三)、第三行为我们的静态文件目录包含———:Js、Css、Html、img、fonts等文件 (四)、第四行主要是我们的Html模板文件目录,这里存放我们的主页,后台管理页的html文件。 (五)、manage.py启动文件 5、电商项目——产品数据,后台管理 电商项目用户部分:主要分为三大类——1、用户浏览商品 ,2、购买商品 ,3、管理订单 电商项目管理部分:主要也为三大类——1、商品数据整合网站 ,2、接受用户信息数据存入后台(注册和管理),2、处理用户订单问题 分析到这里首先进行电商管理部分,商品数据整合——SqlServer + Django: 首先我们需要创建连接数据库py文件——dataas.py: 1 class oneic_settings: 2 MSSQL_INFO = {"hostname":"xxx","username":"xxx","password":"xxx","dbname":"xx"} 接下来创建对数据库详细操作的py文件——data_db.py: 1 from dataas import oneic_settings 2 def mssqlserver_conn_db(): 3 try: 4 #strconn= 'DSN=test;uid='+oneic_settings.MSSQL_INFO.get("username")+';PWD='+oneic_settings.MSSQL_INFO.get("password") 5 strconn= 'DRIVER={SQL Server};SERVER='+oneic_settings.MSSQL_INFO.get("hostname")+';DATABASE='+oneic_settings.MSSQL_INFO.get("dbname")+';UID='+oneic_settings.MSSQL_INFO.get("username")+';PWD='+oneic_settings.MSSQL_INFO.get("password") 6 db = pyodbc.connect(strconn) 7 return db 8 except Exception,e: 9 print e 这里首先使用准备好的sql文件,就是我们的详细数据文件。 6、电商项目——后台部分 1、网站首页各个页面的html模板,这里的模板就是需要各位自己去创造了,这里需要储备前端的基础知识,包括:JS,CSS,HTML基础技能,也可直接下载现成的模板。 2、管理静态文件——settings.py: 1 TEMPLATE_DIRS = ( 2 'E:/Oneic_new/Oneic_new', 3 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". 4 # Always use forward slashes, even on Windows. 5 # Don't forget to use absolute paths, not relative paths. 6 ) 7 STATIC_URL = 'E:/Oneic_new/static/' 8 STATIC_ROOT = 'E:/Oneic_new/static/' 9 10 TEMPLATE_DIRS = (os.path.join(BASE_DIR, 'templates'),) 这里主要修改STATIC_URL 和 STATIC_ROOT文件。 3、策划url.py文件——控制网页首页显示: 1 from django.conf import settings 2 (r'^static/(?P<path>.*)$','django.views.static.serve',{'document_root':settings.STATIC_ROOT}), 3 url(r'^admin/', include(admin.site.urls)), 4 url(r'$','Oneic_new.index.new_html') 这写代码除了3行,剩余是我需要添加的代码,第2行就是静态文件的部署,4行是django所要找到url的位置。 4、处理数据传入操作——index.py: 1 import common 2 import sms 3 from uc import getShopCart,checkLogin 4 def basicinfo(request): 5 logininfo = checkLogin(request) 6 if logininfo and logininfo.get('loginuserid') != None and logininfo.get('loginuserid')!="": 7 userdata={} 8 if logininfo.get('usertype') == None or logininfo.get('usertype') == "" or logininfo.get('usertype') == "0": 9 return HttpResponseRedirect('/selectType.html') 10 mssql_conn = common.mssqlserver_conn_db() 11 cs = mssql_conn.cursor() 12 cs.execute("{call sp_member_Allinfo_get_py (?)}", logininfo.get('loginuserid')) 13 q = cs.fetchone() 14 cs.commit() 15 if (q and len(q) > 0): 16 if q[0] != 0: 17 userdata['mp'] = q[1] 18 userdata['realname'] = q[2] 19 userdata['corname'] = q[3] 20 userdata['tel'] = q[4] 21 userdata['fax'] = q[5] 22 userdata['pos'] = q[6] 23 userdata['userType'] = q[7] 24 userdata['userLevel'] = q[8] if q[8] else '' 25 userdata['userClass'] = q[9] if q[9] else '' 26 userdata['province'] = q[10] if q[10] else '' 27 userdata['city'] = q[11] if q[11] else '' 28 userdata['district'] = q[12] if q[12] else '' 29 userdata['address'] = q[13] if q[13] else '' 30 userdata['RegTime'] = q[14].strftime('%Y-%m-%d %H:%M:%S') if q[14] else '' 31 userdata['LastLoginTime'] = q[15].strftime('%Y-%m-%d %H:%M:%S') if q[15] else '' 32 userdata['LastLoginIP'] = q[16] if q[16] else '' 33 userdata['LoginCount'] = q[17] if q[17] != None else '' 34 userdata['Email'] = q[18] if q[18] else '' 35 userdata['lottery_num'] = q[19] if q[19] != None else 0 36 userdata['integral_num'] = q[20] if q[20] != None else 0 37 userdata['po_num'] = q[21] if q[21] != None else 0 38 userdata['work_order_num'] = q[22] if q[22] != None else 0 39 userdata['rfq_num'] = q[23] if q[23] != None else 0 40 logininfo['userdata'] = userdata 41 cs.close() 42 mssql_conn.close() 43 return render_to_response('index.html',logininfo) 44 else: 45 return HttpResponseRedirect('/signin') 这里包含cookie检测:checkLogin.py文件——cookie检测。logininfo——为我们需要的数据就是要在网页中显示的数据。 checkLogin.py: 1 from django.conf import settings 2 #检测是否登录 3 def checkLogin(req): 4 edition_id = settings.SESSION_CSSID 5 eny_email = req.COOKIES.get(settings.SESSION_COOKIE_MAIL,'') 6 eny_mp = req.COOKIES.get(settings.SESSION_COOKIE_MP,'') 7 eny_userid = req.COOKIES.get(settings.SESSION_COOKIE_UID,'') 8 eny_usertype = req.COOKIES.get(settings.SESSION_COOKIE_UTYPE,'') 9 10 cartlist = getShopCart(req) 11 login_info = {"cartlist":cartlist,"cartnum":len(cartlist),"loginemail":"","loginuserid":"","loginmp":"","usertype":"","css_id":edition_id} 12 if eny_email != "": 13 login_info['loginemail'] = DES.decrypt(str(eny_email)) 14 if eny_usertype: 15 login_info['usertype'] = DES.decrypt(str(eny_usertype)) #DES为加密的py文件,可以自己随便写! 16 if eny_userid != "": 17 login_info['loginuserid'] = DES.decrypt(str(eny_userid)) 18 cartnum = getShoppcartNum(login_info.get('loginuserid')) 19 login_info['cartnum'] = cartnum 20 if eny_mp != "": 21 mphone = DES.decrypt(str(eny_mp)) 22 enymp = [] 23 mp=list(mphone) 24 for i in range(0,len(mp)): 25 if i>2 and i<7: 26 mp[i]=chr(42) 27 enymp.append(mp[i]) 28 else: 29 enymp.append(mp[i]) 30 eny_Mp = ''.join(enymp) 31 login_info['loginmp'] = eny_Mp 32 login_info['mp'] = DES.decrypt(str(eny_mp)) 33 34 return login_info 这里是后台基本完成的项目了之一!WEB的是需要一步一步去扩建,所以我只是介绍一下我们日常项目的简单介绍,如果又不太详细的可加群! 7、电商项目——前端构造: 这里JS,CSS我不去解释了,因为他们是前端的基础应用,其中与python密切结合的是html: 所以我简单介绍一下在html文件中怎么去应用我们后台传入的数据: 1、值传入: 1、<link rel="stylesheet" type="text/css" href="/css/www_style.css?v={{ css_id }}" /> 2、<div><p>{{参数}</p></div> 这里的值与参数都是“ {{ 参数 }} ”两个大括号嵌入的。 2、判断——可直接在html中写if else语句: 1 {% if condition %} 2 ... display 3 {% endif %} 4 5 or 6 7 {% if condition1 %} 8 ... display 1 9 {% elif condition2 %} 10 ... display 2 11 {% else %} 12 ... display 3 13 {% endif %} 这里的用法和python文件中用法无异。 3、嵌入网页: 1 {% include 'template/footer.html' %} 一定要写路径。 至此,总体电商项目初入门介绍完毕,剩下的就是需要自己来创造其它的管理层页面。加油!之后也许继续会出多层次界面的介绍,请期待!Welcome to Python world! I have a contract in this world! How about you?

优秀的个人博客,低调大师

使用 Docker 镜像构建 GO 语言环境

1. 安装 Docker 我当前使用的系统环境是CentOS7,安装Docker使用的命令是yum install docker*。至于其它系统,可以到百度查找其对应的安装方式。 2. 配置 Docker 镜像仓库的地址 目前来说,直接访问 Docker 官网的 DockerHub 会比较慢, 不过幸好现在国内出现了一些 DockerHub 的加速网站。 下面使用 ustc 加速器。 修改文件 /etc/docker/daemon.json,将其内容修改为 1 2 3 { "registry-mirrors" : [ "https://docker.mirrors.ustc.edu.cn" ] } 配置完成后,重启 Docker 服务:systemctl restart docker 这样就可以使用 https://docker.mirrors.ustc.edu.cn 加速器了。 如果 ustc 的加速器速度不够快,还可以尝试一下其它的加速器,具体请参考这里Docker 镜像加速器 3. 下载 golang 的 Docker 镜像 现在就可以下载 golang 的 Docker 镜像了。 在命令行执行命令 docker search golang 就可以查询 golang 镜像的信息了。 1 2 3 4 5 6 $ docker search golang INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED docker.io docker.io /golang Go (golang) is... 1649 [OK] docker.io docker.io /circleci/golang Go (golang) is... 8 docker.io docker.io /resin/artik710-golang Go (golang) is... 1 docker.io docker.io /resin/artik10-golang Go (golang) is... 0 可以看到,在查询结果中排名第一的,STARS 数量最多, 并且 OFFICIAL 选项下面是 OK ,说明是官方的,所以理论上应该是更可信的。 所以我们就选择使用第一个了。 执行命令 docker pull docker.io/golang 来下载 golang 的官方镜像吧。 $ docker pull docker.io/golang [root@fengbo golang]$ docker pull docker.io/golang Using default tag: latest Trying to pull repository docker.io/library/golang ... latest: Pulling from docker.io/library/golang 723254a2c089: Extracting [===============================> ] 40.83 MB/45.12 MB abe15a44e12f: Download complete 409a28e3cc3d: Download complete 503166935590: Download complete abe52c89597f: Download complete ce145c5cf4da: Downloading [===============> ] 31.36 MB/104.3 MB 96e333289084: Download complete 39cd5f38ffb8: Download complete 39cd5f38ffb8: Pulling fs layer 下载好了之后,查看一下镜像的信息 docker images golang [root@fengbo golang]$ docker images golang REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/golang latest 138bd936fa29 4 weeks ago 733.3 MB 4. 使用 golang 镜像 执行命令docker run -it --rm golang bash,测试一下刚刚下载的 golang 镜像 [root@fengbo golang]$ docker run -it --rm golang bash root@9e46b1255f4b:/go# go version go version go1.9.2 linux/amd64 可以看到,最新的是 1.9.2 版本的。 查看进到容器后的默认目录 root@9e46b1255f4b:/go# pwd /go 看来是在 /go 目录下面。 不过因为我们在创建容器的时候加了 --rm 参数,所以当我们执行 exit 命令退出容器的时候,这个临时容器会被删除。 那我们如何使用这个 golang 的镜像来工作呢? 5. golang 的 Docker 镜像的一种使用方式 首先,如果我们把文件直接写在 Docker 容器里面的话,那么数据是无法持久化的。 即使可以使用 docker cp 命令这样的方式把我们的文件复制到容器内部, 或者把文件从容器中复制出来,但是在操作的时候仍会有很多不方便的地方。 而且,在 golang 的镜像中进行 build 操作的时候,程序依赖的第三方包, 会被下载到容器的 /go 目录下面。如果每次容器都删除, 或者每次创建新的容器的时候,都需要从网络上拉取一次第三方包。 如果网速快的话还好,否则时间浪费的有点儿严重。 所以,我们要把主机的目录映射到容器中,这样就可以把文件进行持久化了。 我们可以使用 docker 命令的 -v 参数,把主机的目录映射到容器中。 不过只使用 -v 参数的话,在容器内部操作目录会有权限限制, 所以还需要增加 --privileged 参数给容器放权。 [root@fengbo golang]$ pwd # 查看当前所在的目录 /root/golang [root@fengbo golang]$ ls -l # 查看当前目录下的子目录和文件等 total 0 drwxrwxrwx. 2 root root 6 Jan 10 01:19 code drwxrwxrwx. 2 root root 6 Jan 10 01:20 go [root@fengbo golang]$ docker run \ # 执行 docker 命令,创建一个新的容器并运行这个容器 > -it \ # 使用交互模式 > --rm \ # 当退出这个容器时,系统自动删除这个容器 > -v /root/golang/go:/go \ # 把主机的目录 '/root/golang/go' 映射为容器内的目录 '/go' > -v /root/golang/code:/code \ # 把主机的目录 '/root/golang/code' 映射为容器内的目录 '/code' > --privileged \ # 给这个容器超级权限,否则无法操作上面映射进去的两个目录 > docker.io/golang \ # 基于镜像 'docker.io/golang' 创建容器 > bash # 在容器内执行命令 'bash' > root@fe6be9f3b22d:/go# # 已经进入容器了 我们可以在容器的目录 /go 和目录 /code 里面创建一些文件, 然后返回主机查看。 root@bb2942f33960:/go# echo "hello" > /go/h.txt # 在容器内,创建文件 '/go/h.txt' 并写入数据 root@bb2942f33960:/go# echo "world" > /code/w.txt # 在容器内,创建文件 '/code/w.txt' 并写入数据 root@bb2942f33960:/go# exit # 退出容器 exit [root@fengbo golang]# find # 已经回到主机了。在主机的 '/root/golang' 目录下查看文件 . ./code ./code/w.txt # 可以看到文件 'w.txt' ./go ./go/h.txt # 以及文件 'h.txt' [root@fengbo golang]# cat go/h.txt hello [root@fengbo golang]# cat code/w.txt world 使用上面的方法,每次创建了容器,都会把主机上指定的目录映射到容器中,修改的数据也会反映到主机上。 6. 方便以后查阅和直接使用,完整命令如下 开启容器 docker run -it --rm -v /root/golang/go:/go -v /root/golang/code:/code --privileged docker.io/golang bash 本文转自郝峰波博客园博客,原文链接:http://www.cnblogs.com/fengbohello/p/8259904.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

使用openstack构建私有云计算平台

一、系统 ubuntu 10.04 Desktop 机器ip:10.1.29.15 二、nova的安装 1.安装所用的信息服务器:Rabbitmq sudo apt-get install rabbitmq-server 2.安装nova 1)nova包安装 sudo apt-get install python-software-properties sudo add-apt-repository ppa:nova-core/trunk sudo apt-get update 注意:如果sudo add-apt-repository ppa:nova-core/trunk不行,换成sudo add-apt-repository ppa:nova-core/release 2)nova依赖包安装 sudo apt-get install python-nova sudo apt-get install python-greenlet python-mysqldb python-nova nova-common nova-doc nova-api nova-network nova-objectstore nova-scheduler nova-compute euca2ools unzip 3)配置nova(/etc/nova/nova.conf) 这个文件是安装nova后自动生成的,如果没有,估计是系统问题。 vim /etc/nova/nova.conf 机器上内容如下: daemonize=1 dhcpbridge_flagfile=/etc/nova/nova.conf dhcpbridge=/usr/bin/nova-dhcpbridge loggdir=/var/log/nova state_path=/var/lib/nova verbose sql_connection=mysql://root:nova@10.1.29.15/nova s3_host=10.1.29.15 rabbit_host=10.1.29.15 ec2_host=10.1.29.15 verbose ec2_url=http://10.1.29.15:8773/services/Cloud network_manager=nova.network.manager.VlanManager fixed_range=10.0.0.0/12 network_size=8 注意:10.1.29.15是我电脑ip,替换成你自己的ip即可 4)创建群组并授权 addgroup nova chown -R root:nova /etc/nova chmod 644 /etc/nova/nova.conf 3.安装mysql 1)绕过所有安装提示,加快安装速度 bash MYSQL_PASS=nova cat mysql-server-5.1 mysql-server/root_password password $MYSQL_PASS mysql-server-5.1 mysql-server/root_password_again password $MYSQL_PASS mysql-server-5.1 mysql-server/start_on_boot boolean true MYSQL_PRESEED 2)安装mysql apt-get install -y mysql-server 3)编辑/etc/mysql/my.cnf,绑定地址 sed -i s/127.0.0.1/0.0.0.0/g /etc/mysql/my.cnf service mysql restart 注:sed -i s/127.0.0.1/0.0.0.0/g /etc/mysql/my.cnf表示在行内全面用127.0.0.1代替0.0.0.0 4)mysql配置 创建nova数据库 mysql -uroot -p$MYSQL_PASS -e CREATE DATABASE nova; root用户为超级用户权限 mysql -uroot -p$MYSQL_PASS -e GRANT ALL PRIVILEGES ON *.* TO root@% WITH GRANT OPTION; 设置root用户密码 mysql -uroot -p$MYSQL_PASS -e SET PASSWORD FOR root@% = PASSWORD($MYSQL_PASS); 注意:mysql的root用户初始密码为空,在设置密码时候,最好自己设定一个密码来代替$MYSQL_PASS 4.网桥配置 vim /etc/network/interfaces 修改后内容如下: # The loopback network interface auto lo iface lo inet loopback # Networking for NOVA auto br100 iface br100 inet static address 10.1.29.15 netmask 255.0.0.0 network 10.0.0.0 broadcast 10.255.255.255 gateway 10.1.0.254 bridge_ports eth0 bridge_stp off bridge_maxwait 0 bridge_fd 0 # dns-* options are implemented by the resolvconf package, if installed dns-nameservers 59.108.119.3 注意:在官方配置介绍用的是DHCP,这里使用静态ip地址,根据实际情况,修改相应的address、netmask、network、broadcast、gateway、dns等。 最后,重启mysql:sudo /etc/init.d/networking restart 5.nova环境配置 /usr/bin/nova-manage db sync /usr/bin/nova-manage user admin dub /usr/bin/nova-manage project create dubproject dub /usr/bin/nova-manage network create 192.168.0.0/24 1 255 注意:数据名、用户名、项目名等都可以自己设定。 6.nova认证 mkdir –p /root/creds /usr/bin/python /usr/bin/nova-manage project zipfile $NOVA_PROJECT $NOVA_PROJECT_USER /root/creds/novacreds.zip unzip /root/creds/novacreds.zip -d /root/creds/ cat /root/creds/novarc >> ~/.bashrc source ~/.bashrc 注意:要在root下能建立目录,必须是root用户,可以用以下命令: sudo passwd root su root 输入密码,进入root用户 7.重启相关服务 /etc/init.d/libvirt-bin restart; service nova-network restart; service nova-compute restart; service nova-api restart; service nova-objectstore restart; service nova-scheduler restart 注意:/etc/init.d/libvirt-bin代替libirtd,ubuntu中没有libirtd 8.授权ping和ssh命令给VMS euca-authorize -P icmp -t -1:-1 default euca-authorize -P tcp -p 22 default (不能ping或ssh时候,使用以下命令) killall dnsmasq service nova-network restart chgrp kvm /dev/kvm chmod g+rwx /dev/kvm 配置防火墙 # iptables -t nat -A PREROUTING -d 169.254.169.254/32 -p tcp -m tcp dport 80 -j DNAT to-destination 10.1.29.15:8773 注意:10.1.29.15改成你自己机器的ip 8.安装后测试 1)查看mysql中services表数据 mysql -u$root-p$nova nova -e select * from services; 注意:root是用户名,nova是密码,用你自己设定的mysql用户名和密码即可。 2)获取image image=ttylinux-uec-amd64-12.1_2.6.35-22_1.tar.gz wget http://smoser.brickies.net/ubuntu/ttylinux-uec/$image uec-publish-tarball $image mybucket 3)为ssh创建安全认证 euca-add-keypair mykey > mykey.priv chmod 0600 mykey.priv 4)查看镜像 euca-describe-images 5)运行 euca-run-instances $emi -k mykey -t m1.tiny 注意:$emi用实际的代替,如:ami-u5o8a5lg euca-describe-instances ssh -i mykey.priv root@10.1.29.15 euca-terminate-instances ami-u5o8a5lg-id 到此,nova的私有云就安装完毕 本文转自 念槐聚 博客园博客,原文链接:http://www.cnblogs.com/haochuang/archive/2011/11/24/2262016.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

基于kubernetes构建Docker集群管理详解

一、环境部署 1、平台版本说明 1)Centos7.0 OS 2)Kubernetes V0.6.2 3)etcd version 0.4.6 4)Docker version 1.3.2 2、平台环境说明 192.168.1.20 kubernetes etcd 192.168.1.21 kubernetes docker 192.168.1.22 kubernetes docker 192.168.1.23 kubernetes docker 在这张系统架构图中,我们把服务分为运行在工作节点上的服务和组成集群级别控制板的服务。 Kubernetes节点有运行应用容器必备的服务,而这些都是受Master的控制。 每次个节点上当然都要运行Docker。Docker来负责所有具体的映像下载和容器运行。 Kubernetes主要由以下几个核心组件组成: etcd保存了整个集群的状态; apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制; controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等; scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上; kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理; Container runtime负责镜像管理以及Pod和容器的真正运行(CRI); kube-proxy负责为Service提供cluster内部的服务发现和负载均衡; 3、环境安装 1)系统初始化工作(所有主机) 系统安装-选择[最小化安装] # yum -y install wget ntpdate bind-utils lrzsz vim # wget http://mirror.centos.org/centos/7/extras/x86_64/Packages/epel-release-7-6.noarch.rpm # yum update CentOS 7.0默认使用的是firewall作为防火墙,这里改为iptables防火墙(熟悉度更高,非必须)。 1.1、关闭firewall: # systemctl stop firewalld.service #停止firewall # systemctl disable firewalld.service #禁止firewall开机启动 2 )安装Etcd Kubernetes(192.168.1.20主机) #yum install etcd kubernetes -y 3 )安装Kubernetes docker(192.168.1.21,192.168.1.22,192.168.1.23主机) #yum install kubernetes docker -y 4、启动服务 1) master 启动服务(192.168.1.20) #systemctl daemon-reload #systemctl enable kube-apiserver.service #systemctl start kube-apiserver.service #systemctl enable kube-controller-manager #systemctl start kube-controller-manager #systemctl enable kube-controller-manager #systemctl start kube-controller-manager ####通过systemctl status <service> 查看服务是否启动成功 此处修改过的配置文件 #cat /etc/kubernetes/config | grep -v ^# | grep -v ^$ KUBE_LOGTOSTDERR="--logtostderr=false"#设置为false表示将日志写入文件 KUBE_LOG_LEVEL="--v=2"#日志级别 KUBE_ALLOW_PRIV="--allow-privileged=false" #如果设置为true,则kubernetes将允许pod中运行拥有系统特权的容器应用 KUBE_MASTER="--master=http://192.168.1.20:8080" #cat /etc/kubernetes/apiserver | grep -v ^# | grep -v ^$ KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"#apiserver绑定主机的非安全ip地址 KUBE_API_PORT="--port=8080"#apiserver绑定主机的非安全端口号,默认8080 KUBE_ETCD_SERVERS="--etcd-servers=http://192.168.1.20:2379" KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"#server地址段,不能与实际ip冲突 KUBE_ADMISSION_CONTROL="--admission- control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota" #kubernetes集群的准入控制设置 KUBE_API_ARGS="" 2) slave启动服务 (192.168.1.21,192.168.1.22,192.168.1.23) #systemctl daemon-reload #systemctl enable kubelet #systemctl start kubelet #systemctl enable kube-proxy #systemctl start kube-proxy #cat /etc/kubernetes/kubelet | grep -v ^# | grep -v ^$ KUBELET_ADDRESS="--address=127.0.0.1" KUBELET_HOSTNAME="--hostname-override=192.168.1.21"#master里获取的minion名字 KUBELET_API_SERVER="--api-servers=http://192.168.1.20:8080" KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/podinfrastructure:latest" KUBELET_ARGS="--logtostderr=true --log-dir=/var/log/kubernetes --v=2" 使用kubectl get nodes 查看已经加进来的node 本文转自 转身撞墙角 51CTO博客,原文链接:http://blog.51cto.com/chentianwang/1957398

优秀的个人博客,低调大师

【docker】基于Dockerfile构建monogdb服务镜像

YUM源创建的Dockerfile内容为: [root@docker1 Mongodb]# vi Dockerfile #设置从我们之前创建的sshd镜像继承 FROM sshd:centos MAINTAINER waitfish from dockerpool.com ADD mongodb-3.2.repo /etc/yum.repos.d/ RUN \ yum update -y && \ yum install -y mongodb-org && \ #这里不推荐使用yum安装monodb,实在下载速度太慢 yum clean all # 创建mongodb存放数据文件的文件夹 RUN mkdir -p /data/db VOLUME /data/db ENV AUTH yes # Add run scripts 添加脚本 ADD run.sh /run.sh ADD set_mongodb_password.sh /set_mongodb_password.sh RUN chmod 755 ./*.sh EXPOSE 27017 EXPOSE 28017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% MongoDB是一款可扩展、高性能的开源文档(Document-Oriented)数据库。它采用C++开发,支持复杂的数据类型和强大的查询语言,提供了关系数据库的绝大部分功能。MongoDB由于其高性能、易部署、易使用等特点,已经在各种领域都得到了广泛的应用。 ① 下载文件 从GitHub Dockerpool社区账户下载Mongodb镜像项目: [root@docker1 ~]# git clone https://github.com/DockerPool/Mongodb.git Cloning into 'Mongodb'... remote: Counting objects: 12, done. remote: Compressing objects: 100% (10/10), done. remote: Total 12 (delta 2), reused 12 (delta 2), pack-reused 0 Unpacking objects: 100% (12/12), done. 查看内容,包括写好的Dockerfile和若干脚本等: [root@docker1 ~]# cd Mongodb/ [root@docker1 Mongodb]# ls Dockerfile mongodb-3.2.repo mongodb-linux-x86_64-rhel70-3.6.0.tgz pwgen-2.08.tar.gz run.sh set_mongodb_password.sh ② 其中Dockerfile内容为: [root@docker1 Mongodb]# cat Dockerfile #设置从我们之前创建的sshd镜像继承 FROM sshd:centos MAINTAINER waitfish from dockerpool.com COPY mongodb-linux-x86_64-rhel70-3.6.0.tgz /mongodb-linux-x86_64-rhel70-3.6.0.tgz COPY pwgen-2.08.tar.gz /pwgen-2.08.tar.gz RUN yum update -y && yum install -y gcc automake autoconf libtool make RUN tar -xf pwgen-2.08.tar.gz WORKDIR pwgen-2.08 RUN ./configure && make && make install #定义工作目录 WORKDIR / RUN tar -xf mongodb-linux-x86_64-rhel70-3.6.0.tgz RUN mv mongodb-linux-x86_64-rhel70-3.6.0 /usr/local/mongodb #设置环境变量 ENV PATH /usr/local/mongodb/bin:$PATH #删除压缩包 RUN rm -rf mongodb-linux-x86_64-rhel70-3.6.0.tgz pwgen-2.08.tar.gz # 创建mongodb存放数据文件的文件夹 RUN mkdir -p /data/db VOLUME /data/db ENV AUTH yes # Add run scripts 添加脚本 ADD run.sh /run.sh ADD set_mongodb_password.sh /set_mongodb_password.sh RUN chmod 755 ./*.sh EXPOSE 27017 EXPOSE 28017 CMD ["/run.sh"] ③ set_mongodb_password.sh脚本主要负责配置数据库的用户名和密码,内容为: [root@docker1 Mongodb]# cat set_mongodb_password.sh #这个脚本主要设置数据库的用户名和密码 #!/bin/bash #判断是否已经设置过密码 if [ -f /.mongodb_password_set ]; then echo "MongoDB password already set!" exit 0 fi /usr/local/mongodb/bin/mongod --smallfiles --nojournal & PASS=${MONGODB_PASS:-$(pwgen -s 12 1)} _word=$( [ ${MONGODB_PASS} ] && echo "preset" || echo "random" ) RET=1 while [[ RET -ne 0 ]]; do echo "=> Waiting for confirmation of MongoDB service startup" sleep 5 mongo admin --eval "help" >/dev/null 2>&1 RET=$? done #通过docker logs + id可以看到下面的输出 echo "=> Creating an admin user with a ${_word} password in MongoDB" mongo admin --eval "db.addUser({user: 'admin', pwd: '$PASS', roles: [ 'userAdminAnyDatabase', 'dbAdminAnyDatabase' ]});" mongo admin --eval "db.shutdownServer();" echo "=> Done!" touch /.mongodb_password_set echo "========================================================================" echo "You can now connect to this MongoDB server using:" echo "" echo " mongo admin -u admin -p $PASS --host <host> --port <port>" echo "" echo "Please remember to change the above password as soon as possible!" echo "========================================================================" ④ run.sh脚本是主要的启动脚本,内容为: [root@docker1 Mongodb]# cat run.sh #!/bin/bash if [ ! -f /.mongodb_password_set ]; then /set_mongodb_password.sh fi if [ "$AUTH" == "yes" ]; then export mongodb='/usr/local/mongodb/bin/mongod --nojournal --auth --httpinterface --rest' else export mongodb='/usr/local/mondodb/bin/mongod --nojournal --httpinterface --rest' fi if [ ! -f /data/db/mongod.lock ]; then eval $mongodb else export mongodb=$mongodb' --dbpath /data/db' rm /data/db/mongod.lock mongod --dbpath /data/db --repair && eval $mongodb fi ⑤ 创建镜像 根据Dockerfile创建镜像mongodb:latest: [root@docker1 Mongodb]# docker build -t mongodb . [root@docker1 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mongodb latest adf9a26bb498 15 minutes ago 1.19 GB ...... ⑥ 使用示范: 启动后台容器,并分别映射27017,28017,22端口到本地: [root@docker1 Mongodb]# docker run -d -p 27017:27017 -p 28017:28017 -p 37017:22 mongodb b38f560ba2b16a4e0c9c5b77c02e2e07b9f45eed8ce7de5dd2d6755d8d962050 [root@docker1 Mongodb]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b38f560ba2b1 mongodb "/run.sh" 4 seconds ago Up 3 seconds 0.0.0.0:27017->27017/tcp, 0.0.0.0:28017->28017/tcp, 0.0.0.0:37017->22/tcp trusting_pasteur [root@docker1 Mongodb]# docker logs b38f560ba2b1 ...... ======================================================================== You can now connect to this MongoDB server using: mongo admin -u admin -p NQ1VmsSWUwF1 --host <host> --port <port> Please remember to change the above password as soon as possible! ======================================================================== ...... 输出中的 NQ1VmsSWUwF1 就是admin用户的密码 还可以利用环境变量在容器启动时指定密码: [root@docker1 Mongodb]# docker run -d -p 27017:27017 =p 37017:22 -e MONGODB_PASS="mypass" mongodb 甚至,设定不需要密码: [root@docker1 Mongodb]# docker run -d 27017:27017 -p 28017:28017 -e AUTH=no mongodb 同样,读者可以使用-v参数来映射本地目录到容器。 ⑦ 详细启动参数: Mongodb的启动参数有很多,包括: --quiet #安静输出 --port arg #指定服务端口号,默认端口27017 --bind_ip arg #绑定服务IP,若绑定127.0.0.1,则只能本机访问,不指定默认本地所有IP --logpath arg #指定Mongodb日志文件,注意是指定文件不是目录 --logappend #使用追加的方式写日志 --pidfilepath arg #PID File的完整路径,如果没有设置,则没有PID文件 --keyFile arg #集群的私钥的完整路径,只对于Replica Set架构有效 --unixSocketPrefix arg #UNIX域套接字替代目录,(默认为/tmp) --fork #以守护进程的方式运行MongoDB,创建服务器进程 --auth #启用验证 --cpu #定期显示CPU的利用率和iowait --dbpath arg #指定数据库路径 --dialog arg #diaglog选项 0=off 1=w 2=R 3=both 7=W+some reads --directoryperdb #设置每个数据库将被保存在一个单独的目录 --journal #启用日志选项,MongoDB的数据操作将会写入到journal文件夹的文件里 --journalOptions arg #启用日志诊断选项 --ipv6 #启用ipv6选项 --jsonp #允许JSONP形式通过HTTP访问(有安全影响) --maxConns args #最大同时连接默认2000 --noauth #不启用验证 --nohttpinterface #关闭http接口,默认关闭27018端口访问 --noprealloc #禁用数据文件预分配(往往影响性能) --noscripting #禁用脚本引擎 --notablescan #不允许表扫描 --noubixsocket #禁用Unix套接字监听 --nssize arg (=16) #设置信数据库.ns文件大小(MB) --objcheck #在收到客户数据,检查的有效性 --profile arg #档案参数 0=off 1=slow 2=all --quota #限制每个数据库的文件数,设置默认为8 --quotaFiles arg #number of filess allower per db, requires --quota --rest #开启简单的rest API --repair #修复所有数据库run repair on all dbs --repairpath arg #修复库生成的文件的目录,默认为目录名称dbpath --slowms arg (=100) #value of slow for profile and console log --smallfiles #使用较小的默认文件 --syncdelay arg (=60) #数据写入磁盘的时间秒数(0=never,不推荐) --sysinfo #打印一些诊断系统信息 --upgrade #如果需要升级数据库 * Replication 参数 --------------------------------------------------------------------------------------------------- --fastsync #从一个dbpath里启用从库复制服务,该dbpath的数据库是主库的快照,可用于快速启用同步 --autoresync #如果从库与主库同步数据差得多,自动重新同步 --oplogSize arg #设置oplog的大小(MB) * 主/从参数 --------------------------------------------------------------------------------------------------- --master #主库模式 --slave #从库模式 --source arg #从库 端口号 --only arg #指定单一的数据库复制 --slavedelay arg #设置从库同步主库的延迟时间 * Replica set(副本集)选项 -------------------------------------------------------------------------------------------------- --relSet arg #设置副本集名称 * Sharding(分片)选项 -------------------------------------------------------------------------------------------------- --configsvr #声明这是一个集群的config服务,默认端口为27019,默认目录/data/configdb --shardsvr #声明这是一个集群的分片,默认端口27018 --noMoveParanoia #关闭偏执为moveChunk数据保存 上述参数也可以直接在mongod.conf配置文件中配置,例如: dbpath = /data/mongodb logpath = /data/mongodb/mongodb.log logappend = true fork = true auth = true 本文转自 Mr_sheng 51CTO博客,原文链接:http://blog.51cto.com/sf1314/2048024

优秀的个人博客,低调大师

详解Dialog(二)——有关列表的构建

一、普通列表 普通列表的样式是这样的: 要实现这样的列表样式,是通过下面的方法来实现的: [java] view plain copy builder.setItems(CharSequence[]items,DialogInterface.OnClickListenerlistener) builder.setItems(intitemsId,DialogInterface.OnClickListenerlistener) 这两种方法实现的效果都是一样的, [java] view plain copy setItems(CharSequence[]items,DialogInterface.OnClickListenerlistener) 这个items传进去的是一个字符串数组; [java] view plain copy setItems(intitemsId,DialogInterface.OnClickListenerlistener) 这个传进去的一个itemsId,是在XML中定义好的一个字符串数组资源的ID; 下面,我们一个个看看他们的具体用法: 1、字符串数组 下面是上图是实现上图效果的代码: [java] view plain copy String[]mItems={"item0","item1","itme2","item3","itme4","item5","item6"}; AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("使用列表字符串"); builder.setItems(mItems,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } }); builder.create(); builder.show(); 可以看到首先构造一个mItems数组,然后在buidler.setItems直接传进去就好了。至于DialogInterface.OnClickListener(){}函数就是对点击事件的监听,which表示当前点击的是哪个ITEM的索引。 2、字符串资源ID 首先在xml文件夹下建一个字符串资源XML,命名为:array.xml,位置如图: 然后定义一段字符串数组: [java] view plain copy <?xmlversion="1.0"encoding="utf-8"?> <resources> <string-arrayname="dialog_items"> <item>王菲</item> <item>王力宏</item> <item>帅哥</item> <item>美女</item> </string-array> </resources> 下面就是利用SetItem来生成列表了: [java] view plain copy AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("使用ResourceID"); builder.setItems(R.array.dialog_items,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } }); builder.create(); builder.show(); 在这里的SetItems时直接将我们字符串数组的name直接设置进去,出来的效果就是这样的: 二、单选列表 单选列表的样式是这样的: 要实现单选列表,主要是通过下面四个其中之一来实现的: 方法一: [java] view plain copy setSingleChoiceItems(CharSequence[]items,intcheckedItem,DialogInterface.OnClickListenerlistener) 与上面一样,传进去一个字符串数组,和初始化时选中的ITEM,构造一个单选列表 方法二: [java] view plain copy setSingleChoiceItems(intitemsId,intcheckedItem,DialogInterface.OnClickListenerlistener) 同样,与上面的例子相同,这里传进去的是一个字符串数组的资源ID,字符串数组的构造方法与上面相同,就不再赘述 方法三: [java] view plain copy setSingleChoiceItems(ListAdapteradapter,intcheckedItem,DialogInterface.OnClickListenerlistener) 这 个方法是最难理解的方法,因为这里的ListAdapter并不能是普通的Adapter,不信你传一个Adapter,保证出来只是你自己的ITEM视 图,旁边的单选按钮却出不来,其实这里的Adapter只是重写单选按钮旁的文字的样式,并不支持所有的Adapter,这个我会在本文最后讲述。方法四: [java] view plain copy setSingleChoiceItems(Cursorcursor,intcheckedItem,StringlabelColumn,DialogInterface.OnClickListenerlistener) 这里通过传进去一个Cursor来构造对应的字符串数组,可以是数据库Cursor,也可以其它系统自带的数据Cursor,但基本上用不到,就不再讲了 好了,关于方法三,因为下面会接着讲SetAdapter的知识,所以这部分我留在最后再讲,这里先讲下方法一和方法二: 方法一和方法二,与上例没什么区别,下面我就以方法一以例来讲讲上面的效果图是怎么实现的吧: 代码如下: [java] view plain copy String[]mItems={"攻","受","全能型","不告诉你"}; AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("你懂的"); builder.setSingleChoiceItems(mItems,0,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ //TODOAuto-generatedmethodstub Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } }); builder.create(); builder.show(); 很简单,构造一个mItems的String字符串,然后直接传进去setSingleChoiceItems中,默认选中第一个,即索引是0的项。 三、多选列表 先看看效果图: 自带的多选构造函数有如下几个: 方法一: [java] view plain copy setMultiChoiceItems(CharSequence[]items,boolean[]checkedItems,DialogInterface.OnMultiChoiceClickListenerlistener) 一样,传进去一个ITEMS数组和对应的项目的选中与否状态的数组; 方法二: [java] view plain copy setMultiChoiceItems(intitemsId,boolean[]checkedItems,DialogInterface.OnMultiChoiceClickListenerlistener) 这里传进去的是一个字符串数组,与第一部分相同 方法三: [java] view plain copy setMultiChoiceItems(Cursorcursor,StringisCheckedColumn,StringlabelColumn,DialogInterface.OnMultiChoiceClickListenerlistener) 同样,这里传进去的是一个CURSOR,可以是数据库的指针,也可以是系统自带数据的指针,基本不怎么用,就不讲了 下面以方法一为例看看多选列表的构造过程: [java] view plain copy String[]mItems={"经常犯二","傻叉一枚","逗逼","小清纯","沉稳大叔","有时可爱"}; AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("性格类型"); builder.setMultiChoiceItems(mItems, newboolean[]{false,false,false,false,false,false,false}, newDialogInterface.OnMultiChoiceClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich,booleanisChecked){ Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } } ); builder.show(); 这里构造了两个数组,一个是字符串数组,另一个每项对应是否选中的boolean数组 [java] view plain copy String[]mItems={"经常犯二","傻叉一枚","逗逼","小清纯","沉稳大叔","有时可爱"}; 对应的选中项的布尔值数组: [java] view plain copy newboolean[]{false,false,false,false,false,false,false} 四、自定义列表项 这节我带大家自定义列表项的实现,故名思义,就是每个ITEM都是我们自己来定义,使用我们自己的Adapter,先看看效果: 要实现自定义列表主要是造下面这个函数来实现的: [java] view plain copy setAdapter(ListAdapteradapter,DialogInterface.OnClickListenerlistener) 直接将我们构造好的Adapter设置进去。 下面就带大家实现下图示中的视图: 1、构造Adapter 有关派生自BaseAdapter来构造ListViewAdapter的过程就不再细讲了,大家可以参考我以前的两篇文章: 1、《List控件使用---SimpleAdapter使用详解(一)》 2、《BaseAdapter——convertView回收机制与动态控件响应》 第 一篇现在看来着实太烂了,一直想重写又没时间来做,大家可以再搜搜网上的其它相关文章来学一下有关BaseAdapter的相关内容吧。第二篇有关 convertView的回收机制写的还是挺不错的,大家可以仔细看看,相信会对ListView的机制有一个更清晰的理解。废话不多说了,下面言转正 转,看看我们这里的ListAdapter的构造过程: 首先是单个Item的布局:(list_item.xml) 很简单,采用水平布局,左边一个图像,右边一个对应的TEXT,这里只是基本实现功能,大家完全可以在理解这篇文章的基础上派生出更复杂的视图 [java] view plain copy <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="match_parent"> <ImageView android:id="@+id/item_imageview" android:layout_width="80dip" android:layout_height="80dip" android:scaleType="fitCenter"/> <TextView android:id="@+id/item_text" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center_vertical|left" android:textSize="20sp"/> </LinearLayout> 对应的视图类: [java] view plain copy privateclassViewHolder{ publicTextViewmTvTitle; publicImageViewmImageView; } 其中有两个变量,一个存储对应的TextView,另一个存储对应的ImageView; 现在我们还需要一个类来存储视图类中TextView的标题字符串,和对应ImageView的图片资源的ID值,这就是我们的数据类: [java] view plain copy publicstaticclassDataHolder{ publicStringtitle; publicintImageID; publicDataHolder(Stringtitle,intimageID){ this.title=title; this.ImageID=imageID; } } 我们先阶段性的看看我们的ListViewAdapter: 首先是派生自BaseAdapter,然后是构造函数,我们传进去一个DataHolder的列表,用来存储每个Item应该显示的内容 [java] view plain copy publicclassListItemAdapterextendsBaseAdapter{ privateList<DataHolder>mDataList=newArrayList<DataHolder>(); privateLayoutInflatermInflater; publicListItemAdapter(Contextcontext,ArrayList<DataHolder>datalist){ if(datalist!=null&&datalist.size()>0){ mDataList.addAll(datalist); } mInflater=LayoutInflater.from(context); } ……………… } 然后是最关键的getView部分: [java] view plain copy publicViewgetView(intposition,ViewconvertView,ViewGroupviewGroup){ ViewHolderholder=null; if(convertView==null){ holder=newViewHolder(); convertView=mInflater.inflate(R.layout.list_item,null); holder.mTvTitle=(TextView)convertView.findViewById(R.id.item_text); holder.mImageView=(ImageView)convertView.findViewById(R.id.item_imageview); convertView.setTag(holder); }else{ holder=(ViewHolder)convertView.getTag(); } holder.mImageView.setImageResource(mDataList.get(position).ImageID); holder.mTvTitle.setText(mDataList.get(position).title); returnconvertView; } 首先是通过covertView的tag来获取重复利用的convertView,这什么要这么写,看《BaseAdapter——convertView回收机制与动态控件响应》 然后是利用传进来的数据,初始化列表Item: [java] view plain copy holder.mImageView.setImageResource(mDataList.get(position).ImageID); holder.mTvTitle.setText(mDataList.get(position).title); 最后返回convertView,让系统去做绘图 到这里ListViewAdapter的构造过程就基本完成了,下面是完整的代码: [java] view plain copy /** *Createdbyharvic *date2015-1-11 **/ publicclassListItemAdapterextendsBaseAdapter{ privateList<DataHolder>mDataList=newArrayList<DataHolder>(); privateLayoutInflatermInflater; publicListItemAdapter(Contextcontext,ArrayList<DataHolder>datalist){ if(datalist!=null&&datalist.size()>0){ mDataList.addAll(datalist); } mInflater=LayoutInflater.from(context); } @Override publicintgetCount(){ returnmDataList.size(); } @Override publicObjectgetItem(intposition){ returnmDataList.get(position); } @Override publiclonggetItemId(intposition){ returnposition; } @Override publicViewgetView(intposition,ViewconvertView,ViewGroupviewGroup){ ViewHolderholder=null; if(convertView==null){ holder=newViewHolder(); convertView=mInflater.inflate(R.layout.list_item,null); holder.mTvTitle=(TextView)convertView.findViewById(R.id.item_text); holder.mImageView=(ImageView)convertView.findViewById(R.id.item_imageview); convertView.setTag(holder); }else{ holder=(ViewHolder)convertView.getTag(); } holder.mImageView.setImageResource(mDataList.get(position).ImageID); holder.mTvTitle.setText(mDataList.get(position).title); returnconvertView; } privateclassViewHolder{ publicTextViewmTvTitle; publicImageViewmImageView; } publicstaticclassDataHolder{ publicStringtitle; publicintImageID; publicDataHolder(Stringtitle,intimageID){ this.title=title; this.ImageID=imageID; } } } 2、构造列表 在MainActivity中,首先是初始化我们的ListViewAdapter,要初始化Adapter,就要首先传进去一个DataHolder的数组,所有要先构造一个DataHolder的数组 [java] view plain copy privateArrayList<ListItemAdapter.DataHolder>initDataHolder(){ ArrayList<ListItemAdapter.DataHolder>datalist=newArrayList<ListItemAdapter.DataHolder>(); ListItemAdapter.DataHolderdata_1=newListItemAdapter.DataHolder("可爱萌宠1",R.drawable.animal1); ListItemAdapter.DataHolderdata_2=newListItemAdapter.DataHolder("可爱萌宠2",R.drawable.animal2); ListItemAdapter.DataHolderdata_3=newListItemAdapter.DataHolder("可爱萌宠3",R.drawable.animal3); ListItemAdapter.DataHolderdata_4=newListItemAdapter.DataHolder("可爱萌宠4",R.drawable.animal4); datalist.add(data_1); datalist.add(data_2); datalist.add(data_3); datalist.add(data_4); returndatalist; } 在构造完成数据列表之后,下面就是构造我们的自定义的列表了,我把整个对话框显示过程整合成了一个函数createCustomList,代码如下: [java] view plain copy privatevoidcreateCustomList(){ ArrayList<ListItemAdapter.DataHolder>dataHolders=initDataHolder(); ListItemAdapteradapter=newListItemAdapter(MyActivity.this,dataHolders); AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("可爱萌宠"); builder.setAdapter(adapter,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialogInterface,intwhich){ Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } }); builder.create(); builder.show(); } OK啦,到这,整个自列表项的内容就讲完了,下面再回过来给大家说说上面我们提到的有关单选列表自定义Adapter的问题。 五、有关单选列表自定义Adapter 这里主要讲的函数是第二部分单选列表中的方法三: [java] view plain copy setSingleChoiceItems(ListAdapteradapter,intcheckedItem,DialogInterface.OnClickListenerlistener) 在第四部分,我们构造了一个ListAdapter,这里需要的也是同样的一个ListAdapter,那我们直接将第四部分中的Adapter传进去,会是什么效果呢? 也就是利用下面的代码: 我们直接在createCustomList()上面改一下,即把builder.setAdapter()直接换成setSingleChoiceItems() ,传进去Adpter,看看在我们定义的视图后面会不会出现一个单选按钮呢? [java] view plain copy privatevoidcreateCustomList(){ ArrayList<ListItemAdapter.DataHolder>dataHolders=initDataHolder(); ListItemAdapteradapter=newListItemAdapter(MyActivity.this,dataHolders); AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("可爱萌宠"); builder.setSingleChoiceItems(adapter,0,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialogInterface,intwhich){ Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } }); builder.create(); builder.show(); } 运行一下,效果是这样的: 看见了没,毛也没有,坑爹玩意,那这个函数到底是用来做什么的呢,在源码中有这样一个文件: 地址在:$android_sdk_home/platforms/Android-x.x/data/res/layout/simple_list_item_single_choice.xml 文件内容是这样的: [html] view plain copy <CheckedTextViewxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/single_list_item" android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeightSmall" android:textAppearance="?android:attr/textAppearanceListItemSmall" android:gravity="center_vertical" android:checkMark="?android:attr/listChoiceIndicatorSingle" android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" /> 利用这个玩意是可以实现效果的,我们来试一下。 1、新建Adapter 新建一个布局文件,来保存ListVIew的每项的Item,代码如下: [html] view plain copy <CheckedTextViewxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/single_list_item" android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeightSmall" android:textAppearance="?android:attr/textAppearanceListItemSmall" android:gravity="center_vertical" android:checkMark="?android:attr/listChoiceIndicatorSingle" android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" /> 在Adapter中,同样,用来保存ITEM视图的ViewHolder类,如下: [java] view plain copy privateclassViewHolder{ publicTextViewmName; } 因 为在布局中只有一个TextView,所以在ViewHolder中也只需要一个TextView与其对应,至于类似上面的承载对应数据的 DataHolder,因为我们只需要一个String字符串数组就足够了,所以就没必要再新建一个类来承载这些数据了,所以我们要构造Adapter 时,传进来一个字符串数组就好了: 所以简单的构造函数为: 在构造时,传进来我们每项要显示的标题的字符串数组String[] items,并将其直接添加到我们的List<String> mList中。 [java] view plain copy publicclassSingleChoiceAdapterextendsBaseAdapter{ privateLayoutInflatermInflater; privateList<String>mList=newArrayList<String>(); publicSingleChoiceAdapter(Contextcontext,String[]items){ mInflater=LayoutInflater.from(context); if(items==null||items.length<=0){ return; } for(Stringitem:items){ mList.add(item); } } ………… } 然后是最关键的getView()部分: [java] view plain copy publicViewgetView(intposition,ViewconvertView,ViewGroupviewGroup){ ViewHolderholder=null; if(convertView==null){ holder=newViewHolder(); convertView=mInflater.inflate(R.layout.single_choice_item,null); holder.mName=(TextView)convertView.findViewById(R.id.single_list_item); convertView.setTag(holder); }else{ holder=(ViewHolder)convertView.getTag(); } holder.mName.setText(mList.get(position)); returnconvertView; } 这段代码难度不大,就是每次绘图时,将TextView的内容设置为我们指定的字符串: [java] view plain copy holder.mName.setText(mList.get(position)); 下面是SingleChoiceAdapter完整的代码: [java] view plain copy /** *Createdbyharvic *date2015-1-11 */ publicclassSingleChoiceAdapterextendsBaseAdapter{ privateLayoutInflatermInflater; privateList<String>mList=newArrayList<String>(); publicSingleChoiceAdapter(Contextcontext,String[]items){ mInflater=LayoutInflater.from(context); if(items==null||items.length<=0){ return; } for(Stringitem:items){ mList.add(item); } } @Override publicintgetCount(){ returnmList.size(); } @Override publicObjectgetItem(intposition){ returnmList.get(position); } @Override publiclonggetItemId(intposition){ returnposition; } @Override publicViewgetView(intposition,ViewconvertView,ViewGroupviewGroup){ ViewHolderholder=null; if(convertView==null){ holder=newViewHolder(); convertView=mInflater.inflate(R.layout.single_choice_item,null); holder.mName=(TextView)convertView.findViewById(R.id.single_list_item); convertView.setTag(holder); }else{ holder=(ViewHolder)convertView.getTag(); } holder.mName.setText(mList.get(position)); returnconvertView; } privateclassViewHolder{ publicTextViewmName; } } 然后就是使用的阶段了 2、构造单选列表 这里首先构造SingleChoiceAdapter的实例,然后将其传入setSingleChoiceItems中,代码如下: [java] view plain copy String[]mItems={"攻","受","全能型","不告诉你"}; SingleChoiceAdapteradapter=newSingleChoiceAdapter(MyActivity.this,mItems); AlertDialog.Builderbuilder=newAlertDialog.Builder(MyActivity.this); builder.setIcon(R.drawable.ic_launcher); builder.setTitle("可爱萌宠"); builder.setSingleChoiceItems(adapter,0,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialogInterface,intwhich){ Toast.makeText(MyActivity.this,"clicked:"+which,Toast.LENGTH_LONG).show(); } }); builder.create(); builder.show(); 运行出来的效果如图: 看到没,这里效果是出来了,可见,在单选按钮中,定义Adapter并不是随便定义的,只能定义CheckedTextView的视图,其它是不支持的!!!! 好了,到这里本篇就结束了,下篇给大家讲讲有关自定义对话框的内容。 本文转自农夫山泉别墅博客园博客,原文链接:http://www.cnblogs.com/yaowen/p/5434828.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册