CentOS搭建Java Web环境

题外话:首先痛斥国内“技术”博客圈的拿来风。用汉语搜索到的基本上都是重复的内容,如果最开始的人写错了,那么所有人一起错。或者明明第一篇文章是五年前写出来的,技术环境已经都废弃了,结果到现在还有人转。连最基本的验证都不做。

下面进入正题:
全世界大部分的网站都是PHP做成的。所以各大VPS供应商都提供了一键PHP安装环境。或者各个社区也提供了方便的一键PHP环境安装脚本。相比之下,JAVA就没这么好运了。

之前买了一个搬瓦工的VPS想部署JAVA代码。结果一直被误导。今日虽然已经深夜,仍然打算将此过程记下来。
记住,做成时间2017/01/15。时间太长之后就别参照了。一切都在变。

下面是步骤。

  1. 进入搬瓦工后台,选择系统,CentOS7 64位。 等待重装完毕。
  2. 用Putty进入服务器后台。SSH的端口和密码在重装系统时会自动提供。
  3. 首先安装Java,使用 yum install java即可。一路y,默认安装的应该是OpenJDK(Oracle在Do evil)。
  4. 然后执行java -version查看java版本,以此确认java安装是否正常。现在为OpenJDK1.8。
  5. 之后安装Tomcat。执行yum install tomcat tomcat-webapps tomcat-admin-webapps。网上文章最坑人的地方在于,都是写Tomcat6。其实早就不带版本号了。
  6. 然后一路Y。
  7. 去etc/tomcat路径下面去修改各配置文件。比如Server.xml,tomcat-users.xml,web.xml等。
  8. webapps路径会在/var/lib/tomcat/webapps。根目录是ROOT。
  9. 之后执行service tomcat start会启动服务。
  10. 执行service tomcat stop停止服务。
  11. 执行service tomcat restart重启服务。

//TODO 设置服务自启动。
//TODO 补图。

// Update 1

补充MacOS下使用终端连接SSH的方法。
网上的教程一般指告诉到了使用ssh [userName]@[Host]为止,但是,正常的服务器是不会使用默认端口号的。
那么怎么指定端口号呢,完整版命令是这样的ssh [UserName]:@[Host] -p [Port]

// Update 2

在Win10的最新版本里,可以安装Beta版的Ubuntu Linux,这样不需要Putty等工具,直接在Win10里使用SSH命令了。
具体命令和MacOS里是一样的。

Javascript如何生成Json

最近遇到个想复杂了的问题,就是如何用Javascript生成Json。
因为之前用的都是高级语言,已经封装好了数据结构或者类,直接赋值就好了。
之前想模拟前端向后台呼叫接口,需要POST方式传递JSON进来。然后就懵住了。

咦?我应该不用傻傻的拼接字符串吧。然后开始了脑洞。

脑洞第一版,模仿Salesforce制作List的方式

var dataArray = [];
var data = {};
data["id"] = "0010000000ABCD";
data["name"] = "Account";
dataArray.push(data);
var jsonString = JSON.stringify(dataArray);
var output = eval("(" + jsonString + ")");

感觉很怪。

脑洞第二版,用Javascript的类概念

var Account = new Object();
Account.Id = "0010000000ABCD";
Account.Name = "Account";
var output = JSON.stringify(Account);

感觉好多了,但感觉还是不够简单。毕竟Json是Javascirpt原生支持的啊。

然后查了半天,发现自己真的想复杂了

var output = {Id:"0010000000ABCD", Name:"Account"};

// Update 1
补充一下如何传两条数据

var output = [{Id:"0010000000ABCD", Name:"Account1"}, {Id:"0010000000ABCE", Name:"Account2"}];

Google的人工智能

在围棋领域,Google的Alpha GO与Master已经打败了光荣的人类棋手们。很了不起。

不同与早先的下棋智能程序,Google的AI并没有使用遍历算法。早先红白机上的中国象棋之类的,不过是计算了所有的可能之后回应。围棋的变化太多,计算量超乎目前计算机的承受能力。

Google使用了深度学习系统Tensorflow。(Python,又是Python。。。这个世界要被Python占领了吗)

