首页 文章 精选 留言 我的

精选列表

搜索[手游社交组件],共10000篇文章
优秀的个人博客,低调大师

Centos0S7手动安装OpenStack Pike版--(glance)

#Configure Glance mysql -uroot -ppasswd123 -e "CREATE DATABASE glance" mysql -uroot -ppasswd123 -e "GRANT ALL PRIVILEGES ON glance.TO 'glance'@'localhost' IDENTIFIED BY 'passwd123'" mysql -uroot -ppasswd123 -e "GRANT ALL PRIVILEGES ON glance.TO 'glance'@'%' IDENTIFIED BY 'passwd123'" openstack user create --domain default --password passwd123 glance openstack role add --project service --user glance admin openstack service create --name glance --description "OpenStack Image" image openstack endpoint create --region RegionOne image publichttp://controller:9292 openstack endpoint create --region RegionOne image internalhttp://controller:9292 openstack endpoint create --region RegionOne image adminhttp://controller:9292 openstack-config --set /etc/glance/glance-api.conf database connection mysql+pymysql://glance:passwd123@controller/glance openstack-config --set /etc/glance/glance-api.conf keystone_authtoken auth_urihttp://controller:5000 openstack-config --set /etc/glance/glance-api.conf keystone_authtoken auth_urlhttp://controller:35357 openstack-config --set /etc/glance/glance-api.conf keystone_authtoken memcached_servers controller:11211 openstack-config --set /etc/glance/glance-api.conf keystone_authtoken auth_type password openstack-config --set /etc/glance/glance-api.conf keystone_authtoken project_domain_name Default openstack-config --set /etc/glance/glance-api.conf keystone_authtoken user_domain_name Default openstack-config --set /etc/glance/glance-api.conf keystone_authtoken project_name service openstack-config --set /etc/glance/glance-api.conf keystone_authtoken username glance openstack-config --set /etc/glance/glance-api.conf keystone_authtoken password passwd123 openstack-config --set /etc/glance/glance-api.conf paste_deploy flavor keystone openstack-config --set /etc/glance/glance-api.conf glance_store stores file,http openstack-config --set /etc/glance/glance-api.conf glance_store default_store file openstack-config --set /etc/glance/glance-api.conf glance_store filesystem_store_datadir /var/lib/glance/images/ /etc/glance/glance-registry.conf openstack-config --set /etc/glance/glance-registry.conf database connection mysql+pymysql://glance:passwd123@controller/glance openstack-config --set /etc/glance/glance-registry.conf keystone_authtoken auth_urihttp://controller:5000 openstack-config --set /etc/glance/glance-registry.conf keystone_authtoken auth_urlhttp://controller:35357 openstack-config --set /etc/glance/glance-registry.conf keystone_authtoken memcached_servers controller:11211 openstack-config --set /etc/glance/glance-registry.conf keystone_authtoken auth_type password openstack-config --set /etc/glance/glance-registry.conf keystone_authtoken project_domain_name Default openstack-config --set /etc/glance/glance-registry.conf keystone_authtoken user_domain_name Default openstack-config --set /etc/glance/glance-registry.conf keystone_authtoken project_name service openstack-config --set /etc/glance/glance-registry.conf keystone_authtoken username glance openstack-config --set /etc/glance/glance-registry.conf keystone_authtoken password passwd123 openstack-config --set /etc/glance/glance-registry.conf paste_deploy flavor keystone su -s /bin/sh -c "glance-manage db_sync" glance systemctl enable openstack-glance-api.service openstack-glance-registry.service systemctl start openstack-glance-api.service openstack-glance-registry.service systemctl status openstack-glance-api.service openstack-glance-registry.service source admin-openrc openstack image create "centos7" --file CentOS-7-x86_64-GenericCloud.qcow2 --disk-format qcow2 --container-format bare --public openstack image list 本文转自 OpenStack2015 博客,原文链接: http://blog.51cto.com/andyliu/2069164 如需转载请自行联系原作者

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

Centos0S7手动安装OpenStack Pike版--(keystone)

OpenStack安装指南_Mitakahttp://down.51cto.com/data/2331199 Openstack管理手册-Newton版-CentOS7.2http://down.51cto.com/data/2331201 #Configure Keystone mysql -uroot -ppasswd123 -e "CREATE DATABASE keystone" mysql -uroot -ppasswd123 -e "GRANT ALL PRIVILEGES ON keystone.TO 'keystone'@'localhost' IDENTIFIED BY 'passwd123'" mysql -uroot -ppasswd123 -e "GRANT ALL PRIVILEGES ON keystone.TO 'keystone'@'%' IDENTIFIED BY 'passwd123'" vim /etc/keystone/keystone.conf [database] connection = mysql+pymysql://keystone:passwd123@controller/keystone [token] provider = fernet su -s /bin/sh -c "keystone-manage db_sync" keystone keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone keystone-manage credential_setup --keystone-user keystone --keystone-group keystone keystone-manage bootstrap --bootstrap-password ADMIN_PASS \ --bootstrap-admin-urlhttp://controller:35357/v3/\ --bootstrap-internal-urlhttp://controller:5000/v3/\ --bootstrap-public-urlhttp://controller:5000/v3/\ --bootstrap-region-id RegionOne Configure the Apache HTTP server vim /etc/httpd/conf/httpd.conf ServerName controller ln -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/ systemctl start httpd.service systemctl enable httpd.service systemctl status httpd.service export OS_USERNAME=admin export OS_PASSWORD=passwd123 export OS_PROJECT_NAME=admin export OS_USER_DOMAIN_NAME=Default export OS_PROJECT_DOMAIN_NAME=Default export OS_AUTH_URL=http://controller:35357/v3 export OS_IDENTITY_API_VERSION=3 openstack project create --domain default --description "Service Project" service openstack project create --domain default --description "Demo Project" demo openstack user create --domain default --password passwd123 demo openstack role create user openstack role add --project demo --user demo user unset OS_AUTH_URL OS_PASSWORD openstack --os-auth-urlhttp://controller:35357/v3\ --os-project-domain-name Default --os-user-domain-name Default \ --os-project-name admin --os-username admin token issue openstack --os-auth-urlhttp://controller:5000/v3\ --os-project-domain-name Default --os-user-domain-name Default \ --os-project-name demo --os-username demo token issue vim admin-openrc export OS_PROJECT_DOMAIN_NAME=Default export OS_USER_DOMAIN_NAME=Default export OS_PROJECT_NAME=admin export OS_USERNAME=admin export OS_PASSWORD=passwd123 export OS_AUTH_URL=http://controller:35357/v3 export OS_IDENTITY_API_VERSION=3 export OS_IMAGE_API_VERSION=2 source admin-openrc openstack token issue 本文转自 OpenStack2015 博客,原文链接: http://blog.51cto.com/andyliu/2069163 如需转载请自行联系原作者

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

