Maven:下载慢的解决办法
C:\Windows\System32\drivers\etc\hosts
151.101.24.215 repo.maven.apache.org
location ~ \.(jpg|png|jpeg|gif)$ { expires 30d; root /data/www/wizzer.cn/; } location ~ \.(js|css)$ { expires 2h; root /data/www/wizzer.cn/; }
Dockerfile:
FROM node:6.2 # Author MAINTAINER wizzer "wizzer@qq.com" ENV PORT 1337 RUN apt-get update && apt-get install -y \ imagemagick \ --no-install-recommends && rm -rf /var/lib/apt/lists/* RUN mkdir -p /node/nodeshop WORKDIR /node/nodeshop RUN npm config set registry https://registry.npm.taobao.org RUN npm i node-gyp -g RUN npm i pm2 -g ADD api /node/nodeshop/api ADD assets /node/nodeshop/assets ADD config /node/nodeshop/config ADD tasks /node/nodeshop/tasks ADD views /node/nodeshop/views ADD app.js /node/nodeshop ADD Gruntfile.js /node/nodeshop ADD package.json /node/nodeshop RUN npm i EXPOSE ${PORT} ENV LANG C.UTF-8 ENV TZ "Asia/Shanghai" VOLUME ["/node/nodeshop/cert", "/node/nodeshop/upload", "/node/nodeshop/backup"] CMD [ "pm2", "start", "--no-daemon", "app.js" ]
docker-compose.yml:
redis: image: redis db: image: mariadb:5.5 environment: "MYSQL_ROOT_PASSWORD": "xxxxxx" "MYSQL_DATABASE": "db123" command: "mysqld --character-set-server=utf8" ports: - "127.0.0.1:3306:3306" volumes: - "/node/nodeshop/db:/var/lib/mysql" web: image: wizzer/nodeshop links: - redis - db environment: "MYSQL_HOST": "db" "MYSQL_USER": "root" "MYSQL_PASSWORD": "xxxxxx" "MYSQL_DATABASE": "db123" "MYSQL_LIMIT": 150 "REDIS_HOST": "redis" "REDIS_PASS": "" "LOG_LEVEL": "verbose" "PORT": 1337 "NODE_ENV": "development" command: "pm2 start /node/nodeshop/app.js --no-daemon" ports: - "1337:1337" volumes: - "/node/nodeshop/cert:/node/nodeshop/cert" - "/node/nodeshop/upload:/node/nodeshop/upload" - "/node/nodeshop/backup:/node/nodeshop/backup"
说明:
1、把数据库端口3306映射到127.0.0.1:3306 是为了还原数据库,web映射端口不绑定IP这样外网可以访问,通过nginx代理出去.
2、volumes将数据文件、数据库文件使用容器外文件夹,这样重启后不丢失数据.
…
1、打包最新image
docker build -t wizzer/nodeshop .
. 为当前文件夹,通过Dockerfile打包
wizzer/nodeshop:v1.0 用户名/项目:版本号
docker images 列出所有镜像
docker rmi ID 删除某个镜像
docker ps -a 列出所有容器
docker rm ID 删除某个容器
2、Centos安装Docker-engine 1.7.1版本(windows安装docker-toolbox即可)
vi /etc/yum.repos.d/docker.repo
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/6/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
yum search docker
yum install docker-engine.x86_64
service docker start 启动docker服务
chkconfig docker on 设置为开启启动
3、Centos安装docker-compose 1.1.0版本(windows安装docker-toolbox即可)
curl -L https://github.com/docker/compose/releases/download/1.7.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ps:第一行命令复制会少符号,到 https://github.com/docker/compose/releases/ 复制命令。
4、迁移镜像
docker ps -a 列出容器快照
docker export ID > nodeshop.tar 将容器快照导出
cat /node/nodeshop.tar | docker import – wizzer/nodeshop 加载容器快照
5、创建运行目录
分别创建4个文件夹【必须】
/node/nodeshop/cert 将证书文件拷贝进去
/node/nodeshop/upload 附件上传文件夹
/node/nodeshop/backup 数据库备份文件夹
/node/nodeshop/db 数据库文件夹
将Dockfile 、 docker-compose.yml 拷贝到 /node/nodeshop 目录
6、启动项目
cd /node/nodeshop
docker-compose up -ddocker-compose ps 列出正在运行的服务
docker-compose stop 停止服务
docker ps -a 列出所有容器状态
docker rm ID 删除容器
若要修改环境变量,可以修改 /node/nodeshop/docker-compose.yml 文件内容
7、安装mariadb客户端(用于连接数据库)
cd /etc/yum.repos.d/
vi MariaDB.repo[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/5.5/centos6-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1yum install MariaDB-client
MariaDB-server 不需要安装
8、还原数据
mysql -h 127.0.0.1 -u root -p
密码
show databases;
use nodeshop;
source /node/nodeshop/db.sql;
show tables;
exit;
9、重启docker容器
docker-compose stop
docker-compose start
10、进入容器执行命令,比如测试网络情况
docker ps -a
docler exec -it ID /bin/bash
ping 192.168.1.11
exit
如果网络不通,可能需要关闭防火墙,然后重启docker服务:
service docker restart
11、容器开机自启动
vi /etc/rc.d/rc.local
/usr/local/bin/docker-compose -f /node/sunshop/docker-compose.yml up -d
注意:如果是centos7 则需要执行 chmod +x /etc/rc.d/rc.local 添加执行权限.
本教程适用于Centos6.x版本,7或有不同。
本文基于Sails.js MVC框架
一、安装
npm i apidoc -save npm i grunt-apidoc -save
二、配置
package.json
增加配置项
"apidoc": { "title": "Sunshop" },
tasks/config/apidoc.js
/** * Created by wizzer on 2016/5/24. */ module.exports = function (grunt) { grunt.config.set('apidoc', { myapp: { src: "api/controllers/api", dest: "apidoc/", options: { includeFilters: [ ".*\\.json$" ] } } }); grunt.loadNpmTasks('grunt-apidoc'); };
tasks/register/compileAssets.js
module.exports = function (grunt) { grunt.registerTask('compileAssets', [ 'clean:dev', 'jst:dev', 'less:dev', 'copy:dev', 'coffee:dev', 'apidoc:myapp' // <-- apidoc ]); };
api/controllers/api/oauth.json 一个API文档示例,详细参数见apidoc官网。
/** * @api {POST} /api/oauth/token Token * @apiName Token * @apiGroup Oauth * @apiVersion 1.0.0 * @apiDescription 获取Token * @apiPermission anyone * * @apiParam {string} client_id client_id * @apiParam {string} client_secret client_secret * * @apiParamExample {json} 示例 * POST /api/oauth/token * { * "client_id": "client_id", * "client_secret": "client_secret" * } * * @apiSuccess (成功) {number} code 0 * @apiSuccess (成功) {string} msg success * @apiSuccess (成功) {Object} data Token对象 * @apiSuccess (成功) {string} data.token Token * @apiSuccess (成功) {number} data.expires 失效时间(24小时)请保存若失效重新获取 * @apiSuccess (成功) {number} data.appid AppId * @apiSuccessExample {json} 示例 * HTTP/1.1 200 OK * { * "code": 0, * "msg": "success", * "data": { * "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOjIsImV4cCI6MTQ2NDE1NjA2OTg3Nn0.4i_o7gCjCKvOImSi4peCMgCUrzpdgbtmvMECKf5wkqE", * "expires": 1464156069876, * "appid": 2 * } * } * * @apiError (失败) {number} code 1:client_id不存在 2:client_id禁用 3:client_secret错误 4:参数错误 * @apiError (失败) {string} msg 错误文字描述 * @apiErrorExample {json} 示例 * HTTP/1.1 200 OK * { * "code": 1 * "msg": "client_id has error" * } */
框架配置静态目录,让其可访问:
config/http.js
customMiddleware: function (app) { app.use('/apidoc', require('express')['static'](require('path').normalize(__dirname + '/../apidoc'))); },
http://connect.qq.com/manage/login
网站首页头文件添加验证字符串,如:
<meta property=”qc:admins” content=”765754250763563070636” />
填写回调地址:
必须是公网地址,可以填写多个,注意 /xxx 和 http://wizzer.cn/xxx 是两个地址,两个都需要配置。
登录页面:
<span id=”qqLoginBtn”></span>
<script type="text/javascript" src="http://qzonestyle.gtimg.cn/qzone/openapi/qc_loader.js" data-appid="<%=qq_appid||''%>" data-redirecturi="<%=req.baseUrl%>/public/shop/pc/account/oauthQq" charset="utf-8" ></script> <script type="text/javascript"> QC.Login({ btnId:"qqLoginBtn", //插入按钮的节点id scope: "get_user_info" },function(oInfo, oOpts){ //登陆成功执行 var nickname=QC.String.escHTML(oInfo.nickname);//获取QQ会员名 var info={ nickname:nickname, gender:oInfo.gender, headimgurl:oInfo.figureurl_qq_1 //头像40X40 };//封装对象 if(QC.Login.check()){ QC.Login.getMe(function(openId, accessToken){ info.openid=openId;//传递openid及昵称头像等,业务逻辑自动注册会员或登录 $.post( "/public/shop/pc/account/oauthQqStatus", info, function(result){ console.log(result); if(result.code==0){ window.location.href=$("#r").val()||'/member';//登录成功跳转 }else{ alert('登录失败'); } },'json' ); }); } });</script>
回调页面:
<script type="text/javascript" src="http://qzonestyle.gtimg.cn/qzone/openapi/qc_loader.js" charset="utf-8" data-callback="true"></script>
退出登录:
<%if(sails.config.system.ShopConfig.oauth_open&&sails.config.system.ShopConfig.pay_wxpay&&sails.config.system.ShopConfig.oauth_qq){ var qq_appid=''; if(sails.config.system.ShopConfig.oauth_qq_info){ qq_appid=sails.config.system.ShopConfig.oauth_qq_info.qq_appid; } %> <script type="text/javascript" src="http://qzonestyle.gtimg.cn/qzone/openapi/qc_loader.js" data-appid="<%=qq_appid||''%>" data-redirecturi="http://<%=sails.config.system.AppDomain%>/public/shop/pc/account/oauthQq" charset="utf-8" ></script> <script type="text/javascript"> QC.Login.signOut(); if(QC.Login.check()==false){ window.location.href='/public/shop/pc/account/logout';//先QQ登出,再清除session }else{ window.location.reload(); } </script> <%}else{%> <script type="text/javascript"> window.location.href='/public/shop/pc/account/logout'; </script> <%}%>
审核条件:登录页面有QQ登录图标、使用申请的QQ或测试QQ号,测试可以正常登录后提交申请,否则肯定是不通过的。
1、JDK安装
/data1/soft/java/
>>chmod 777 jdk-6u45-linux-x64-rpm.bin
>>jdk-6u45-linux-x64-rpm.bin
>>gedit /etc/profile
JAVA_HOME=/data1/soft/java/jdk1.6.0_45
CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME
export CLASSPATH
export PATH
>>source /etc/profile
2、TOMCAT安装
将原windows系统中的tomcat主要文件拷贝到linux(conf、lib、bin),并新建空文件夹(logs、temp、work)
/data1/soft/tomcat1 多网站的那个tomcat
/data1/soft/tomcat2 少网站的那个tomcat
分别修改两个tomcat下的server.xml文件,将项目路径分别替换为 /data1/www/websties1 和 /data1/www/websties2
>>/data1/soft/tomcat/bin/startup.sh //启动tomcat
>>/data1/soft/tomcat/bin/shutdown.sh //停止tomcat
开机启动:
http://jingyan.baidu.com/article/6525d4b1382f0aac7d2e9421.html
【tomcat1、tomcat2分别设置为启动项】
除了百度经验之外,要在catalina.sh 里加上下面三行,否则在自启动的时候找不到jdk
export JAVA_HOME=/data1/soft/java/jdk1.6.0_45
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$JAVA_HOME/bin:$PATH
3、Nginx安装
>>rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
>>yum -y install nginx
通过命令安装后
配置文件:/etc/nginx/nginx.conf
域名配置:/etc/nginx/conf.d/ 一个域名一个配置文件,不要的域名可以备份后删除
server {
listen 80;
server_name test.wizzer.cn;
location / {
proxy_pass http://test.wizzer.cn:8101;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
日志文件路径:/var/logs/nginx
服务启动或通知
>>service nginx stop
>>service nginx start
设置为随机启动
>>chkconfig nginx on
4、Nginx代理权限设置
若通过域名+端口号可访问,但80端口显示 502 Bad Gateway ,日志/var/logs/nginx/error.log报
2015/12/19 18:02:03 [crit] 9978#0: *8 connect() to 61.132.139.155:8101 failed (13: Permission denied) while connecting to upstream, client: 124.73.13.21, server: test.wizzer.cn, request: “GET / HTTP/1.1”, upstream: “http://61.132.139.155:8101/”, host: “test.wizzer.cn”
则需要设置selinux权限(宽容模式):
>>setenforce 0
>>setsebool -P httpd_can_network_connect 1
5、防火墙配置
>>vi /etc/sysconfig/iptables
#########################################################
# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state –state NEW -m tcp -p tcp –dport 21 -j ACCEPT
-A INPUT -m state –state NEW -m tcp -p tcp –dport 22 -j ACCEPT
-A INPUT -m state –state NEW -m tcp -p tcp –dport 80 -j ACCEPT
-A INPUT -j REJECT –reject-with icmp-host-prohibited
-A FORWARD -j REJECT –reject-with icmp-host-prohibited
COMMIT
#########################################################
>>/etc/init.d/iptables restart #重启防火墙使配置生效,或者命令 service iptables restart
php.ini 修改:
cgi.fix_pathinfo=1
nginx/vhost/ 域名配置:
server {
listen 80;
server_name www.wizzer.cn wizzer.cn;
root “/data/www/www.wizzer.cn”;
location / {
index index.html index.htm index.php;
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php?$1 last;
break;
}
}
location ~ \.php(.*)$ {
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
include fastcgi_params;
}
}
适应场景:Sails框架、微信公众号数据配置在数据库中,支持多个公众号。
1、Model定义(Waterline)
文件路径:/api/models/wx/Wx_config.js
/** * Created by root on 10/25/15. */ var moment = require('moment'); module.exports = { schema: true, autoCreatedAt: false, autoUpdatedAt: false, attributes: { id: { type: 'integer', autoIncrement: true, primaryKey: true }, appname: { type: 'string', required: true }, ghid: {//原始ID type: 'string', unique: true, required: true }, appid: { type: 'string', unique: true, required: true }, appsecret: { type: 'string', unique: true, required: true }, encodingAESKey:{ type: 'string', unique: true, required: true }, token: { type: 'string', unique: true, required: true }, access_token: { type: 'string' }, expire_time: { type:'integer', defaultsTo:function(){ return 0; } }, createdBy:{ type: 'integer' }, createdAt:{ type:'integer', defaultsTo:function(){ return moment().format('X'); } } } };
2、Sails默认不支持微信xml post,改造之
文件路径:/config/http.js
rawParser: function(req, res, next) { switch(req.headers['content-type']) { case 'text/xml': require('body-parser').raw({ type: 'text/xml' })(req, res, next); break; default : next(); } }, order: [ 'startRequestTimer', 'cookieParser', 'session', 'myRequestLogger', 'rawParser', 'bodyParser', 'handleBodyParserError', 'compress', 'methodOverride', 'poweredBy', '$custom', 'router', 'www', 'favicon', '404', '500' ],
3、控制类
文件路径:/api/controllers/open/WeixinController.js
微信公众号后台配置路径:http://127.0.0.1/open/weixin/api?wxid=1
/** * Created by root on 10/25/15. */ module.exports = { api: function (req, res) { var id = req.query.wxid; Wx_config.findOne(id).exec(function (err, conf) { if (err)return res.send(200, 'fail'); if (req.body) { WeixinService.loop(req, function (data) { if (data.type = 'text') {//用户发送纯文本 var msg = {toUserName: data.openid, fromUserName: conf.ghid, content: 'Node.js Test...'}; WeixinService.sendTextMsg(res, msg);//向用户回复消息 } }); } //签名 if (WeixinService.checkSignature(req, conf.token)) { res.send(200, req.query.echostr); } else { res.send(200, 'fail'); } }); } };
4、微信服务工具类
文件路径:/api/services/WeixinService.js
/** * Created by root on 10/26/15. */ var sha1 = require('sha1'), xml2js = require('xml2js'); module.exports = { /** * 签名验证 * @param req * @param token * @returns {boolean} */ checkSignature: function (req, token) { var signature = req.query.signature, timestamp = req.query.timestamp, nonce = req.query.nonce, echostr = req.query.echostr; // 按照字典排序 var array = [token, timestamp, nonce]; array.sort(); // 连接 var str = sha1(array.join("")); // 对比签名 return str == signature; }, /** * 监听用户消息 * @param req * @param callback */ loop: function (req, callback) { var body = req.body.toString('utf-8'); var data = {}; xml2js.parseString(body, function (err, json) { if (err) { } else { console.log('json::' + JSON.stringify(json)); data.type = json.xml.MsgType; data.openid = json.xml.FromUserName; if (data.type == 'text') { data.txt = json.xml.Content; } else if (data.type == 'image') { data.pic = json.xml.PicUrl; } return callback(data); } }); }, /** * 发送文本消息 * @param res * @param msg */ sendTextMsg: function (res, msg) { var time = Math.round(new Date().getTime() / 1000); var funcFlag = msg.funcFlag ? msg.funcFlag : 0; var output = "" + "<xml>" + "<ToUserName><![CDATA[" + msg.toUserName + "]]></ToUserName>" + "<FromUserName><![CDATA[" + msg.fromUserName + "]]></FromUserName>" + "<CreateTime>" + time + "</CreateTime>" + "<MsgType><![CDATA[text]]></MsgType>" + "<Content><![CDATA[" + msg.content + "]]></Content>" + "<FuncFlag>" + funcFlag + "</FuncFlag>" + "</xml>"; res.type('xml'); res.send(output); }, /** * 发送图文消息 * @param res * @param msg */ sendNewsMsg: function (res, msg) { var time = Math.round(new Date().getTime() / 1000); var articlesStr = ""; for (var i = 0; i < msg.articles.length; i++) { articlesStr += "<item>" + "<Title><![CDATA[" + msg.articles[i].title + "]]></Title>" + "<Description><![CDATA[" + msg.articles[i].description + "]]></Description>" + "<PicUrl><![CDATA[" + msg.articles[i].picUrl + "]]></PicUrl>" + "<Url><![CDATA[" + msg.articles[i].url + "]]></Url>" + "</item>"; } var funcFlag = msg.funcFlag ? msg.funcFlag : 0; var output = "" + "<xml>" + "<ToUserName><![CDATA[" + msg.toUserName + "]]></ToUserName>" + "<FromUserName><![CDATA[" + msg.fromUserName + "]]></FromUserName>" + "<CreateTime>" + time + "</CreateTime>" + "<MsgType><![CDATA[news]]></MsgType>" + "<ArticleCount>" + msg.articles.length + "</ArticleCount>" + "<Articles>" + articlesStr + "</Articles>" + "<FuncFlag>" + funcFlag + "</FuncFlag>" + "</xml>"; res.type('xml'); res.send(output); } };
Nodejs版本:0.12.7
Sails版本:0.11.0
require相关组件,记得安装。
参考项目1:https://github.com/node-webot/wechat-api
参考项目2:https://github.com/JeremyWei/weixin_api
Html:
姓名状态是否在线操作
用户名 datatables初始化:
var datatable; function initDatatable() { datatable = $('.datatable').DataTable({ "processing": false, "serverSide": true, "select": true, "ordering": true, "language": { "url": "/plugins/datatables/cn.json" }, "preDrawCallback": function () { sublime.closeLoadingbar($(".main-content")); sublime.showLoadingbar($(".main-content")); }, "drawCallback": function () { sublime.closeLoadingbar($(".main-content")); }, "ajax": { "url": "/private/sys/user/data", "type": "post", "data": function (d) { d.unitid = $('#unitid').val(); d.loginname=$('#loginname').val(); d.nickname=$('#nickname').val(); } }, "order":[[0,"desc"]], "columns": [ {"data": "loginname", "bSortable": true}, {"data": "nickname", "bSortable": true}, {"data": "disabled", "bSortable": true}, {"data": "online", "bSortable": true} ], "columnDefs": [ { "render": function (data, type, row) { return 'html.....'; }, "targets": 4 }, { "render": function (data, type, row) { if (data) { return ''; } else { return ''; } }, "targets": 3 }, { "render": function (data, type, row) { if (!data) { return ''; } else { return ''; } }, "targets": 2 } ] }); datatable.on('click', 'tr', function () { $(this).toggleClass('selected'); }); $("#searchBtn").on('click',function(){ datatable.ajax.reload(null, false); }); }重新加载数据:
datatable.ajax.reload(null, false);//当前页 datatable.ajax.reload();//回到第一页排序:通过后台参数 order数组得到dir:asc/desc,通过order的column下标,获取columns数组中的data字段名,两者结合写排序条件
后台把所有参数打印出来,你就知道代码应该怎么写了……over响应的数据格式:
{ "draw": draw, "recordsTotal": pageSize, "recordsFiltered": count, "data": list }Nodejs 后端完整代码:
data: function (req, res) { var pageSize = parseInt(req.body.length); var start = parseInt(req.body.start); var page = start / pageSize + 1; var draw = parseInt(req.body.draw); var unitid = req.body.unitid || 1; var loginname = req.body.loginname || ''; var nickname = req.body.nickname || ''; var order = req.body.order || []; var columns = req.body.columns || []; var sort = {}; var where = {unitid: unitid}; if (loginname) { where.loginname = {'like':'%'+loginname+'%'}; } if (nickname) { where.nickname = {'like':'%'+nickname+'%'}; } if (order.length > 0) { sort[columns[order[0].column].data] = order[0].dir; } Sys_user.count(where).exec(function (err, count) { if (!err && count > 0) { Sys_user.find(where) .sort(sort) .paginate({page: page, limit: pageSize}) .exec(function (err, list) { return res.json({ "draw": draw, "recordsTotal": pageSize, "recordsFiltered": count, "data": list }); }); } else { return res.json({ "draw": draw, "recordsTotal": pageSize, "recordsFiltered": 0, "data": [] }); } }); },
1) 打开端口
vi /etc/sysconfig/iptables
-A INPUT -m state –state NEW -m tcp -p tcp –dport 80 -j ACCEPT
注意:新开放的端口一定要在端口22后面
重启防火墙使配置生效
/etc/init.d/iptables restart
查看开放端口
/etc/init.d/iptables status
1) 永久性生效,重启后不会复原
开启: chkconfig iptables on
关闭: chkconfig iptables off
2) 即时生效,重启后复原
开启: service iptables start
关闭: service iptables stop
Sys_user.js
module.exports = { schema: true, autoCreatedAt: false, autoUpdatedAt: false, attributes: { id: { type: 'integer', autoIncrement: true, primaryKey: true }, roles: { collection: 'Sys_role', via: 'users' } } };
Sys_role.js
users: { collection: 'Sys_user', via: 'roles' //dominant: true },
使用populate查询
Sys_role.findOne(1).populate('users').populate('menus').exec(function(err, role) { console.log(':::'+JSON.stringify(role.users)); console.log(':::'+JSON.stringify(role.menus)); });
npm install bcrypt –save
var salt = bcrypt.genSaltSync(10);
var hash = bcrypt.hashSync(‘pass’, salt);
console.log(‘加密::’+hash);
console.log(‘解密::’+bcrypt.compareSync(‘pass’,hash));
友情提示:do not 在windows下开发node.js应用,否则你会浪费很多时间并且会pia撞墙的……
1.CentOS6.5 安装 nodejs 并配置到环境
———————————–
>>gedit /etc/profile
export NODE_HOME=/soft/node-v0.12.7-linux-x64
export PATH=$NODE_HOME/bin:$PATH
>>source /etc/profile
>>node -v
2.npm 设置为国内源
———————————–
>>npm config set registry https://registry.npm.taobao.org
3.安装必备模块 node-gyp (CentOS6.5 自带Python2.6.6)
———————————–
>>npm install node-gyp -g
4.安装WebStorm 并安装JDK7
———————————–
>>rpm -ivh jdk-7u79-linux-x64.rpm
>>gedit /etc/profile
JAVA_HOME=/usr/java/jdk1.7.0_79
CLASSPATH=.:$JAVA_HOME/lib.tools.jar
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME CLASSPATH PATH
>>source /etc/profile
5.安装Git 并生成ssh密钥,github帐号设置中添加密钥
———————————–
>>yum install git
>>cd ~/.ssh
>>ssh-keygen -t rsa -C “wizzer@qq.com”
>>cat ~/.ssh/id_rsa.pub
>>git clone git@github.com:Wizzercn/nodeshop.git
>>git pull
>>git commit -am ‘note’
>>git push
6.验证码组件ccap,需安装python2.7
————————————
http://blog.csdn.net/tiantiandjava/article/details/17242345
>>npm install ccap –save
# yum update
# yum search mysql
# yum list mysql
# yum list mysql-server
# yum install mysql
# yum install mysql-server
运行命令chkconfig –levels 235 mysqld on使MySQL服务可以自动启动,并使用命令/etc/init.d/mysqld start立刻启动MySQL服务
设置MySQL的root密码,运行命令/usr/bin/mysqladmin -u root password ‘new-password’,其中’new-password’是新设的密码,如123456
@At public String test5(@Param("taskId") String taskId) { Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); if (task == null) return "null"; ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(task.getProcessDefinitionId()); List<ActivityImpl> activitiList = def.getActivities(); System.out.println("getTaskDefinitionKey:::" + task.getTaskDefinitionKey()); NutMap map = new NutMap(); int type = 0; getTaskActivitys(task.getTaskDefinitionKey(), activitiList, type, map); return Json.toJson(map); } public static List<PvmActivity> getTaskActivitys(String activityId, List<ActivityImpl> activityList, int type, NutMap map) { List<PvmActivity> activitiyIds = new ArrayList<>(); for (ActivityImpl activityImpl : activityList) { String id = activityImpl.getId(); if (activityId.equals(id)) { List<PvmTransition> outgoingTransitions = activityImpl.getOutgoingTransitions();//获取某节点所有线路 List<NutMap> list = new ArrayList<>(); for (PvmTransition tr : outgoingTransitions) { NutMap map1 = new NutMap(); PvmActivity ac = tr.getDestination();//获取线路的终点节点 if (ac.getProperty("type").equals("userTask")) { map.setv("type", type++); map1.setv("id", ac.getId()); map1.setv("name", ac.getProperty("name")); String conditionText=Strings.sNull(tr.getProperty("conditionText")); if(!Strings.isEmpty(conditionText)){ map1.setv("conditionText",conditionText ); } list.add(map1); } else if (ac.getProperty("type").equals("exclusiveGateway")) { getTaskActivitys(ac.getId(), activityList, type, map); } else { map.setv("type", type++); break; } } if (list.size() > 0) map.addv("list", list); break; } } return activitiyIds; }
pom.xml
<!--CXF START--> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-api</artifactId> <version>2.7.15</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>2.7.15</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-bindings-soap</artifactId> <version>2.7.15</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>2.7.15</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-ws-security</artifactId> <version>2.7.15</version> </dependency> <!--CXF END-->
web.xml
<servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class>com.auto.webservice.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/webservice/*</url-pattern> </servlet-mapping>
CXFServlet.java:
package com.auto.webservice.servlet; import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.frontend.ServerFactoryBean; import org.apache.cxf.transport.servlet.CXFNonSpringServlet; import org.nutz.ioc.Ioc; import org.nutz.lang.Strings; import org.nutz.log.Log; import org.nutz.log.Logs; import org.nutz.mvc.Mvcs; import javax.jws.WebService; import javax.servlet.ServletConfig; import javax.xml.namespace.QName; /** * Created by wizzer on 15-4-10. */ @SuppressWarnings("serial") public class CXFServlet extends CXFNonSpringServlet { private final Log log = Logs.get(); @Override protected void loadBus(ServletConfig sc) { super.loadBus(sc); //全局配置 Bus bus = getBus(); //添加白名单过滤器 bus.getInInterceptors().add(new IpAddressInInterceptor()); //使用全局配置 BusFactory.setDefaultBus(bus); Ioc ioc = Mvcs.ctx().getDefaultIoc(); for (String name : ioc.getNames()) { try { Object obj = ioc.get(null, name); if (!obj.getClass().getPackage().getName().equals("com.auto.webservice.server")) { continue; } if (obj.getClass().getAnnotation(WebService.class) == null) continue; Class face = Class.forName(obj.getClass().getPackage().getName() + "." + Strings.upperFirst(name)); ServerFactoryBean serverFactoryBean = new ServerFactoryBean(); // 设置服务接口类 serverFactoryBean.setServiceClass(face); // 服务请求路径 serverFactoryBean.setAddress("/" + name.substring(0, name.indexOf("Service"))); // 设置服务实现类 serverFactoryBean.setServiceBean(obj); serverFactoryBean.setBindingId("http://schemas.xmlsoap.org/wsdl/soap12/"); serverFactoryBean.create(); } catch (Throwable e) { } } } }
接口类
WorkflowService.java
package com.auto.webservice.server; import org.nutz.json.Json; import javax.jws.WebService; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by wizzer on 15-4-13. */ @WebService public interface WorkflowService { String start(String flowKey, String userId);//启动流程 }
实现类
WorkflowServiceImpl.java
package com.auto.webservice.server; import org.activiti.engine.*; import org.activiti.engine.form.FormProperty; import org.activiti.engine.form.StartFormData; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.activiti.engine.task.TaskQuery; import org.nutz.dao.Dao; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.json.Json; import org.nutz.json.JsonFormat; import org.nutz.lang.Strings; import org.nutz.log.Log; import org.nutz.log.Logs; import org.nutz.mvc.Mvcs; import javax.jws.WebService; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by wizzer on 15-4-13. */ @IocBean(name = "workflowService") @WebService public class WorkflowServiceImpl implements WorkflowService { private final Log log = Logs.get(); @Inject Dao dao; @Inject FormService formService; @Inject IdentityService identityService; @Inject RepositoryService repositoryService; @Inject RuntimeService runtimeService; @Inject TaskService taskService; /** * 启动一个流程 * * @param flowKey 流程模型key * @param userId 用户ID * @return */ public String start(String flowKey, String userId) { Map<String, Object> map = new HashMap<String, Object>(); try { if (!Strings.isEmpty(userId)) { identityService.setAuthenticatedUserId(userId); } ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(flowKey); map.put("errcode", 0); map.put("errmsg", ""); map.put("processInstanceId", processInstance.getId()); } catch (Exception e) { log.error("WebServcice启动流程出错", e); map.put("errcode", 1); map.put("errmsg", e.getMessage()); } finally { identityService.setAuthenticatedUserId(null); } return Json.toJson(map, JsonFormat.compact()); } }