这里是来自极客学院的翻译教程

关于随机数

在随机数这个问题上,一般程序员总是要经历下面的过程:

  1. 压根没有随机数的概念,想使用随机数的念头往往出于想每次执行自己辛辛苦苦写的小程序时可以有不一样的结果。
  2. 发现有个函数/方法是专门用来生成随机数的,试了一下,确实挺随机的。
  3. 兴高采烈的在自己的小程序里使用了这个函数/方法。结果发现每次结果其实还是一样的(C的话)
  4. 经历了千万次google才发现原来自己没加种子,只有不同的种子才会产生不同的随机数。往往种子都是使用一个恒定在变的东西——–时间。
  5. 当程序被高频访问的时候,问题又来了————-时间在计算里有最小单位,所以高频访问中临近访问的随机数是一样的。
  6. 又学会了一种叫随机数仓库的东西,来应对突然的高频访问。不断的往随机数队列里填充随机数,然后每个访问都是去随机数队列里去取。
  7. 然后,突然有一天,有人告诉你,这些不是随机数,最多只能称为伪随机数。

那么问题来了,什么是伪随机数,维基百科上的解释

伪随机性英语:Pseudorandomness)是指一个过程似乎是随机的,但实际上并不是。例如伪随机数(或称伪乱数),是使用一个确定性的算法计算出来的似乎是随机的数序,因此伪随机数实际上并不随机。在计算伪随机数时假如使用的开始值不变的话,那么伪随机数的数序也不变。伪随机数的随机性可以用它的统计特性来衡量,其主要特征是每个数出现的可能性和它出现时与数序中其它数的关系。伪随机数的优点是它的计算比较简单,而且只使用少数数值很难推算出计算它的算法。一般人们使用一个假的随机数,比如电脑上的时间作为计算伪随机数的开始值。

所以严格来讲,计算机生成的随机数并不是严格意义上的随机。那么我们如果想要真正的随机数怎么办呢。

有一个简便的方法,调用http://random.org的接口。

调用示例等参考此链接

 

Salesforce中的Apex Class Security设定问题

在我以往的印象中,给Profile设定VF和Apex Class的访问权限,都是需要什么就加什么。

比如新建了一个VF叫PageA, 又新建了一个Controller叫ControllerA,然后新建了一个被Controller调用的工具类ToolA。
那么,在此Profile中,PageA,ControllerA和ToolA通通都要加到Profile的访问权限里。

如果只添加了PageA,按理说应该是无法正常执行才对。

但通过实践,发现就算只添加了PageA的权限,整个功能仍然能正常运行。与之前的印象不符。

所以去查了文档,发现官方给出的解释是这样的:

Permission for an Apex class is checked only at the top level. For example, if class A calls class B, and a user profile has access only to class A but not class B, the user can still execute the code in class A. Likewise, if a Visualforce page uses a custom component with an associated controller, security is only checked for the controller associated with the page. The controller associated with the custom component executes regardless of permissions.

就是说如果代码之间存在着依赖链,那么权限判断中,只关注最顶层的那个代码。按照这个逻辑下来,只要拥有了PageA的权限,因为PageA与ControllerA的依赖关系,就自动获取了ControllerA的访问权限,同理ToolA。

知其然,不知其所以然还是不对的。

Javascript的KeyCode

在前端开发中,经常使用onkeypress,onkeydown等event来做快捷键。
我之前就是打算使用“;”来做快捷键功能。
使用了如下代码

document.onkeydown = function(e) {
    e = e || window.event;
    var kcode = e.which || e.keyCode;
	if(String.fromCharCode(kcode) == ";") {
              // TODO Place your code here.
	}
};

结果。。。只有在Firefox好用,Chrome和IE都阵亡了。
我并没有做任何的浏览器判断,怎么会自动按浏览器区分功能呢?

原来,对于event的keycode,大部分的按键的keycode值在所有浏览器中都是一致的。
但是,有一小撮按键。。。。很不幸就有我选中的的“;”,在firefox和Chrome中是不一致的。
具体列表参照http://www.javascripter.net/faq/keycodes.htm

Apache与Nginx