Centos0S7手动安装OpenStack Pike版--(Evironment)

OpenStack安装指南_Mitakahttp://down.51cto.com/data/2331199 Openstack管理手册-Newton版-CentOS7.2http://down.51cto.com/data/2331201 [root@controller ~]# cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 192.168.137.145 controller 192.168.137.146 compute 192.168.137.149 storage #Install ALL Packages and Configure Evironment yum install centos-release-openstack-pike -y yum install python-openstackclient -y yum install openstack-selinux -y yum install mariadb mariadb-server python2-PyMySQL -y yum install rabbitmq-server -y yum install memcached python-memcached -y yum install etcd -y yum install openstack-keystone httpd mod_wsgi -y yum install openstack-glance -y yum install -y openstack-nova-api openstack-nova-conductor \ openstack-nova-console openstack-nova-novncproxy \ openstack-nova-scheduler openstack-nova-placement-api yum install -y openstack-neutron openstack-neutron-ml2 \ openstack-neutron-linuxbridge ebtables #Configure RabbitMQ systemctl enable rabbitmq-server.service systemctl start rabbitmq-server.service systemctl status rabbitmq-server.service rabbitmqctl add_user openstack passwd123 rabbitmqctl set_permissions openstack "." "." ".*" #Configure Memcached vim /etc/sysconfig/memcached OPTIONS="-l 127.0.0.1,::1,controller" systemctl enable memcached.service systemctl start memcached.service OpenStack服务可以使用户可靠,分布式键值存储的分布式密钥锁定,存储配置,跟踪服务活性等情况。 #Configure Etcd vim /etc/etcd/etcd.conf [root@controller ~]# vim /etc/etcd/etcd.conf #[Member] ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ETCD_LISTEN_PEER_URLS="http://192.168.137.145:2380" ETCD_LISTEN_CLIENT_URLS="http://192.168.137.145:2379" ETCD_NAME="controller" #[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.137.145:2380" ETCD_ADVERTISE_CLIENT_URLS="http://192.168.137.145:2379" ETCD_INITIAL_CLUSTER="controller=http://192.168.137.145:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-01" ETCD_INITIAL_CLUSTER_STATE="new" systemctl enable etcd systemctl start etcd systemctl status etcd 本文转自 OpenStack2015 博客,原文链接:http://blog.51cto.com/andyliu/2069162 如需转载请自行联系原作者

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

Centos0S7手动安装OpenStack Pike版--(nova)

