Jump to content
新域网络技术论坛

All Activity

This stream auto-updates     

  1. Earlier
  2. 最近公司里在使用Perl语言,格式化代码不如PHP那么方便,有个PerlTidy的工具很方便,能够将代码格式化保存,美中不足的是,它会自动生成一个扩展名为.tdy的文件,原文件不会去改,自己用的时候还要手动删除文件及改名,好麻烦,能不能让它自动完成?当然可以,我是在windows里,如果是其它系统也可以借鉴,按同样的思路去实现,当然实现的方法就不一样了。 @echo off perl.exe %~dp0perltidy-20190601.pl %1 %2 %3 %4 %5 %6 %7 %8 %9 copy %1.tdy %1 del %1.tdy 安装方式备忘: 1. 下载安装包:https://sourceforge.net/projects/perltidy/ 2. 解压缩文件,到目录中执行 perl pm2pl 3. 生成一个类似于perltidy-20190601.pl的文件,然后在这个目录中新建上面的BAT文件,加上PATH,今后就可以安心调用了。
  3. 为了更直观的了解框架运行速度,特做了此次测试,为了公平起见,测试在同一台计算机上,各类请求分别请求10次,目前分三种情况,一是直接输出Hello World文本,二是使用默认模板输出相同内容,三是输出JSON串,其实一和三基本属于同一层面上的东西。先看测试代码。为了公平起见,未使用任何第三方代码。 <?php /** * Created by PhpStorm. * User: Jamers * Date: 2019-06-27 * Time: 10:18 * File: speedtest.php */ set_time_limit(0); $acts = [ 'text', 'template', 'json', ]; $urls = [ 'laravel' => 'http://localhost:8080/laravel/public/index.php/test/', 'zpf' => 'http://localhost:8080/Test/zpf/index.php?a=', 'ci' => 'http://localhost:8080/Test/ci/index.php/Test/', ]; $loop = 10; $ret = []; for ($i = $loop; $i > 0; $i--) { foreach ($acts as $act) { foreach ($urls as $k => $v) { $url = $v . $act; $s = microtime(true) * 1000; $data = getRequest($url); $time = round(microtime(true) * 1000 - $s, 4); if (!isset($ret[$act][$k])) { $ret[$act][$k] = ['total' => 0, 'max' => $time, 'min' => $time, 'avg' => 0, 'lost' => 0,]; } $ret[$act][$k]['total'] += $time; if ($ret[$act][$k]['max'] < $time) { $ret[$act][$k]['max'] = $time; } if ($ret[$act][$k]['min'] > $time) { $ret[$act][$k]['min'] = $time; } if ($ret[$act][$k]['avg'] == 0) { $ret[$act][$k]['avg'] = $time; } else { $ret[$act][$k]['avg'] = round(($time + $ret[$act][$k]['avg'])/2, 4); } if (!$data) { $ret[$act][$k]['lost'] ++; } } } } $result = var_export($ret, true); file_put_contents('times.txt', $result); echo $result; function getRequest($url, $header = []) { $ch = curl_init(); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_HEADER, false); if ($header) { curl_setopt($ch, CURLOPT_HTTPHEADER, $header); } curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_AUTOREFERER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $res = curl_exec($ch); $info = curl_getinfo($ch); curl_close($ch); if ($info['http_code']!=200) { $res = ''; } return $res; } 框架方面,均使用默认配置,有修改的地方列出来: Laravel 5.8.26,今天使用composer create-project --prefer-dist laravel/laravel laravel安装: routes\web.php 添加以下路由: Route::get('test/{act}', function (App\Http\Controllers\TestController $obj, $act) { return $obj->$act(); }); app\Http\Controllers\TestController.php <?php /** * Created by PhpStorm. * User: Jamers * Date: 2019-06-27 * Time: 10:00 * File: TestController.php */ namespace App\Http\Controllers; class TestController extends Controller { public function text() { exit('Hello World'); } public function template() { $data = [ 'name' => 'World', 'list' => [ 'Google' => 'https://www.google.com', 'Baidu' => 'https://www.baidu.com', 'Sohu' => 'https://www.sohu.com', 'Zomew' => '', ], ]; return view('demo', $data); } public function json() { $data = [ 'name' => 'World', 'list' => [ 'Google' => 'https://www.google.com', 'Baidu' => 'https://www.baidu.com', 'Sohu' => 'https://www.sohu.com', 'Zomew' => '', ], ]; header('Content-type: application/json'); exit(json_encode($data)); } } resources\views\demo.blade.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello {{ $name }}</title> </head> <body> @if ($list && is_array($list)) @foreach ($list as $k => $v) @if (trim($v)) <a href="{{ $v }}" target="_blank">{{ $k }}</a><br> @else {{ $k }}<br> @endif @endforeach @else no data @endif </body> </html> zpf几乎是原生代码,因为没有默认控制器只能新建入口文件,https://github.com/zomew/zpf 因为使用了Twig模板引擎,需要在git clone完成后,composer update一下。 新建index.php <?php /** * Created by PhpStorm. * User: Jamers * Date: 2019-06-27 * Time: 9:32 * File: index.php */ require_once '__INIT.php'; $act = \ZF\Common::input('a'); switch ($act) { case 'text': exit('Hello World'); break; case 'template': $data = [ 'name' => 'World', 'list' => [ 'Google' => 'https://www.google.com', 'Baidu' => 'https://www.baidu.com', 'Sohu' => 'https://www.sohu.com', 'Zomew' => '', ], ]; $twig = new \ZF\Twig(); echo $twig->render('demo.twig', $data); break; case 'json': $data = [ 'name' => 'World', 'list' => [ 'Google' => 'https://www.google.com', 'Baidu' => 'https://www.baidu.com', 'Sohu' => 'https://www.sohu.com', 'Zomew' => '', ], ]; header('Content-type: application/json'); exit(json_encode($data)); break; default: exit('Access deny'); break; } views\demo.twig <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello {{ name }}</title> </head> <body> {% if list %} {% for k,v in list %} {% if v|trim %} <a href="{{ v }}" target="_blank">{{ k }}</a><br> {% else %} {{ k }}<br> {% endif %} {% endfor %} {% else %} no data {% endif %} </body> </html> CodeIgniter 3.1.10 application\controllers\Test.php <?php /** * Created by PhpStorm. * User: Jamers * Date: 2019-06-27 * Time: 9:07 * File: Test.php */ defined('BASEPATH') or exit('No direct script access allowed'); class Test extends CI_Controller { public function text() { exit('Hello World'); } public function template() { $data = [ 'name' => 'World', 'list' => [ 'Google' => 'https://www.google.com', 'Baidu' => 'https://www.baidu.com', 'Sohu' => 'https://www.sohu.com', 'Zomew' => '', ], ]; $this->load->view('demo', $data); } public function json() { $data = [ 'name' => 'World', 'list' => [ 'Google' => 'https://www.google.com', 'Baidu' => 'https://www.baidu.com', 'Sohu' => 'https://www.sohu.com', 'Zomew' => '', ], ]; header('Content-type: application/json'); exit(json_encode($data)); } } application\views\demo.php <?php defined('BASEPATH') or exit('No direct script access allowed'); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello <?php echo $name; ?></title> </head> <body> <?php if (isset($list) && $list && is_array($list)) { foreach ($list as $k => $v) { if (trim($v)) { echo "<a href='{$v}' target='_blank'>{$k}</a><br>"; } else { echo "{$k}<br>"; } } } else { echo 'no data'; } ?> </body> </html> 相关测试代码仅这些,然后看一下本地测试的结果: array ( 'text' => array ( 'laravel' => array ( 'total' => 3435.4015, 'max' => 359.5203, 'min' => 329.5181, 'avg' => 353.3861, 'lost' => 0, ), 'zpf' => array ( 'total' => 2270.3377, 'max' => 234.7439, 'min' => 221.2659, 'avg' => 228.5257, 'lost' => 0, ), 'ci' => array ( 'total' => 2397.8734999999997, 'max' => 251.7878, 'min' => 221.7522, 'avg' => 231.6582, 'lost' => 0, ), ), 'template' => array ( 'laravel' => array ( 'total' => 5673.1377, 'max' => 584.2161, 'min' => 546.803, 'avg' => 572.1757, 'lost' => 0, ), 'zpf' => array ( 'total' => 2369.9499, 'max' => 254.4719, 'min' => 220.6382, 'avg' => 233.7834, 'lost' => 0, ), 'ci' => array ( 'total' => 4424.9958, 'max' => 464.0081, 'min' => 431.9641, 'avg' => 446.3534, 'lost' => 0, ), ), 'json' => array ( 'laravel' => array ( 'total' => 3397.3995, 'max' => 349.1572, 'min' => 328.8938, 'avg' => 342.091, 'lost' => 0, ), 'zpf' => array ( 'total' => 2289.3552999999997, 'max' => 237.9939, 'min' => 214.7542, 'avg' => 232.6302, 'lost' => 0, ), 'ci' => array ( 'total' => 2363.8577999999998, 'max' => 248.4502, 'min' => 222.6829, 'avg' => 240.1061, 'lost' => 0, ), ), ) 从结果上来看, 1. 简单的hello world,laravel由于加载的内容较多,需要的时间足足比其它框架高出来100多ms,CodeIgniter和zpf几乎平手,平均速度相差2-3ms。 2. 模板引擎,这样框架需要加载的东西更多了,laravel又垫底,平均速度比CI高了125ms,CI与zpf相比高了212ms,差距还是很明显的。 3. JSON,之前也说过json和测试1的纯文本几乎一致,laravel还是慢100ms,CI和zpf相比高了7ms。 总结:如果是相对轻型的应用使用zpf应该会更合适一些,扩展方面需要自行完善,laravel虽然在测试中均在最后,不过由于它的可扩展性较强,目前仍有很多项目选择。CodeIgniter效率上中规中矩,但是模板引擎对前端来说太不友好了,也只能适合一些小型的应用,当然可以换模板引擎,那样的话不如换个框架来用了。 以上纯属个人看法,如果测试过程有所疏漏,烦请告知,谢谢。
  4. 升级过后有时会无法添加用户,出现错误提示: pw: user 'xxx' disappeared during update 同步生成一下密码文件,即可 /usr/sbin/pwd_mkdb -p /etc/master.passwd
  5. freebsd-update fetch install pkg update && pkg upgrade freebsd-update -r 12.0-RELEASE upgrade freebsd-update install 这里重启一次 reboot freebsd-update install pkg-static install -f pkg pkg update pkg upgrade reboot
  6. package main import ( "./myfunc" //加载本项目包 "flag" //解析命令行参数 "fmt" "os" "strconv" ) //定义解析的命令行参数 var s = flag.String("s", "", "某某字符串") var b = flag.Bool("b", false, "布尔参数") func main() { //定义names变量 等同于 names := "World" var names = "World" //遍历命令行参数并输出 for idx, args := range os.Args { fmt.Println(strconv.Itoa(idx) + ":", args) } //解析命令行参数并赋值 flag.Parse() fmt.Println("-b:", *b) fmt.Println("-s:", *s) //未解析的参数 var params = flag.Args() fmt.Println(params) //如果有未解析的参数,访问 if len(params) > 0 { names = params[0] } fmt.Println("Hello " + names + "!") //多数据定义并赋值 var a, b = 2, 3 //省略var的方式定义,如果之前已经有此变量时会产生编译错误 c := 99 fmt.Printf("%d _++_+ %d, %x\n", a, b, &c) // & 取地址 * 取内容 fmt.Println(*&c) //调用其他包的函数 fmt.Println(myfunc.Demo("Hello", "=-=-=", "World!")) //字典定义以及遍历 dict := map[string] string {"One": "1111", "Two": "2222", "Three": "3333",} for k, v := range dict { fmt.Printf("%s: %s\n", k, v) } } /* 文件名及路径:myfunc/functions.go */ package myfunc func Demo(sstr ...string) string { result := "" //数组遍历方式 /*for i := 0; i < len(sstr); i ++ { result += " " + sstr[i] }*/ //通用遍历方式 数组、切片、字典通用 for _, v := range sstr { result += " " + v } return result }
  7. 继续优化python代码,添加请求模式(POST|GET),添加链接配置,直接通过参数可控制具体请求的链接。 # -*- Coding: UTF-8 -*- """ 自定义参数高并发压力测试工具 @author Jamers @since 2019.05.08 """ import time import sys import getopt import asyncio from aiohttp import ClientSession import json import re import codecs sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach()) url = "http://192.168.0.200/cli/asynctest.php" tasks = [] result = {} def usage(): print("usage: python " + sys.argv[0] + " -n 100 -c 500 -m post|get http://www.baidu.com") sys.exit() async def run(cid=0, obj=None): global cols if obj is None: obj = asyncio.Semaphore(cols) async with obj: async with ClientSession() as session: if method == 'get': resp = session.get(url, data={"id": cid}) else: resp = session.post(url, data={"id": cid}) async with resp as response: try: text = await response.text() j = json.loads(text) except json.JSONDecodeError: if -1 not in result: result[-1] = 0 result[-1] += 1 else: if j["code"] not in result: result[j["code"]] = 0 result[j["code"]] += 1 # print(j) if __name__ == "__main__": nums = 10 cols = 500 method = 'get' if len(sys.argv) > 1: opts, args = getopt.getopt(sys.argv[1:], "hn:c:m:") if len(args) > 0: reg = re.compile(r"^https?://[^/]{3,}\S*$", re.I) url = args.pop(0) if not reg.match(url): print("URL must be Illegal") usage() for op, value in opts: if op == "-h": usage() elif op == "-n": nums = int(value) elif op == '-c': cols = int(value) elif op == '-m': tmp = value.lower() if tmp in ['post', 'get', ]: method = tmp else: print("method only set to post or get") usage() loop = asyncio.get_event_loop() start_time = time.time() semaphore = asyncio.Semaphore(cols) tasks = [run(cid, semaphore) for cid in range(nums)] loop.run_until_complete(asyncio.wait(tasks)) loop.close() end_time = time.time() print(result) print("Loop Nums:", str(nums)) print("Start Time:", str(start_time)) print("End Time:", str(end_time)) print("Running Time:", str(end_time - start_time))
  8. 我在FREEBSD上测试过了,用参数 -n 10000 -c 10000 没问题,所以并发压力测试的时候尽量不要用windows,另外考虑带宽问题,尽量在内网走,基本不受带宽限制。 如果像高并发秒杀的时候,可以模拟各种情况了。甚至于分析最终秒杀成功的用户是否属于随机,保证算法的公平性。
  9. apache中有ab压力测试工具,但是无法自定义参数,并且无法分析最终结果,特写此文,共勉之。 我们先在服务端创建一个有10%概率成功的PHP脚本,由于高并发使用默认的随机数算法可能有些问题,所以采用了自定义的随机数种子算法。这里接收id用以区分请求顺序号。 $rate = 10; $id = isset($_REQUEST['id']) ? $_REQUEST['id'] : '0'; $seed = sRandSeed(); mt_srand($seed); if (mt_rand(1, 100) <= $rate) { $code = 0; $msg = 'success'; } else { $code = 1; $msg = 'busy'; } header('Content-type: application/json'); echo json_encode(['code' => $code, 'msg' => $msg, 'id' => $id, 'seed' => $seed,]); function sRandSeed() { $hash = md5(session_create_id()); $result = 0x003F; foreach (str_split($hash, 8) as $v) { $result ^= hexdec($v); } return $result & 0x7FFFFFFF; } 由于windows最大同时打开文件只能是512个,我这里限制最大并发数为500了,如果非windows可以适当增加此值,否则会报错,无法执行下去。由于高并发的时候,有可能http服务会报错,如果返回的值不是标准json串,设置此次请求为失效(code = -1),并统计各code的数量。 # -*- Coding: UTF-8 -*- import time import sys import getopt import asyncio from aiohttp import ClientSession import json import codecs sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach()) url = "http://192.168.0.200/cli/asynctest.php" tasks = [] result = {} async def run(cid=0, obj=None): global cols if obj is None: obj = asyncio.Semaphore(cols) async with obj: async with ClientSession() as session: async with session.post(url, data={"id": cid}) as response: try: text = await response.text() j = json.loads(text) except json.JSONDecodeError: if -1 not in result: result[-1] = 0 result[-1] += 1 else: if j["code"] not in result: result[j["code"]] = 0 result[j["code"]] += 1 # print(j) if __name__ == "__main__": nums = 10 cols = 500 if len(sys.argv) > 1: opts, args = getopt.getopt(sys.argv[1:], "hn:c:") for op, value in opts: if op == "-h": print("python " + sys.argv[0] + " -n 100 -c 500") sys.exit() elif op == "-n": nums = int(value) elif op == '-c': cols = int(value) loop = asyncio.get_event_loop() start_time = time.time() semaphore = asyncio.Semaphore(cols) tasks = [run(cid, semaphore) for cid in range(nums)] loop.run_until_complete(asyncio.wait(tasks)) loop.close() end_time = time.time() print(result) print("Loop Nums:", str(nums)) print("Start Time:", str(start_time)) print("End Time:", str(end_time)) print("Running Time:", str(end_time - start_time))
  10. 使用场景模拟,例如:登录过程中,有很多相关日志、积分或者某些活动参加部分解耦,将这些相关联模块采用观察者模式,用户登录时添加这些观察者,通知一次,观察者们会自动调用相关的方法处理。避免登录模块中掺杂过多的其他方面的代码。 /** * 事件产生类 * Class EventGenerator */ abstract class EventGenerator { private $ObServers = []; //增加观察者 public function add(ObServer $ObServer) { $this->ObServers[] = $ObServer; } //事件通知 public function notify($msg = '') { foreach ($this->ObServers as $ObServer) { $ObServer->update($msg); } } } /** * 观察者接口类 * Interface ObServer */ interface ObServer { public function update($event_info = null); } /** * 观察者1 */ class ObServer1 implements ObServer { public function update($event_info = null) { var_dump($event_info); echo "观察者1 收到执行通知 执行完毕!\n"; } } /** * 观察者1 */ class ObServer2 implements ObServer { public function update($event_info = null) { var_dump($event_info); echo "观察者2 收到执行通知 执行完毕!\n"; } } /** * 事件 * Class Event */ class Event extends EventGenerator { /** * 触发事件 */ public function trigger() { //通知观察者 $this->notify(mt_rand(1, 10)); } } //创建一个事件 $event = new Event(); //为事件增加旁观者 $event->add(new ObServer1()); $event->add(new ObServer2()); //执行事件 通知旁观者 $event->trigger(); sleep(1); $event->trigger();
  11. 继续学习: 痛苦的,连基本的数组操作也需要自己写过程,字符串操作之类也很麻烦,其他语言有大量的内置函数真的很好。如果没有一个好的封装库的话,肯定会很慢,真的! /** * 素数 */ private static void prime() { int num; System.out.print("请输入一个整数:"); try { Scanner sc = new Scanner(System.in); num = sc.nextInt(); if (num > 1) { boolean isPrime = true; for (int i = 2; i < Math.sqrt(num); i++) { if (num % i == 0) { isPrime = false; break; } } if (isPrime) { System.out.printf("%d 是素数\n", num); } else { System.out.printf("%d 不是素数\n", num); } } else { System.out.println("输入的数字必须大于1"); } } catch (Exception e) { System.out.println(e.toString()); } } /** * 水仙花数 */ private static void asphodel() { String str; int s1, s2, s3, count = 0; for (int i = 100; i < 1000; i++) { str = String.valueOf(i); s1 = Integer.parseInt(new String(new char[]{str.charAt(0)})); s2 = Integer.parseInt(new String(new char[]{str.charAt(1)})); s3 = Integer.parseInt(new String(new char[]{str.charAt(2)})); if (i == Math.pow(s1, 3) + Math.pow(s2, 3) + Math.pow(s3, 3)) { count ++; System.out.print(i + " "); } } System.out.printf("\n水仙花数共有 %d 个\n", count); } /** * 正则与时间 */ private static void regular() { String date; Date dt = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); date = format.format(dt); System.out.println(date); String p = "(\\d{4})-(\\d{2})-(\\d{2}) (\\d+):(\\d+):(\\d+)"; Pattern r = Pattern.compile(p); Matcher m = r.matcher(date); if (m.find()) { String[] ary = {}; for (int i = 0; i <= m.groupCount(); i++) { ary = pushArray(ary, m.group(i)); } Vardump.print(ary); } else { System.out.println("NO MATCH"); } } /** * 操蛋,连数组操作也要自己造轮子? * @param src * @param push * @return */ private static String[] pushArray(String[] src, String push) { String[] tempArray = new String[src.length + 1]; for (int i = 0;i < src.length; i++) { tempArray[i] = src[i]; } tempArray[src.length] = push; return tempArray; }
  12. 2019.04.13 学习内容: 1. Swap 变量返回问题 2. 字符串输入 3. 类似PHP中的魔法调用,用反射方式动态调用不同方法 import java.lang.reflect.*; import java.util.Scanner; import cn.lcfms.utils.*; public class Main { public static void main(String[] args) { String opt = ""; try { if (args.length > 0) { Vardump.print(args); opt = args[0].toLowerCase(); System.out.printf("Operate: %s \n", opt); } else { System.out.printf("Option is empty"); return; } } catch (Exception e) { System.out.println(e.toString()); } try { java.lang.Class[] empty_class = new java.lang.Class[]{}; java.lang.Object[] empty_object = new java.lang.Object[]{}; Method method = Main.class.getDeclaredMethod(opt, empty_class); method.setAccessible(true); method.invoke(null, empty_object); } catch (NoSuchMethodException e) { System.out.println(e.toString()); System.out.printf("Option '%s' is incorrect", opt); } catch (Exception e) { System.out.println(e.toString()); } } /** * 交换数值入口 */ private static void swap() { Integer a, b; a = 10; b = 20; System.out.printf("a = %d, b = %d\n", a, b); try { doSwap(a, b); } catch (Exception e) { System.out.println(e.toString()); } System.out.printf("a = %d, b = %d\n", a, b); } /** * 交换数值处理过程 * @param a * @param b * @throws Exception */ private static void doSwap(Integer a, Integer b) throws Exception { // 请在这里实现交换过程 int c = a; Integer cInteger = new Integer(c); Class<? extends Integer> aClass = a.getClass(); Field avalue = aClass.getDeclaredField("value"); avalue.setAccessible(true); avalue.set(a, b); Class<? extends Integer> bClass = b.getClass(); Field bvalue = bClass.getDeclaredField("value"); bvalue.setAccessible(true); bvalue.set(b, cInteger); } /** * 输入字符串 */ private static void input() { System.out.print("请输入你的字符串:"); Scanner s = new Scanner(System.in); String val = s.nextLine(); String outstr = "你输入的字符串为空"; if (val.length() > 0) { outstr = String.format("你输入的字符串为:%s,长度为:%d", val, val.length()); } System.out.println(outstr); } private static void rightnum() { System.out.println("run rightnum"); } }
  13. 这个问题原来是C++的版本,目前在学习Java中,问题就用Java描述吧。 看代码:将变量a 和 b的值交换后输出。当然实际情况下,肯定不允许这样的情况发生,如果可以传指参的话,直接使用指参就可以了,比如PHP里可以直接使用 function doSwap(&$a, &$b) {...} 就可以了,我查了一下JAVA是没有指参的,所以不能这么处理。代码中还有部分不是太理解,逻辑是理解了,等后续再看吧。 public class Main { public static void main(String[] args) { Integer a, b; a = 1; b = 2; System.out.printf("a = %d, b = %d\n", a, b); try { doSwap(a, b); } catch (Exception e) { System.out.println(e.toString()); } System.out.printf("a = %d, b = %d\n", a, b); } private static void doSwap(Integer a, Integer b) throws Exception { // 请在这里实现交换过程 } } 我这里先给出一个PHP版本的解法,不使用Class的情况是可以实现的,如果限制在Class环境中,暂时还没想到实现方式,PHP中没有内存操作的概。: $a = 10; $b = 20; echo "a:{$a} b:{$b}\n"; doSwap($a, $b); echo "a:{$a} b:{$b}\n"; function doSwap($a, $b) { /* 请实现交换两个变量 预期结果: a:1 b:2 a:2 b:1 */ global $a, $b; $c = $a; $a = $b; $b = $c; } 看一下JAVA的实现方式,你没看错,就这个操作需要这么长的代码: import java.lang.reflect.Field; public class Main { public static void main(String[] args) { Integer a, b; a = 1; b = 2; System.out.printf("a = %d, b = %d\n", a, b); try { doSwap(a, b); } catch (Exception e) { System.out.println(e.toString()); } System.out.printf("a = %d, b = %d\n", a, b); } private static void doSwap(Integer a, Integer b) throws java.lang.Exception { // 请在这里实现交换过程 int c = a; Integer cInteger = new Integer(c); Class<? extends Integer> aClass = a.getClass(); Field avalue = aClass.getDeclaredField("value"); avalue.setAccessible(true); avalue.set(a, b); Class<? extends Integer> bClass = b.getClass(); Field bvalue = bClass.getDeclaredField("value"); bvalue.setAccessible(true); bvalue.set(b, cInteger); } }
  14. 从PHP5.3开始phar模块已经默认编译在里面了,直接使用就可以了。 使用前需要把php.ini中的只读权限去掉, [Phar] ; http://php.net/phar.readonly ;phar.readonly = On phar.readonly = Off 然后新建一个PHP文件 if (class_exists('\Phar')) { $phar = new \Phar('demo.phar', 0, 'demo.phar'); $phar->buildFromDirectory(__DIR__ . '/a1/'); $phar->setStub($phar->createDefaultStub('demo.php', 'index.php')); $phar->compressFiles(Phar::GZ); } else { exit('no Phar module'); } 然后运行一下这个新的文件,指定目录下的所有文件(包括其他资源文件,是所有文件)都会被打包到phar文件中,运行时这些文件都可以直接被PHP代码调用 。如果没有错误的话,当前目录会产生一个指定的phar文件。然后就可以随便把它放到哪个目录下调用了。
  15. 在linux环境下,可以直接使用 composer install这样的操作,但是在windows里不能这么调用,必须使用 x:\php\php.exe x:\...\composer.phar install这样的操作方式,是不是感觉到太麻烦了?用这个脚本吧。 把这个文件composer.bat和composer.phar放在同一个目录下,然后设置一下自动搜索PATH,包含PHP的路径以及新增的这个目录(可以同时放到同一个目录下)。 @echo off php.exe %~dp0composer.phar %1 %2 %3 %4 %5 %6 %7 %8 %9 然后你就可以在命令行下的任何目录直接调用composer install之类的操作了。
  16. $where 使用示例: db.test.find({ "detail.test": {$nin:[null],$exists: true}, $where: function() { var ret = false; for(var curr in this.detail.test) { //print(this.detail.test[curr].nums); if (this.detail.test[curr].nums >= 100) { ret = true; break; } } return ret; } }); 以上仅为演示使用$where的方式,上面的功能推荐用子元素匹配处理,上面的效率太低了 db.test.find({ 'detail.test': { '$elemMatch': {'nums': {'$gte': 100}} }, } 查看print输出日志需要到服务器上直接查看日志,不推荐打开日志 tail -f /var/db/mongodb/mongod.log
  17. 试想一个场景: 自己Push了一个Commit后,后续有其他人也相继Push了相应的代码到Git库里,结果你发现自己的代码里的敏感信息,这时候怎么处理? 以下是测试过的处理方式: 进入git bash界面,到指定目录 git log 找到自己提交的前一个commit的hash值 git rebase -i hash 把自己的 pick own_hash 改成 drop own_hash 保存退出 git push origin HEAD --force 然后就一切正常啦 git log 查看一下
  1. Load more activity
×
×
  • Create New...