一、项目简介 基于Spring+SpringMVC+Mybatis分布式敏捷开发系统架构,提供整套公共微服务服务模块:内容管理、支付中心、用户管理(包括第三方)、微信平台、存储系统、配置中心、日志分析、任务和通知等,支持服务治理、监控和追踪,努力为中小型企业打造全方位J2EE企业级开发解决方案。目前已经累计获得10000+的Star,受到了广大程序员的密切关注! 由于该项目框架采用的技术点比较多,新手入门会有一定的困难,所以笔者整理资料写了本篇环境搭建指南,希望能够帮助大家把环境快速的搭建起来。 oschina地址:https://gitee.com/shuzheng/zheng github地址:https://github.com/shuzheng/zheng 二、工具下载 JDK官方下载地址 | 老版本JDK下载地址 TortoiseGit: 下载地址 | 安装与配置教程 Git客户端官网下载太慢,最新版本: Git-2.14.1-64-bit 客户端下载 MySQL数据库: 下载与安装5.7教程 | 百度经验 (电脑可以装多个MySQL,端口不一样即可) MySQL客户端: Navicat for MySQL下载、安装与破解 Maven官方下载地址 下载最新的apache-maven-3.5.0-bin.zip解压到本地目录,打开/conf/settings.xml进行编辑,修改本地的仓库地址,默认的Maven镜像下载速度十分感人,强烈建议使用阿里云的,可以享受飞一般的速度。精简版的配置如下,以供参考:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <!-- 仓库地址 --> <localRepository>E:/maven/repository</localRepository> <pluginGroups></pluginGroups> <proxies></proxies> <servers></servers> <mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors> <profiles></profiles> </settings> |
Redis官方下载地址 : Linux版本 | Windows教程 | 安装教程2 最新版本Redis3.2配置文件redis.conf详细说明 Redis客户端Redis Desktop Manager: 官网下载 | PC6快速下载 ActiveMQ: 官方最新版下载地址 | ActiveMQ基本配置与示例演示 ZooKeeper:官方下载地址 | Zookeeper 安装和配置 Nginx:官方下载地址 | Nginx安装与配置 | 负载均衡 dubbo-admin-2.5.4: 下载地址 (需使用jdk1.7) | dubbo-admin管理平台搭建 三、导入项目 推荐使用IntelliJ IDEA, 安装教程: Windows7下安装与破解IntelliJ IDEA2017 IDEA使用Git在线导入,具体操作可以百度一下,或者File ->Open进行导入项目。 导入完毕,IDEA右侧Maven Projects找到zheng->Lifecycle->install 点击运行,在本地Repository中安装依赖的jar包,编译时间有点长,请耐心等待。 加入作者建立的QQ群,群内含各种工具、文档、视频教程下载,还有热心群友答疑解惑。 四、环境搭建 QQ群内提供了环境搭建文档和视频【点击下载】 ,未能加入群?没关系,参考本篇指南就够了。 修改项目配置文件里mysql和Redis密码: 各dao模块和rpc-service模块的redis.properties、jdbc.properties、generator.properties数据库连接等配置信息,其中master.redis.password、master.jdbc.password、slave.jdbc.password、generator.jdbc.password里密码值使用了AES加密,请使用com.zheng.common.util.AESUtil工具类修改这些值。项目里默认的是空字符串加密后密文:FNFl9F2O2Skb8yoKM0jhHA==。 配置hosts, 打开文件C:\Windows\System32\drivers\etc\hosts,增加如下配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
127.0.0.1 ui.zhangshuzheng.cn 127.0.0.1 upms.zhangshuzheng.cn 127.0.0.1 cms.zhangshuzheng.cn 127.0.0.1 pay.zhangshuzheng.cn 127.0.0.1 ucenter.zhangshuzheng.cn 127.0.0.1 wechat.zhangshuzheng.cn 127.0.0.1 api.zhangshuzheng.cn 127.0.0.1 oss.zhangshuzheng.cn 127.0.0.1 config.zhangshuzheng.cn 127.0.0.1 zkserver 127.0.0.1 rdserver 127.0.0.1 dbserver 127.0.0.1 mqserver |
配置Nginx:进入项目zheng/project-tools/nginx/,把里面的nginx.conf和servers复制到Nginx安装路径的conf目录下,比如我的D:\Java\nginx-1.12.1\conf,然后进入servers文件夹修改zheng-ui.conf,root路径修改到zheng-ui的根目录,详细的配置参考下面:
1 2 3 4 5 6 7 8 9 10 |
server { listen 1000 default; server_name localhost; location / { root E:/workspace/IntelliJIDEA2017/zheng/zheng-ui/; index index.html index.htm; add_header Access-Control-Allow-Origin *; } access_log logs/zheng-ui.access.log; } |
五、启动项目 六、见证奇迹的时刻 访问 http://upms.zhangshuzheng.cn:1111/,默认帐号密码:admin/123456 内容管理系统CMS访问 http://cms.zhangshuzheng.cn:2224,页面如下: 至此,项目的环境搭建大功告成,为了同学们能够快速入门,搜罗了不少资料,如有帮助请点赞。 现在已经将近凌晨一点了,洗洗睡喽! from:https://my.oschina.net/yzuzhang/blog/1538555
View DetailsDubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和Spring框架无缝集成。 主要核心部件 Remoting: 网络通信框架,实现了 sync-over-async 和 request-response 消息机制. RPC: 一个远程过程调用的抽象,支持负载均衡、容灾和集群功能 Registry: 服务目录框架用于服务的注册和服务事件发布和订阅 工作原理 Provider 暴露服务方称之为“服务提供者”。 Consumer 调用远程服务方称之为“服务消费者”。 Registry 服务注册与发现的中心目录服务称之为“服务注册中心”。 Monitor 统计服务的调用次数和调用时间的日志服务称之为“服务监控中心”。 (1) 连通性: 注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小 监控中心负责统计各服务调用次数,调用时间等,统计先在内存汇总后每分钟一次发送到监控中心服务器,并以报表展示 服务提供者向注册中心注册其提供的服务,并汇报调用时间到监控中心,此时间不包含网络开销 服务消费者向注册中心获取服务提供者地址列表,并根据负载算法直接调用提供者,同时汇报调用时间到监控中心,此时间包含网络开销 注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外 注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者 注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表 注册中心和监控中心都是可选的,服务消费者可以直连服务提供者 (2) 健壮性: 监控中心宕掉不影响使用,只是丢失部分采样数据 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务 注册中心对等集群,任意一台宕掉后,将自动切换到另一台 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯 服务提供者无状态,任意一台宕掉后,不影响使用 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复 (3) 伸缩性: 注册中心为对等集群,可动态增加机器部署实例,所有客户端将自动发现新的注册中心 服务提供者无状态,可动态增加机器部署实例,注册中心将推送新的服务提供者信息给消费者 例子 服务端 定义一个Service Interface:(HelloService.java) 1 2 3 4 5 6 7 8 package com.alibaba.hello.api; public interface HelloService { String sayHello(String name); } 接口的实现类:(HelloServiceImpl.java) 1 2 3 4 5 6 7 package com.alibaba.hello.impl; import com.alibaba.hello.api.HelloService; public class HelloServiceImpl implements HelloService{ public String sayHello(String name){ return "Hello" + name; } } Spring配置:(provider.xml) 1 2 3 4 5 6 7 8 […]
View Details导入了一个工程,编译什么的都还好,但是报了一个XML的错误。 cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'dubbo:application'. 具体错误如下: Multiple annotations found at this line: – cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'dubbo:application'. – schema_reference.4: Failed to read schema document 'http://code.alibabatech.com/schema/dubbo/dubbo.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>. 根据错误提示,有可能是http://code.alibabatech.com/schema/dubbo/dubbo.xsd这个文档找不到或者打不开,于是百度了一下,发现类似问题的问还是比较多的,比较轻松找到解决办法。大致的思路是,到网上下载一个dubbo.xsd文件,其实在dubbo的jar包里就有,直接解压出来就好,放到本地目录,然后在Eclipse里配置上关联关系,让Eclipse能找到这个文件即可。 1、下载一个dubbo.xsd文件; 2、在windows->preferrence->xml->xmlcatalogadd->catalog entry ->file system 选择刚刚下载的文件路径; 3、修改key值和配置文件的http://code.alibabatech.com/schema/dubbo/dubbo.xsd 相同保存。 4、在xml文件右键validate就可以k解决了。 后记:有其它的xsd文件找不到的情况,也可以按照类似的方法解决。 from:https://blog.csdn.net/ddshang/article/details/72772640
View Details
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
var http = require('http'); var moment = require('moment'); process.env.TZ = "Asia/Shanghai"; http.createServer(function (request, response) { var sql = require('mssql'); sql.close(); //连接方式1:"mssql://用户名:密码@ip地址(无需端口号)/SqlServer名/数据库名称" //连接方式2:"mssql://用户名:密码@ip地址:1433(默认端口号)/数据库名称" sql.connect("mssql://sa:s1a2@127.0.0.1/DBNAME").then(function () { new sql.Request().query('select top 10 * from TABLENAME').then(function (result) { response.writeHead(200, { "content-type": "text/html;charset=utf-8;" }); result.recordset.forEach(row => { response.write(row.ID + ' - ' + row.Name + ' - ' + moment(row.DateTime).utc().format("YYYY-MM-DD HH:mm:ss") + "<br>"); }); response.end(); }).catch(function (err) { console.log(err); }); }).catch(function (err) { console.log(err); }); }).listen(8886); |
引用: https://blog.csdn.net/u010668495/article/details/50817136 https://www.npmjs.com/package/mssql https://www.cnblogs.com/cyfhykx/p/6224078.html
View Details今天开始学习Node.js,在写一个文件上传的功能时候,调用fs.renameSync方法错误 出错代码所在如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
1 function upload(response,request){ 2 console.log("upload called"); 3 var form = new formidable.IncomingForm(); 4 console.log("about to parse"); 5 form.parse(request, function(error, fields, files) { 6 console.log("parsing done"); 7 fs.renameSync(files.upload.path, "./tmp/test.jpg"); 8 response.writeHead(200, {"Content-Type": "text/html"}); 9 response.write("received image:<br/>"); 10 response.write("<img src='/show' />"); 11 response.end(); 12 }); 13 } |
大致分析后,预计是因为跨磁盘分区移动或操作文件会有权限问题。 下面提供两种解决办法: 方法一: 主要利用fs的createReadStream、createWriteSream和unlinkSync方法 具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
1 function upload(response,request){ 2 console.log("upload called"); 3 var form = new formidable.IncomingForm(); 4 console.log("about to parse"); 5 form.parse(request, function(error, fields, files) { 6 console.log("parsing done"); 7 // fs.renameSync(files.upload.path, "./tmp/test.jpg"); 8 <strong>var readStream=fs.createReadStream(files.upload.path); 9 var writeStream=fs.createWriteStream("./tmp/test.jpg"); 10 readStream.pipe(writeStream); 11 readStream.on('end',function(){ 12 fs.unlinkSync(files.upload.path); 13 }); </strong>14 response.writeHead(200, {"Content-Type": "text/html"}); 15 response.write("received image:<br/>"); 16 response.write("<img src='/show' />"); 17 response.end(); 18 }); 19 } |
PS:我用的node版本是0.10.69,如果使用的是0.6以下的版本,可以使用util.pump 相应代码只需将上面的代码中readStream.on处改成:(注意引入util模块)
1 2 3 |
util.pump(readStream,writeStream, function() { fs.unlinkSync('files.upload.path'); }); |
方法二: 这种就简洁很多了 添加一个 form.uploadDir=’tmp' 即可(写一个临时路径)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
1 function upload(response,request){ 2 console.log("upload called"); 3 var form = new formidable.IncomingForm(); 4 <strong> form.uploadDir='tmp'; </strong> 5 6 console.log("about to parse"); 7 form.parse(request, function(error, fields, files) { 8 console.log("parsing done"); 9 fs.renameSync(files.upload.path, "./tmp/test.jpg"); 10 response.writeHead(200, {"Content-Type": "text/html"}); 11 response.write("received image:<br/>"); 12 response.write("<img src='/show' />"); 13 response.end(); 14 }); 15 } 16 |
解决问题后,就可以很开心的继续我的Node学习了,感觉路还很长啊 PS:附上两个有关Node文件上传的帖子,个人觉得挺不错的,来源都是cnode nodejs-post文件上传原理详解 node-formidable详解 from:https://www.cnblogs.com/glczero/archive/2014/08/23/3932024.html
View Details如果VS2013,在打开解决方案时,报如下错误: “未找到与约束 ContractName Microsoft.Internal.VisualStudio.PlatformUI.ISolutionAttachedCollectionService RequiredTypeIdentity Microsoft.Internal.VisualStudio.PlatformUI.ISolutionAttachedCollectionService 匹配的导出” 导致项目无法打开以及VS无法关闭。 解决方法: 1.关闭VS; 2.去C:/Users/<your users name>/AppData/Local/Microsoft/VisualStudio/12.0/ComponentModelCache文件夹下删除所有文件及文件夹; 3.重新打开VS即可。 如果是vs2012的话 方法一: 可以尝试删除最近更新的windows补丁更新,主要是关于.net Framework的。 如果方法一行不通,可以尝试方法二,或直接用方法二解决。 方法二: 安装微软的windows补丁 KB2781514(官网:https://www.microsoft.com/zh-cn/download/details.aspx?id=36020) ,补丁主要解决“在 .NET Framework 4.5 更新之后,Visual Studio 用户可能无法打开或创建 C++ 或 JavaScript 文件或项目。” from:https://www.cnblogs.com/ChineseMoonGod/p/5687521.html
View Details注:laravel 查询返回行的都是 php 的 stdClass 对象实例,不是数组!!!! 1)查询多行(get)
1 |
DB::table('table_name')->get(); |
带偏移和限制的查询(skip take 或 offset limit)(两种用法是一样的)
1 2 3 4 5 |
//skip take DB::table('table_name')->skip(10)->take(10)->get(); //offset limit DB::table('table_name')->offset(20)->limit(10)->get(); |
2)查询一行(first)
1 |
DB::table('table_name')->first(); |
1 |
DB::table('table_name')->find(1); |
PS:find方法也可以查多行,它可以这样玩 DB::table('table_name')->find([1,2,3,4]); 3)直接查询一个字段(value)
1 |
DB::table('table_name')->where('name','Tiac')->value('email'); |
4)查询一列(pluck)
1 |
DB::table('table_name')->where('brand_id','100')->pluck('goods_id'); |
5)块组结果集(chunk) 使用情景: 假设我们需要查询 1 百万的数据,并对其做处理,一次性查询 1 百万并统一处理势必会对数据产生不小的压力,消耗大量的服务器资源,有没有一种更做优的处理方法? 将 1 百万的查询分成 1000 次 1000 条记录的查询的块查询怎样?? 这个 chunk的作用,chunk方法接口一个闭包函数做回调处理
1 2 3 4 5 |
DB::table('users')->orderBy('id')->chunk(1000, function($users) { foreach ($users as $user) { // } }); |
PS:上面只是举例,chunk 貌似不能和 limit 一起用,chunk 默认情况下一次性处理整张表的数据,不过我可以通过自己加判断用 return false 跳出 chunk 操作 6)聚合函数(count max min avg sum 等等)
1 |
DB::table('table_name')->count(); |
PS:其他聚合函数的使用方法一样的,不一一举例了 7)where 条件字句 这个比较多,懒得写了,想看的直接到 laravel 学院看吧,传送门:http://laravelacademy.org/post/6140.html#ipt_kb_toc_6140_8 (where, orWhere, whereNUll, whereIn, whereNotIn, whereBetween, whereNotBetween, whereDate, whereYear, whereMonth, whereDay 等等) 8)orderBy 排序字句
1 |
DB::table('table_name')->orderBy('id','desc')->get(); |
PS:如果想要返回随机的查询结果集,可以使用 inRandomOrder 子句 […]
View Details
1 2 3 4 |
$user_info = DB::table('usermetas') ->select('browser', DB::raw('count(*) as total')) ->groupBy('browser') ->get(); |
from:https://stackoverflow.com/questions/18533080/laravel-eloquent-groupby-and-also-return-count-of-each-group
View Details昨天在写程序的时候,发现在用户的时候记录IP和地区信息也许以后用得上,去网上找了找,发现实现的方式有好多好多,因为我用的ThinkPHP,后来又去TP官网找了找,最后采用了下面这种方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
<?php // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK IT ] // +---------------------------------------------------------------------- // | Copyright (c) 2009 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st <liu21st@gmail.com> // +---------------------------------------------------------------------- /** * IP 地理位置查询类 修改自 CoolCode.CN * 由于使用UTF8编码 如果使用纯真IP地址库的话 需要对返回结果进行编码转换 * @author liu21st <liu21st@gmail.com> */ class IpLocation { /** * QQWry.Dat文件指针 * * @var resource */ private $fp; /** * 第一条IP记录的偏移地址 * * @var int */ private $firstip; /** * 最后一条IP记录的偏移地址 * * @var int */ private $lastip; /** * IP记录的总条数(不包含版本信息记录) * * @var int */ private $totalip; /** * 构造函数,打开 QQWry.Dat 文件并初始化类中的信息 * * @param string $filename * @return IpLocation */ public function __construct($filename = "UTFWry.dat") { $this->fp = 0; if (($this->fp = fopen(dirname(__FILE__).'/'.$filename, 'rb')) !== false) { $this->firstip = $this->getlong(); $this->lastip = $this->getlong(); $this->totalip = ($this->lastip - $this->firstip) / 7; } } /** * 返回读取的长整型数 * * @access private * @return int */ private function getlong() { //将读取的little-endian编码的4个字节转化为长整型数 $result = unpack('Vlong', fread($this->fp, 4)); return $result['long']; } /** * 返回读取的3个字节的长整型数 * * @access private * @return int */ private function getlong3() { //将读取的little-endian编码的3个字节转化为长整型数 $result = unpack('Vlong', fread($this->fp, 3).chr(0)); return $result['long']; } /** * 返回压缩后可进行比较的IP地址 * * @access private * @param string $ip * @return string */ private function packip($ip) { // 将IP地址转化为长整型数,如果在PHP5中,IP地址错误,则返回False, // 这时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串 return pack('N', intval(ip2long($ip))); } /** * 返回读取的字符串 * * @access private * @param string $data * @return string */ private function getstring($data = "") { $char = fread($this->fp, 1); while (ord($char) > 0) { // 字符串按照C格式保存,以\0结束 $data .= $char; // 将读取的字符连接到给定字符串之后 $char = fread($this->fp, 1); } return $data; // return iconv('gb2312', 'utf-8', $data); //通用函数,不能在这转 } /** * 返回地区信息 * * @access private * @return string */ private function getarea() { $byte = fread($this->fp, 1); // 标志字节 switch (ord($byte)) { case 0: // 没有区域信息 $area = ""; break; case 1: case 2: // 标志字节为1或2,表示区域信息被重定向 fseek($this->fp, $this->getlong3()); $area = $this->getstring(); break; default: // 否则,表示区域信息没有被重定向 $area = $this->getstring($byte); break; } return $area; // return iconv('gb2312', 'utf-8', $area); //在最后统一转 } /** * 根据所给 IP 地址或域名返回所在地区信息 * * @access public * @param string $ip * @return array */ public function getlocation($ip='') { if (!$this->fp) return null; // 如果数据文件没有被正确打开,则直接返回空 if(empty($ip)) $ip = get_client_ip(); $location['ip'] = gethostbyname($ip); // 将输入的域名转化为IP地址 $ip = $this->packip($location['ip']); // 将输入的IP地址转化为可比较的IP地址 // 不合法的IP地址会被转化为255.255.255.255 // 对分搜索 $l = 0; // 搜索的下边界 $u = $this->totalip; // 搜索的上边界 $findip = $this->lastip; // 如果没有找到就返回最后一条IP记录(QQWry.Dat的版本信息) while ($l <= $u) { // 当上边界小于下边界时,查找失败 $i = floor(($l + $u) / 2); // 计算近似中间记录 fseek($this->fp, $this->firstip + $i * 7); $beginip = strrev(fread($this->fp, 4)); // 获取中间记录的开始IP地址 // strrev函数在这里的作用是将little-endian的压缩IP地址转化为big-endian的格式 // 以便用于比较,后面相同。 if ($ip < $beginip) { // 用户的IP小于中间记录的开始IP地址时 $u = $i - 1; // 将搜索的上边界修改为中间记录减一 } else { fseek($this->fp, $this->getlong3()); $endip = strrev(fread($this->fp, 4)); // 获取中间记录的结束IP地址 if ($ip > $endip) { // 用户的IP大于中间记录的结束IP地址时 $l = $i + 1; // 将搜索的下边界修改为中间记录加一 } else { // 用户的IP在中间记录的IP范围内时 $findip = $this->firstip + $i * 7; break; // 则表示找到结果,退出循环 } } } //获取查找到的IP地理位置信息 fseek($this->fp, $findip); $location['beginip'] = long2ip($this->getlong()); // 用户IP所在范围的开始地址 $offset = $this->getlong3(); fseek($this->fp, $offset); $location['endip'] = long2ip($this->getlong()); // 用户IP所在范围的结束地址 $byte = fread($this->fp, 1); // 标志字节 switch (ord($byte)) { case 1: // 标志字节为1,表示国家和区域信息都被同时重定向 $countryOffset = $this->getlong3(); // 重定向地址 fseek($this->fp, $countryOffset); $byte = fread($this->fp, 1); // 标志字节 switch (ord($byte)) { case 2: // 标志字节为2,表示国家信息又被重定向 fseek($this->fp, $this->getlong3()); $location['country'] = $this->getstring(); fseek($this->fp, $countryOffset + 4); $location['area'] = $this->getarea(); break; default: // 否则,表示国家信息没有被重定向 $location['country'] = $this->getstring($byte); $location['area'] = $this->getarea(); break; } break; case 2: // 标志字节为2,表示国家信息被重定向 fseek($this->fp, $this->getlong3()); $location['country'] = $this->getstring(); fseek($this->fp, $offset + 8); $location['area'] = $this->getarea(); break; default: // 否则,表示国家信息没有被重定向 $location['country'] = $this->getstring($byte); $location['area'] = $this->getarea(); break; } if (trim($location['country']) == 'CZ88.NET') { // CZ88.NET表示没有有效信息 $location['country'] = '未知'; } if (trim($location['area']) == 'CZ88.NET') { $location['area'] = ''; } $location['country']=iconv('gb2312', 'utf-8', $location['country']); $location['area']=iconv('gb2312', 'utf-8', $location['area']); return $location; } /** * 析构函数,用于在页面执行结束后自动关闭打开的文件。 * */ public function __destruct() { if ($this->fp) { fclose($this->fp); } $this->fp = 0; } } IpLocation.class.php |
这个是TP里带的,从上面的信息上来看已经很旧了,不过感觉写的还不错,就没改什么,只是在后面加上了
1 2 |
$location['country']=iconv('gb2312', 'utf-8', $location['country']); $location['area']=iconv('gb2312', 'utf-8', $location['area']); |
因为TP的纯真数据库已经转码了,但是很旧,似乎还是2012年的,IP这东西,那么老的东西估计很不准,于是我去纯真官网下了一个,但是纯真本身是GB2312的,所以要加上上面这两句转码一下。 然后在项目中导入了这个PHP类以后,这样去用就可以。
1 2 3 |
$ip=get_client_ip(); $ipData=new IpLocation("QQWry20140125.dat"); $ipInfo=$ipData->getlocation($ip); |
得到的结果是这样的,测试IP:218.197.147.154。
1 2 3 4 5 6 |
array (size=5) 'ip' => string '218.197.147.154' (length=15) 'beginip' => string '218.197.146.1' (length=13) 'endip' => string '218.197.147.154' (length=15) 'country' => string '湖北省武汉大学' (length=21) 'area' => string '外语自主学习中心' (length=24) |
最新版的纯真数据库去纯真官网下就可以,里面的QQWry.dat就是,用的时候也可以像我那样在后面标上版本,免得以后记不清。然后把.dat跟上面的php类放在一个目录下就OK啦。 from:https://www.cnblogs.com/fordawn/p/3538665.html
View Details微软现在所有Visual Studio相关的下载到www.visualstudio.com网站下载是非常方便的 下载地址: 下载ISO版本后,进行安装,由于10-20人的小团队,不需要SharePoint所以就安装【基本服务器】版本 点击下一步 勾选试用(请支持正版),点击下一步 由于本次主要数据库选择了阿里云的RDS,而阿里云的SQL Server只有2008 R2版本而且太贵,所以就选择安装一个Express版本 由于本次发布主要采用WebDeploy,而且以前也没使用过TFS的发布,不是很熟悉流程和原理,以后有时间再研究吧,暂时不勾选生产发布代理 选择下一步 下一步后检查配置 点击配置,然后开始安装了 安装的时候发现有在线下载SQL Server Express,难怪2015.2的安装包突然小了500多M,微软真是越来越与时俱进了啊 安装后默认端口是8080,因此需要在服务器上防火墙打开8080端口 由于本次服务是采用了域名进行访问并且使用了HTTPS,因此需要在配置中更改URL并到IIS中绑定相关域名 然后新建一个用户 新建一个项目集合 然后添加刚才的用户为管理员 这样,就可以在Visual Studio里面用刚才添加的用户连接到TFS服务器了 from:https://www.cnblogs.com/printhelloworld/p/5622186.html
View Details