OpenStack安装指南_Mitakahttp://down.51cto.com/data/2331199 Openstack管理手册-Newton版-CentOS7.2http://down.51cto.com/data/2331201 #Configure Nova mysql -uroot -ppasswd123 -e "CREATE DATABASE nova_api" mysql -uroot -ppasswd123 -e "CREATE DATABASE nova" mysql -uroot -ppasswd123 -e "CREATE DATABASE nova_cell0" mysql -uroot -ppasswd123 -e "GRANT ALL PRIVILEGES ON nova_api.TO 'nova'@'localhost' IDENTIFIED BY 'passwd123'" mysql -uroot -ppasswd123 -e "GRANT ALL PRIVILEGES ON nova_api.TO 'nova'@'%' IDENTIFIED BY 'passwd123'" mysql -uroot -ppasswd123 -e "GRANT ALL PRIVILEGES ON nova.TO 'nova'@'localhost' IDENTIFIED BY 'passwd123'" mysql -uroot -ppasswd123 -e "GRANT ALL PRIVILEGES ON nova.TO 'nova'@'%' IDENTIFIED BY 'passwd123'" mysql -uroot -ppasswd123 -e "GRANT ALL PRIVILEGES ON nova_cell0.TO 'nova'@'localhost' IDENTIFIED BY 'passwd123'" mysql -uroot -ppasswd123 -e "GRANT ALL PRIVILEGES ON nova_cell0.TO 'nova'@'%' IDENTIFIED BY 'passwd123'" source admin-openrc openstack user create --domain default --password passwd123 nova openstack role add --project service --user nova admin openstack service create --name nova --description "OpenStack Compute" compute openstack endpoint create --region RegionOne compute publichttp://controller:8774/v2.1 openstack endpoint create --region RegionOne compute internalhttp://controller:8774/v2.1 openstack endpoint create --region RegionOne compute adminhttp://controller:8774/v2.1 openstack user create --domain default --password paswd123 placement openstack role add --project service --user placement admin openstack service create --name placement --description "Placement API" placement openstack endpoint create --region RegionOne placement publichttp://controller:8778 openstack endpoint create --region RegionOne placement internalhttp://controller:8778 openstack endpoint create --region RegionOne placement adminhttp://controller:8778 Edit the /etc/nova/nova.conf openstack-config --set /etc/nova/nova.conf DEFAULT enabled_apis osapi_compute,metadata openstack-config --set /etc/nova/nova.conf api_database connection mysql+pymysql://nova:passwd123@controller/nova_api openstack-config --set /etc/nova/nova.conf database connection mysql+pymysql://nova:passwd123@controller/nova openstack-config --set /etc/nova/nova.conf DEFAULT transport_url rabbit://openstack:passwd123@controller openstack-config --set /etc/nova/nova.conf api auth_strategy keystone openstack-config --set /etc/nova/nova.conf keystone_authtoken auth_urihttp://controller:5000 openstack-config --set /etc/nova/nova.conf keystone_authtoken auth_urlhttp://controller:35357 openstack-config --set /etc/nova/nova.conf keystone_authtoken memcached_servers controller:11211 openstack-config --set /etc/nova/nova.conf keystone_authtoken auth_type password openstack-config --set /etc/nova/nova.conf keystone_authtoken project_domain_name default openstack-config --set /etc/nova/nova.conf keystone_authtoken user_domain_name default openstack-config --set /etc/nova/nova.conf keystone_authtoken project_name service openstack-config --set /etc/nova/nova.conf keystone_authtoken username nova openstack-config --set /etc/nova/nova.conf keystone_authtoken password passwd123 openstack-config --set /etc/nova/nova.conf DEFAULT my_ip 192.168.137.145 openstack-config --set /etc/nova/nova.conf DEFAULT use_neutron True openstack-config --set /etc/nova/nova.conf DEFAULT firewall_driver nova.virt.firewall.NoopFirewallDriver openstack-config --set /etc/nova/nova.conf vnc enabled true openstack-config --set /etc/nova/nova.conf vnc vncserver_listen 192.168.137.145 openstack-config --set /etc/nova/nova.conf vnc vncserver_proxyclient_address 192.168.137.145 openstack-config --set /etc/nova/nova.conf glance api_servershttp://controller:9292 openstack-config --set /etc/nova/nova.conf oslo_concurrency lock_path /var/lib/nova/tmp openstack-config --set /etc/nova/nova.conf placement os_region_name RegionOne openstack-config --set /etc/nova/nova.conf placement project_domain_name Default openstack-config --set /etc/nova/nova.conf placement project_name service openstack-config --set /etc/nova/nova.conf placement auth_type password openstack-config --set /etc/nova/nova.conf placement user_domain_name Default openstack-config --set /etc/nova/nova.conf placement auth_urlhttp://controller:35357/v3 openstack-config --set /etc/nova/nova.conf placement username placement openstack-config --set /etc/nova/nova.conf placement password passwd123 vim /etc/httpd/conf.d/00-nova-placement-api.conf <Directory /usr/bin> <IfVersion >= 2.4> Require all granted </IfVersion> <IfVersion < 2.4> Order allow,deny Allow from all </IfVersion> </Directory> systemctl restart httpd systemctl status httpd su -s /bin/sh -c "nova-manage api_db sync" nova su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova su -s /bin/sh -c "nova-manage cell_v2 create_cell --name=cell1 --verbose" nova su -s /bin/sh -c "nova-manage db sync" nova nova-manage cell_v2 list_cells systemctl enable openstack-nova-api.service openstack-nova-consoleauth.service openstack-nova-scheduler.service \ openstack-nova-conductor.service openstack-nova-novncproxy.service systemctl start openstack-nova-api.service openstack-nova-consoleauth.service openstack-nova-scheduler.service \ openstack-nova-conductor.service openstack-nova-novncproxy.service systemctl status openstack-nova-api.service openstack-nova-consoleauth.service openstack-nova-scheduler.service \ openstack-nova-conductor.service openstack-nova-novncproxy.service openstack service list 本文转自 OpenStack2015 博客,原文链接: http://blog.51cto.com/andyliu/2069165 如需转载请自行联系原作者

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

物联网推动城市发展 诊治“城市病”很有一手

城市发展要走集约、智慧、绿色的新兴道路,这个思路必须通过“互联网+”与传统城市建设思维的结合才行得通。近些年来,随着互联网的发展,我们的生活与网络产生很大的管理,物物互联成为必然趋势,物联网的发展,为城市管理等都做出很大的贡献。一系列“城市病”如期而至:交通拥挤、环境污染、居民健康受到威胁,给市民工作生活带来诸多不便,而移动物联网的应用则成为治理手段。从广东移动了解到,目前各大运营商正积极落实与各级政府签订的战略合作协议要求,物联网、云计算、大数据等新技术,将在智慧生活、智慧医疗、智能环保等多个领域推陈出新,实现未来城市低碳、可持续发展的目标,从而大大造福于民。探索运用物联网等新技术,加强城市的智慧管理,助力解决“城市病”等问题。 据悉,今年全国两会期间,有人大代表就建议把握“万物互联”的时代机遇,加快建设“城市物联网”,将传感设备置入到城市的基础设施中,采集交通、停车场、水文、空气、土壤、城市内涝风险等数据,有利于实现城市的智能管理,提前进行灾害预防,也为城市大数据应用提供基础,提升民生服务和城市管理水平,有效治理“城市病”。比如广东移动的“基于物联云平台的行业大数据服务”项目成功入选广东省2015年大数据应用示范项目。 城市照明可调光可巡视 目前,上海市路灯中心所管辖的路灯有50万盏,加上各个小区,城市照明系统存在巨大节能减排潜力。由复旦大学、上海市建交委合作的项目已着手尝试。信息科学与工程学院沈海平老师介绍,上海城市隧道、越江隧道将采用基于LED的智能照明技术。新技术在色温、眩光指标、照明方式、控制系统、节能标准上均有所突破,其中最为新颖的,莫过于调光、巡检功能。专家解释,调光功能将能精确照明亮度,最大限度实现节能;至于巡检,过去路灯坏了,需要人力一个个检查;而今路灯性能将在操作平台上自行显示,免去了不必要的人力投入。 有研究表明,新型技术(物联网、云计算等)与传统产业相结合形成的智能产业,有望为全球降低15%至35%的碳排放,而其自身付出的碳排放仅有2%。郑立荣表示,智能产业形成智慧城市的构架,解决了因资源枯竭导致的“城市病”,更能使城市服务能力最大化,让市民切实体会到科技带来的生活改变。 智能药箱当随身“护士站” 老龄化社会扑面而来,目前,我国许多大医院人满为患,医生病人均怨声载道。如此不低碳、不环保的模式,也能通过物联网来扭转。由信息科学与工程学院院长郑立荣教授领衔的团队,开发了智能药箱(iMedbox)技术。专家解释,新技术整合传感器信息,通过清理、压缩、分析数据,远程指导老年人、慢性病人的服药情况。对病人而言,智能药箱犹如随身“护士站”,它非但会提醒何时服药,更可将服药后的身体各项指标监测状况传回医生,实现全程监测。 小小的智能药箱,不过是智慧医疗一部分。专家补充,今后在物联网协助下的“泛在医疗理念”,更可突破医患供需不平衡的尴尬。所谓“泛在医疗”,即在任何时间、任何地点对任何人进行医疗护理服务。这一理念对空巢独居老人、偏远地区病人等群体都具有开创性意义。 除此而外,节能减排不仅关系到当代人的利益,而且关系到下一代。节能减排有很多问题必须要用新的机制来解决,不能单纯靠传统的来解决。如果用物联网来建设管理城市节能减排,就可以精确到量,精确到点,就可避免“大而概之”的事情,按上一个芯片能够感知绿色设施的能源利用、水资源消耗情况,同步调节这些指标,就能让生活变得更好。 再比如,海绵城市用了一些智慧手段,控制水量、控制管网,使更多的水转化成地下水,把水面和地下水沟通起来。这样城市就像海绵那样多储存水。还有,如果我们每一个屋顶都装上太阳能,可以产生两个三峡电站的发电量,通过非常简单的智能电网,使更多的人可以享受住宅不仅用电还可以发电的效益。 在江门市,气象部门在46个气象站安装物联网卡,可以通过4G网络实施监控气象情况变化。在佛山市,有停车场试点推出了智能收费系统,可以通过移动网络将传感器所采集的停车信息传输到管理平台,大大提高停车计时计费的准确性。在汕头,公交企业在公交车上安装物联网卡,调度部门可以实时掌握车辆的位置信息,已覆盖11条公交线路的120辆公交车。 结语: 事实已经证明,推动集约、智能、绿色、低碳,都离不开物联网,其中的基础就是城市里广泛建设的数字资本市场。中央城市工作会议指出,数字成果的平台是我们现代化城市管理的一个基础性数据共享。而数字管理是实现城市管制效能提高的一个基础。在这个基础上,大数据帮我们可直接找到城市问题的症结。在这个基础上,把传统的网络化、精细化城市管理,升级为以智能传感为基础的物联网管理,这样物联网、云计算、大数据累加在一起,就可科学实现城市的节能减排,让生活环境更美好。 智慧城市模式有单向性的,也有综合性的。我们应该从一些单向性的城市病治理,转向综合性的治理模式,把几个专题性的问题叠加起来,其效果肯定是“1+1大于2”,这种效果只有依靠“互联网+”和物联网,依靠大数据,才能办到。 本文转自d1net(转载)

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