之前的服务器都是随大流使用的Apache,后来在新的备份服务器上美滋滋的想着尝试一下Nginx。
结果悲剧了。常用几个开源应用的.htaccess都是默认自带Apache语法的。尝试了一下网上的翻译器,并没有什么卵用。
小众者必然会死。。

// update

经过艰苦卓绝的训练。
技能【反向代理某搜索引擎】 Get。
技能【用Nginx进行负载平衡】 Get。

Salesforce如何取得Guest User的Debug Log

// Update4 2018/04/10

Salesforce这次不仅吃书。。。连设定都吃回去了。。。
这篇文章不用看了,以后再也不用设Cookie了。一切又回到了最初的样子。
官方文档

从Winter’17开始,Guest User的Debug Log不再能通过正常渠道直接获取了。这给我们做Wechat集成的小伙伴们造成了很大的困扰。
虽然说官方文档中,介绍了在Chrome下使用插件添加Cookie的方法来激活Guest User的Debug log,但微信里是没法修改Cookie的。
不过官方提到了可以通过各种代码添加Cookie的Sample Code,尤其是Javascript,可以放到被访问的页面上。
代码只有简简单单的一句

document.cookie ="debug_logs=debug_logs;domain=.force.com";

在修改了Page之后,兴冲冲的打开了微信进行测试,发现并没有卵用。
然后切回浏览器,通过浏览器访问发现,这段Js代码加入的Cookie值与我之前用插件添加进去的值并完全不一致。
不一致的属性是“Path”,由于我的Salesforce Site是设定了Path的,所以Js代码生成的Cookie的Path也跟着变成了我设定的Path。而我用插件加入的Cookie的Path属性默认为“/”。
好,那么我们修改一下这句Js

document.cookie ="debug_logs=debug_logs;domain=.force.com;path=/";

修改完之后再试,问题解决,Debug Log乖乖出来了。
打完收工。

// Update 1

微信内置浏览器是可以使用Cookie的,不过要慎重,因为微信的内置浏览器对于Cookie的处理策略与桌面浏览器不是很一致,并且每个版本都有变动。所以不应该过度依赖于微信内置浏览器的Cookie。

// Update 2

微信的内置浏览器为X5内核,所以行为和渲染等都与Webkit内核有出入。慎重!!
另,Spring’17 开始进入倒计时的时候,发现前文提到的官方文档不见了!!但是此方法仍然有效!!到底发生了什么!!

// Update 3
对于Salesforce官方不断吃书的行为表示不满与谴责(Knowledge文章被取消了)。
然并卵,已经不是第一次吃书了,所以想参考官方文档的同学看这里

关于Lorem Ipsum

对于前端开发人员来讲,涉及到内容填充或者排版的时候,最常用的就是Lorem Ipsum文本。

标准文本内容

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

// Update 1

在Word里如果输入=Rand()会随机的生成一段文本给你当填充物,或者输入=lorem(),则是填充Lorem Ipsum。当然这两个函数都贴心的设置了可选参数,可以选择长度与段落数量等。

Salesforce不登录调用Webservice的方法

Salesforce中提供了WebService的调用方式,在系统内部使用的时候,比如通过VF上的JS,或者通过标准页面上的按钮进行调用,可以方便的实现很多功能。
同时,Salesforce中的WebService可以也以rest方式提供给第三方系统进行可控的数据交互。
但是,鉴于Salesforce的License价格虚高,并且有些第三方,例如微信后台是无法进行身份认证的时候,通过public site开放WebSerivce用rest方式调用就非常有必要了。

首先,要在Webservice的首行添加@RestResource(urlMapping=’/{your name}/*’)
之后定义好@HttpGet方法或者@HttpPost方法。

将WebService类及相关类加到Site的可访问Apex Class列表里。
准备完毕后确认site有没有设定Path。
如果是sandbox的话
https://{prefix}.{sandbox instance Name}.force.com/{path}/services/apexrest/{Name Space}/{webservice urlMapping Name}/{your paramater}
如果是Production的话,
https://{prefix}.secure.force.com/{path}/services/apexrest/{Name Space}/{webservice urlMapping Name}/{your paramater}

尤其是Name Space,曾经难倒无数英雄汉。