curd组件2:按钮实现

2 --> 参考:https://blog.csdn.net/dixian4894/article/details/102209151 上篇没有区分哪些字段可以编辑,而且如果像性别这种,在编辑的时候应该是个选择器,所以,在fields_config添加attr属性,并在attr赋值是否可编辑,编辑状态所用html标签,select的数据来源属性,一个例子如下: { "field_name": "性别", "field_in_db": "gender", "display": True, "show_data": "!GENDER", "attr": { "editable": True, "htmlLabel": "select", "selectDataFrom":"GENDER" } }, 前端得到这些数据,便可实现,编辑,全选,反选,取消按钮,代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> <style> .data-display{ margin: 200px; } </style> </head> <body> <div class="data-display"> <div class="btn-group" role="group" aria-label="..."> <button id="SelectAll" type="button" class="btn btn-default">全选</button> <button id="Reserve" type="button" class="btn btn-default">反选</button> <button id="Cancel" type="button" class="btn btn-default">取消</button> <button id="EditMode" type="button" class="btn btn-default">进入编辑模式</button> <button id="Del" class="btn btn-default">批量删除</button> <button id='save' type="button" class="btn btn-default">保存</button> </div> <table class="table table-bordered" id="Datatable"> <thead id="table_th"></thead> <tbody id="table_td"></tbody> </table> </div> </body> <script src="/static/js/jquery-3.5.1.min.js"> </script> <script> $(function () { initTable(); BindEditMode(); BindCheckboxEditMode(); BindSelectAll(); BindCancel(); BindReserve(); }) function initTable(){ $.ajax({ url:"getCurdData", type:'POST', dataType:'Json', success:function (arg) { initchoice(arg.choices_dict) initThead(arg.fields_config) initTbody(arg.data,arg.fields_config) } }) } function initThead(field) { tr_ele=$("<tr></tr>") $.each(field,function (k,v) { if(v["display"]){ th_ele=$("<th></th>") th_ele.text(v["field_name"]) tr_ele.append(th_ele) } $("#table_th").append(tr_ele) }) } function initTbody(data,field) { // 数据展示一般做法是,取出展示的字段,然后循环数据列表判断是否在里面,有则展示 // 但是这么做有个缺点是数据和字段的顺序要对应(因为是以数据为顺序,而字段顺序是可能变化的),而且不利于扩展 // 这里采用先循环数据列表,再循环field字段列表,根据字段的列表的顺序反选查找赋值 // 缺点是多次循环field比较耗性能,但是扩展能力变强了 $.each(data,function (data_k,data_v) { tr_ele=$("<tr></tr>") $.each(field,function (field_k,field_v) { if(field_v.display){ td_ele=$("<td></td>") //赋值attr $.each(field_v.attr,function (attr_k,attr_v) { td_ele.attr(attr_k,attr_v) }) if(field_v["show_data"][0]==='@'){ td_ele.html(data_v[field_v["field_in_db"]]) } else if(field_v["show_data"][0]==='!'){ var f_v=field_v["show_data"] var choice_list=f_v.substring(1,f_v.length) var choice_v=value_from_choice_list(data_v[field_v["field_in_db"]],window[choice_list]) td_ele.html(choice_v) } else{ td_ele.html(field_v["show_data"]) } tr_ele.append(td_ele) } }) $("#table_td").append(tr_ele) }) } function initchoice(choice_dict) { $.each(choice_dict,function (i,j) { // a='123'相当于window[a]='123' // 这里把choices列表转化为全局变量 window[i]=j; }) } function value_from_choice_list(index,choice) { //choice格式:{0: (2) ["male", "男"],} //v[0]="male",v[1]="男" ret=null $.each(choice,function (k,v) { if(v[0] === index){ ret=v[1] //js 的return只能跳出当前循环,类似shell的break // 所以额外赋值 return } }) return ret } function BindEditMode() { $('#EditMode').click(function () { //进入编辑模式,应该有个标记,才能区分进入与退出,这里用btn-info属性给button上色 //所以也用这个属性判断是否在编辑模式,有则是应退出,无则不是应进入 //也可以自己定义一个属性判断 if($(this).hasClass("btn-info")) { OutEditMode() }else{ IntoEditMode() } }) } function IntoEditMode() { $('#EditMode').addClass("btn-info") $('#EditMode').text("退出编辑模式") //查找checkbox是否选中,有则查找对应tr进入编辑 $("#table_td").find(":checked").each(function () { $cur_tr=$(this).parent().parent() TrIntoEdit($cur_tr) }) } function OutEditMode() { $('#EditMode').removeClass("btn-info") $('#EditMode').text("进入编辑模式") $("#table_td").find(":checked").each(function () { $cur_tr=$(this).parent().parent() TrOutEdit($cur_tr) }) } function TrIntoEdit(cur_tr) { //给当前行加个颜色表示正在编辑 cur_tr.addClass("info") // 查找tr下的td含有editable属性的元素进行渲染 cur_tr.find('[editable="true"]').each(function () { var htmllabel = $(this).attr('htmllabel') if(htmllabel === 'select'){ //如果类型是select,获取列表值,渲染成select选择 var selectData=$(this).attr('selectDataFrom') var select_ele=$("<select></select>") var cur_select_v=$(this).html() $.each(window[selectData],function (select_k,select_v) { var option_ele=$("<option></option>") option_ele.val(select_v[0]) option_ele.html(select_v[1]) if(cur_select_v === select_v[1]){ option_ele.attr("selected",true) } select_ele.append(option_ele) }) $(this).html(select_ele) }else { label_v=$(this).text() input_ele=$("<input>") input_ele.val(label_v) $(this).html(input_ele) } }) } function TrOutEdit(cur_tr) { //当前行去掉颜色表示退出 cur_tr.removeClass("info") // 查找tr下的td含有editable属性的元素进行渲染 cur_tr.find('[editable="true"]').each(function () { var htmllabel = $(this).attr('htmllabel') if(htmllabel === 'select'){ //如果类型是select,获取选中的值,赋值 var select_ele = $(this).children().first() var cur_select_v=select_ele[0].selectedOptions[0].innerHTML $(this).html(cur_select_v) }else { var input_ele = $(this).children().first() var cur_input_v=input_ele.val() $(this).html(cur_input_v) } }) } function BindCheckboxEditMode() { // IntoEditMode的函数有个bug,如果先进入编辑模式,再点击checkbox按钮 // 当前行不会进入编辑模式,这是因为点击button比勾选快 // 所以需要对CheckBox进行编辑模式下的事件委托 $("#table_td").on('click',':checkbox',function () { if ($("#EditMode").hasClass("btn-info")) { cur_status = $(this).prop('checked'); var $cur_tr = $(this).parent().parent(); if(cur_status){ TrIntoEdit($cur_tr) }else{ TrOutEdit($cur_tr) } } }) } function BindSelectAll() { // 全选分两种,编辑模式下,要TrIntoEdit,普通则勾选即可 $('#SelectAll').click(function () { // 全选只需处理未被选中的即可 $("#table_td").find(":checkbox").not(":checked").each(function () { if($("#EditMode").hasClass("btn-info")){ $(this).prop('checked',true); var $cur_tr = $(this).parent().parent(); TrIntoEdit($cur_tr) }else{ $(this).prop('checked',true); } }) }) } function BindReserve() { // 反选需要两种情况,编辑模式下,如果选中则TrOutEdit,未选中则TrIntoEdit // 普通则反选即可 $('#Reserve').click(function () { $("#table_td").find(":checkbox").each(function () { if($("#EditMode").hasClass("btn-info")){ var $cur_tr = $(this).parent().parent(); if($(this).prop('checked')){ $(this).prop('checked',false); TrOutEdit($cur_tr) }else{ $(this).prop('checked',true); TrIntoEdit($cur_tr) } }else{ if($(this).prop('checked')){ $(this).prop('checked',false); } else{ $(this).prop('checked',true); } } }) }) } function BindCancel() { // 取消跟全选相反,只需要处理选中的checkbox // 也是两种情况,若编辑模式,则TrOutEdit,否则去掉勾选即可 $('#Cancel').click(function () { $("#table_td").find(":checked").each(function () { if($("#EditMode").hasClass("btn-info")){ $(this).prop('checked',false); var $cur_tr = $(this).parent().parent(); TrOutEdit($cur_tr) }else{ $(this).prop('checked',false); } }) }) } </script> </html> 在实现删除和保存的时候,需要改动的东西比较多,因为保存意味着更新,所以要知道旧值和新值,如果新旧不一样才更新,这意味着多加字段标记旧属性,修改赋值代码等,具体如下:在实现删除和保存的时候,需要改动的东西比较多,因为保存意味着更新,所以要知道旧值和新值,如果新旧不一样才更新,这意味着多加字段标记旧属性,修改赋值代码等,具体如下: config属性赋值更新: 之前: "attr": { "editable":True, "htmlLabel":"" } 之后: "attr": { "editable":True, "origin_v":"@field_name", "htmlLabel":"" } initTbody函数修改: tr赋值属性记录当前行id; 之前: tr_ele=$("<tr></tr>") 之后: tr_ele=$("<tr></tr>") var old_data_id=data_v["id"] tr_ele.attr("old_data_id",old_data_id) td属性赋值更新: //赋值attr // 赋值field_in_db属性,用以在更新时找到对应数据库字段 td_ele.attr("field_in_db",field_v["field_in_db"]) $.each(field_v.attr,function (attr_k,attr_v) { // "origin_v":"@field_name",属性赋值需转为数据库的值 if(attr_k==="origin_v") { attr_v=data_v[field_v["field_in_db"]] td_ele.attr(attr_k,attr_v) }else{ td_ele.attr(attr_k,attr_v) } }) TrIntoEdit函数修改: 之前: cur_tr.addClass("info") 之后: cur_tr.addClass("info") // 标记当前行已编辑,表明可能数据变更,没有则没变更 cur_tr.attr("has-edit",true) TrOutEdit退出赋新值: 之前: var select_ele = $(this).children().first() var cur_select_v=select_ele[0].selectedOptions[0].innerHTML $(this).html(cur_select_v) 之后: var select_ele = $(this).children().first() var cur_select_v=select_ele[0].selectedOptions[0].innerHTML $(this).html(cur_select_v) // 赋新值属性 origin_v=$(this).prop("origin_v") change_v=DBvalue_from_choice_list(cur_select_v,window[selectdata]) if(origin_v != change_v){ $(this).attr("change_v",change_v) } 添加save 按钮: function BindSave() { // 收集改变的行,每行为一条记录,从tr标签读取旧数据id // 从td读取field_name作为key,读取chang_v为value,若无则不赋值 $('#Save').click(function () { // 如果编辑模式下,相当于点了取消 $('#Cancel').click() // 用update_list作为标记,告知后端传送的是更新的数据 var update_list=[] $('#table_td').find('tr[has-edit="true"]').each(function () { record={} id_v=$(this).attr("old_data_id") record["id"]=id_v $(this).children('[editable="true"]').each(function(){ if($(this).attr("change_v")) { field_k = $(this).attr("field_in_db") field_v = $(this).attr("change_v") record[field_k] = field_v } }) update_list.push(record); }) $.ajax({ url: "getCurdData", type: 'POST', data: {'update_list': JSON.stringify(update_list)}, dataType: 'json', success:function (arg) { if(arg.status=='ok'){ initTbody() } } }) }) } 添加删除按钮: function BindDel() { // 删除按钮要获取当前选中行的数据库id,还要弹窗提示确认 $('#Del').click(function () { del_list=[] $('#table_td').find(":checked").each(function () { record={} // save找的是tr,这里是td,所以需parent id_v=$(this).parent().parent().attr("old_data_id") console.log($(this)) record["id"]=id_v }) del_list.push(record) var r=confirm("确定删除?"); if(r){ $.ajax({ url: "getCurdData", type: 'POST', data: {'del_list': JSON.stringify(del_list)}, dataType: 'json', success:function (arg) { if(arg.status=='ok'){ initTbody() } } }) } }) } 按钮都实现后,就可以提取共同的部分封装成js(增加功能:requestURL,用pager分页等),最终代码如下: 后端view(无实现保存和删除) def getCurdData(request): print(request.POST) Gender_list=list(User.GENDER) work_list=[('1', '开'), ('2', '关')] fields_config=[ { "field_name": "选项", "field_in_db": "", "display": True, "show_data": "<input type='checkbox' />", "attr":{ } }, { "field_name":"用户名", "field_in_db":"username", "display":True, "show_data":"@field_name", "attr": { "editable":True, "origin_v":"@field_name", "htmlLabel":"", } }, { "field_name": "密码", "field_in_db": "password", "display": True, "show_data": "@field_name" }, { "field_name": "邮件", "field_in_db": "email", "display": True, "show_data": "@field_name", "attr": { "editable": True, "htmlLabel": "", "origin_v":"@field_name", } }, { "field_name": "性别", "field_in_db": "gender", "display": True, "show_data": "!GENDER", "attr": { "editable": True, "origin_v": "@field_name", "htmlLabel": "select", "selectDataFrom":"GENDER" } }, { "field_name": "电话", "field_in_db": "tel", "display": True, "show_data": "@field_name" }, { "field_name": "生日", "field_in_db": "birthday", "display": True, "show_data": "@field_name" }, { "field_name": "别名", "field_in_db": "name", "display": True, "show_data": "@field_name" }, ] data_list=list(User.objects.all().values()) result={ "fields_config":fields_config, "data":data_list, "choices_dict":{ "GENDER":Gender_list, "work":work_list, } } return HttpResponse(json.dumps(result,cls=CJsonEncoder)) 删除和保存的POST数据如下: <QueryDict: {'del_list': ['[{"id":"1"}]']}> [30/Jun/2021 16:35:21] "POST /getCurdData HTTP/1.1" 200 1574 <QueryDict: {'update_list': ['[{"id":"1"},{"id":"2"}]']}> CURDbyLinzb.js $(function () { function initTable(pager){ // pager:提取第pager页的数据 $.ajax({ url:requestURL, type:'GET', data:{'pager':pager}, dataType:'Json', success:function (arg) { initchoice(arg.choices_dict) initThead(arg.fields_config) initTbody(arg.data,arg.fields_config) } }) } function initThead(field) { tr_ele=$("<tr></tr>") $.each(field,function (k,v) { if(v["display"]){ th_ele=$("<th></th>") th_ele.text(v["field_name"]) tr_ele.append(th_ele) } $("#table_th").append(tr_ele) }) } function initTbody(data,field) { // save按钮重载时,会重新生成,所以需清空 $('#table_td').empty(); // 数据展示一般做法是,取出展示的字段,然后循环数据列表判断是否在里面,有则展示 // 但是这么做有个缺点是数据和字段的顺序要对应(因为是以数据为顺序,而字段顺序是可能变化的),而且不利于扩展 // 这里采用先循环数据列表,再循环field字段列表,根据字段的列表的顺序反选查找赋值 // 缺点是多次循环field比较耗性能,但是扩展能力变强了 $.each(data,function (data_k,data_v) { tr_ele=$("<tr></tr>") // tr赋值属性,标记当前行在数据库中的id,为更新做旧数据标记 var old_data_id=data_v["id"] tr_ele.attr("old_data_id",old_data_id) $.each(field,function (field_k,field_v) { if(field_v.display){ td_ele=$("<td></td>") // td 赋值attr // 赋值field_in_db属性,用以在更新时找到对应数据库字段 td_ele.attr("field_in_db",field_v["field_in_db"]) $.each(field_v.attr,function (attr_k,attr_v) { // "origin_v":"@field_name",属性赋值需转为数据库的值 if(attr_k==="origin_v") { attr_v=data_v[field_v["field_in_db"]] td_ele.attr(attr_k,attr_v) }else{ td_ele.attr(attr_k,attr_v) } }) if(field_v["show_data"][0]==='@'){ td_ele.html(data_v[field_v["field_in_db"]]) } else if(field_v["show_data"][0]==='!'){ var f_v=field_v["show_data"] var choice_list=f_v.substring(1,f_v.length) var choice_v=value_from_choice_list(data_v[field_v["field_in_db"]],window[choice_list]) td_ele.html(choice_v) } else{ td_ele.html(field_v["show_data"]) } tr_ele.append(td_ele) } }) $("#table_td").append(tr_ele) }) } function initchoice(choice_dict) { $.each(choice_dict,function (i,j) { // a='123'相当于window[a]='123' // 这里把choices列表转化为全局变量 window[i]=j; }) } function value_from_choice_list(index,choice) { //choice格式:{0: (2) ["male", "男"],} //v[0]="male",v[1]="男" ret=null $.each(choice,function (k,v) { if(v[0] === index){ ret=v[1] //js 的return只能跳出当前循环,类似shell的break // 所以额外赋值 return } }) return ret } function DBvalue_from_choice_list(index,choice) { //choice格式:{0: (2) ["male", "男"],} //v[0]="male",v[1]="男" ret=null $.each(choice,function (k,v) { if(v[1] === index){ ret=v[0] //js 的return只能跳出当前循环,类似shell的break // 所以额外赋值 return } }) return ret } function BindEditMode() { $('#EditMode').click(function () { //进入编辑模式,应该有个标记,才能区分进入与退出,这里用btn-info属性给button上色 //所以也用这个属性判断是否在编辑模式,有则是应退出,无则不是应进入 //也可以自己定义一个属性判断 if($(this).hasClass("btn-info")) { OutEditMode() }else{ IntoEditMode() } }) } function IntoEditMode() { $('#EditMode').addClass("btn-info") $('#EditMode').text("退出编辑模式") //查找checkbox是否选中,有则查找对应tr进入编辑 $("#table_td").find(":checked").each(function () { $cur_tr=$(this).parent().parent() TrIntoEdit($cur_tr) }) } function OutEditMode() { $('#EditMode').removeClass("btn-info") $('#EditMode').text("进入编辑模式") $("#table_td").find(":checked").each(function () { $cur_tr=$(this).parent().parent() TrOutEdit($cur_tr) }) } function TrIntoEdit(cur_tr) { //给当前行加个颜色表示正在编辑 cur_tr.addClass("info") // 标记当前行已编辑,表明可能数据变更,没有则没变更 cur_tr.attr("has-edit",true) // 查找tr下的td含有editable属性的元素进行渲染 cur_tr.find('[editable="true"]').each(function () { var htmllabel = $(this).attr('htmllabel') if(htmllabel === 'select'){ //如果类型是select,获取列表值,渲染成select选择 var selectData=$(this).attr('selectDataFrom') var select_ele=$("<select></select>") var cur_select_v=$(this).html() $.each(window[selectData],function (select_k,select_v) { var option_ele=$("<option></option>") option_ele.val(select_v[0]) option_ele.html(select_v[1]) if(cur_select_v === select_v[1]){ option_ele.attr("selected",true) } select_ele.append(option_ele) }) $(this).html(select_ele) }else { label_v=$(this).text() input_ele=$("<input>") input_ele.val(label_v) $(this).html(input_ele) } }) } function TrOutEdit(cur_tr) { //当前行去掉颜色表示退出 cur_tr.removeClass("info") // 查找tr下的td含有editable属性的元素进行渲染 cur_tr.find('[editable="true"]').each(function () { var htmllabel = $(this).attr('htmllabel') var selectdata = $(this).attr('selectDataFrom') if(htmllabel === 'select'){ //如果类型是select,获取选中的值,赋值 var select_ele = $(this).children().first() var cur_select_v=select_ele[0].selectedOptions[0].innerHTML $(this).html(cur_select_v) // 赋新值属性 origin_v=$(this).attr("origin_v") change_v=DBvalue_from_choice_list(cur_select_v,window[selectdata]) if(origin_v != change_v){ $(this).attr("change_v",change_v) } }else { var input_ele = $(this).children().first() var cur_input_v=input_ele.val() $(this).html(cur_input_v) origin_v=$(this).attr("origin_v") change_v=cur_input_v if(origin_v != change_v){ $(this).attr("change_v",change_v) } } }) } function BindCheckboxEditMode() { // IntoEditMode的函数有个bug,如果先进入编辑模式,再点击checkbox按钮 // 当前行不会进入编辑模式,这是因为点击button比勾选快 // 所以需要对CheckBox进行编辑模式下的事件委托 $("#table_td").on('click',':checkbox',function () { if ($("#EditMode").hasClass("btn-info")) { cur_status = $(this).prop('checked'); var $cur_tr = $(this).parent().parent(); if(cur_status){ TrIntoEdit($cur_tr) }else{ TrOutEdit($cur_tr) } } }) } function BindSelectAll() { // 全选分两种,编辑模式下,要TrIntoEdit,普通则勾选即可 $('#SelectAll').click(function () { // 全选只需处理未被选中的即可 $("#table_td").find(":checkbox").not(":checked").each(function () { if($("#EditMode").hasClass("btn-info")){ $(this).prop('checked',true); var $cur_tr = $(this).parent().parent(); TrIntoEdit($cur_tr) }else{ $(this).prop('checked',true); } }) }) } function BindReserve() { // 反选需要两种情况,编辑模式下,如果选中则TrOutEdit,未选中则TrIntoEdit // 普通则反选即可 $('#Reserve').click(function () { $("#table_td").find(":checkbox").each(function () { if($("#EditMode").hasClass("btn-info")){ var $cur_tr = $(this).parent().parent(); if($(this).prop('checked')){ $(this).prop('checked',false); TrOutEdit($cur_tr) }else{ $(this).prop('checked',true); TrIntoEdit($cur_tr) } }else{ if($(this).prop('checked')){ $(this).prop('checked',false); } else{ $(this).prop('checked',true); } } }) }) } function BindCancel() { // 取消跟全选相反,只需要处理选中的checkbox // 也是两种情况,若编辑模式,则TrOutEdit,否则去掉勾选即可 $('#Cancel').click(function () { $("#table_td").find(":checked").each(function () { if($("#EditMode").hasClass("btn-info")){ $(this).prop('checked',false); var $cur_tr = $(this).parent().parent(); TrOutEdit($cur_tr) }else{ $(this).prop('checked',false); } }) }) } function BindSave() { // 收集改变的行,每行为一条记录,从tr标签读取旧数据id // 从td读取field_name作为key,读取chang_v为value,若无则不赋值 $('#Save').click(function () { // 如果编辑模式下,相当于点了取消 $('#Cancel').click() // 用update_list作为标记,告知后端传送的是更新的数据 var update_list=[] $('#table_td').find('tr[has-edit="true"]').each(function () { record={} id_v=$(this).attr("old_data_id") record["id"]=id_v $(this).children('[editable="true"]').each(function(){ if($(this).attr("change_v")) { field_k = $(this).attr("field_in_db") field_v = $(this).attr("change_v") record[field_k] = field_v } }) update_list.push(record); }) $.ajax({ url: requestURL, type: 'POST', data: {'update_list': JSON.stringify(update_list)}, dataType: 'json', success:function (arg) { if(arg.status=='ok'){ initTbody(1) } } }) }) } function BindDel() { // 删除按钮要获取当前选中行的数据库id,还要弹窗提示确认 $('#Del').click(function () { del_list=[] $('#table_td').find(":checked").each(function () { record={} // save找的是tr,这里是td,所以需parent id_v=$(this).parent().parent().attr("old_data_id") if(id_v!=undefined) { record["id"] = id_v del_list.push(record) } }) var r=confirm("确定删除?"); if(r){ $.ajax({ url: requestURL, type: 'POST', data: {'del_list': JSON.stringify(del_list)}, dataType: 'json', success:function (arg) { if(arg.status=='ok'){ initTbody(1) } } }) } }) } jQuery.extend({ 'CreateCURD':function (url) { requestURL = url; initTable(1); BindEditMode(); BindCheckboxEditMode(); BindSelectAll(); BindCancel(); BindReserve(); BindSave(); BindDel(); }, 'TurnToPager':function (num) { inittable(num); } }) }) 前端代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> <style> .data-display{ margin: 200px; } </style> </head> <body> <div class="data-display"> <div class="btn-group" role="group" aria-label="..."> <button id="SelectAll" type="button" class="btn btn-default">全选</button> <button id="Reserve" type="button" class="btn btn-default">反选</button> <button id="Cancel" type="button" class="btn btn-default">取消</button> <button id="EditMode" type="button" class="btn btn-default">进入编辑模式</button> <button id="Del" class="btn btn-default">批量删除</button> <button id='Save' type="button" class="btn btn-default">保存</button> </div> <table class="table table-bordered" id="Datatable"> <thead id="table_th"></thead> <tbody id="table_td"></tbody> </table> </div> </body> <script src="/static/js/jquery-3.5.1.min.js"> </script> <script src="/static/js/CURDbyLinzb.js"> </script> <script> $(function () { $.CreateCURD( 'getCurdData') }) </script> </html>

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

Netty组件之Channel注册

前言 本文将分析EventLoopGroup初始化、EventLoop的选择策略以及Channel是如何通过EventLoop注册到Selector上的。 一、EventLoopGroup类图概览 在客户端示例代码中的中实例化了NioEventLoopGroup,接下来分析下该实例化过程。 EventLoopGroup workerGroup = new NioEventLoopGroup();Bootstrap b = new Bootstrap();b.group(workerGroup); 从以下类图结构io.netty.util.concurrent.AbstractEventExecutorGroup分支主要负责多线程任务的处理;io.netty.channel.EventLoopGroup分支主要负责Channel相关的注册。MultithreadEventExecutorGroup与MultithreadEventLoopGroup分别继承和实现了上面AbstractEventExecutorGroup和EventLoopGroup,将其负责的功能进行融合。 二、构造函数解读 构造函数nThreads:eventLoopThreads线程数量,默认值0时取CPU核数的2倍,可以通过参数io.netty.eventLoopThreads指定Executor:默认ThreadPerTaskExecutorSelectorProvider默认SelectorProvider.provider(),用于开启Selector和ChannelSelectStrategyFactory:SelectStrategy工厂类,默认DefaultSelectStrategyFactoryEventExecutorChooserFactory:EventExecutor选择器,默认为DefaultEventExecutorChooserFactory 三、初始化EventExecutor数组 代码解读EventExecutor[] children:数组大小为nThreads,默认为CPU核数乘以2。EventExecutor继承了EventExecutorGroup本质上为线程框架类Executorchildren[i]:数据元素为EventLoop,本示例中为NioEventLoop。 NioEventLoop类图 NioEventLoop继承了SingleThreadEventLoop,SingleThreadEventLoop同时继承和实现了EventExecutor和EventLoop。即:NioEventLoop拥有了线程类框架处理多线程任务的能力和处理Channel能力。 备注:本文中EventExecutor数组children的元素为NioEventLoop,NioEventLoop同时拥有线程框架能力和Channel注册等处理能力。 四、EventExecutor选择器 第三部分对EventExecutor[] children进行初始化分析,然在使用时如何选择其中一个元素呢?在初始化过程中有以下一行代码,用于初始化EventExecutorChooser。 chooser = chooserFactory.newChooser(children); EventExecutorChooser类图结构 选择策略 @1 如果数组长度是2的幂次方,选择PowerOfTwoEventExecutorChooser,在选取EventExecutor时使用executors[idx.getAndIncrement() & executors.length - 1] @2 如果数组长度不是2的幂次方,选择GenericEventExecutorChooser,executors[Math.abs(idx.getAndIncrement() % executors.length)]。 五、Channel注册 Channel注册入口 选择EventLoop本文为NioEventLoop 绑定Channel到EventExecutor通过DefaultChannelPromise绑定Channel到EventExecutor(NioEventLoop) 将Channel注册到Selector 作者丨梁勇来源丨瓜农老梁(ID:gh_01130ae30a83)欢迎关注公众号“瓜农老梁” 「瓜农老梁学习同行」 本文分享自微信公众号 - 瓜农老梁(gh_01130ae30a83)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

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

Sublime Text

Sublime Text

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

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册