我们程序员的属性 [转]

俗话说:三句不离本行,对于程序员这个可爱的群体来说也是一样。

他们在编程中养成的一些思维方法会不自觉地在日常生活中表现出来。

我们这里总结了程序员日常生活中经常表现出来的8个编程思维。

你有没有同感呢?

0.在正常交流中掺杂编程规范和语法

职业原因:编程语言都有自己特定的语法,程序员在开发者都要遵守这些。

当然,还有一些约定俗成的编程规范,如代码缩进(是缩进4个字符还是8个字符)、注释风格,采用骆驼式(CamelCase)或帕斯卡式(Pascal)来命名变量或函数等等。

日常行为:这些编程习惯可能就会影响到程序员的日常文档书写习惯,比如写邮件时会用分号来结束一行内容等。

例子:

iWriteInCamelCaseEveryNowAndThenItAnnoysMySisterWhoReadsMyEmail.(小骆驼式拼写法)
IF you have tea I’ll have it ELSE I’ll just take wate.(利用了IF-ELSE判断语句)

1.真实生活中习惯讲操作快捷键

职业原因:程序员玩快捷键操作软件应该很熟练了,一般来说,Ctrl-C表示复制、Ctrl-V表示粘贴(对特定编辑器如Vi、Emacs来说会有不同)。

日常行为:这些快捷键有时在程序员的行为和话语中表现的很常见,这也会在一些场合引起尴尬。

例子:

“Mentally trying to Ctrl-Z on things I just said.(Ctrl-z表示撤消,这句话意思是我收回我刚才说的话)
In life there is no undo.(生活中没有撤消)

2.从0开始计数

职业原因:大多数编程语言中的“数组”初始值都是从0开始而不是1。

日常行为:这种约定使得程序员经常在生活中数数都是从0开始,没有编程背景的人们很难理解这种计数方式,如果你的程序员朋友祝愿你在3千米长跑中获得第0名,你就偷着乐吧。

例子:

– How many beers are left?(啤酒还剩多少杯?)
– Zero, one, two, three… We have four left!(0,1,2,3,……我们还有4杯呢~)

3.生活方式不健康

职业原因:程序员写起程序来有时一坐就是大半天,眼镜不离电脑屏幕,甚至在灵感爆发时熬夜。
日常行为:作息无规律,锻炼不足,与外界接触过少。

例子:
Eating lunch at 3pm and going to bed at 3am.(下午3点吃饭,凌晨3点睡觉)
Lack of exercise -> Eating too much -> unhealthy life style.(缺乏锻炼->吃得过多->生活方式不健康)

4.试图优化任何事情

职业原因:软件开发者会不断地优化自己的代码,让它越来越快、越来越高效。常用的方法有多线程处理任务、代码复用等,并在任何有可能自动化执行的情况下使其自动化。

日常行为:会尝试优化真实生活中的事情,尽量省力、高效,往往会被认为太懒惰,比如脏衣服经常堆到一定规模,实在没有可穿的了才去清洗(往往一次全部清洗完)。

例子:
don’t solve a problem until you absolutely, positively have to.(不到万不得已,不解决问题)

5.过于强迫症、完美主义

职业原因:程序中一般不能使用模糊语义,因为计算机不理解“差不多”,“基本”。程序中即使有一点小错误,也会导致程序编译不过、运行不起来。

日常行为:程序员也经常是过于认真,不放过任何小细节,“打破沙锅问到底”,这有时会给周围的人造成压力。

例子:
Requesting clear spec for favors and errands. ‘Wait what do you mean by ‘some eggs’? What is the lower and upper bound?'”(老婆让去买些鸡蛋,会追问到底买几个啊?)

6.希望人们都和电脑一样循规蹈矩

职业原因:计算机会按照程序设定的方式运行,运行出错,那就是程序出Bug了。

日常行为:程序员有时会忽略人们是和电脑不一样的,人不可能完全按照逻辑和理性来做事,更多的是“跟着感觉走”。

例子:
Having to explain what a logical fallacy is, first, everytime someone says something completely wrong gets frustrating fast.(经常去解释逻辑上存在的错误,如果人们否定整个事情则很容易感到沮丧)

7.总是想到2的乘方

职业原因:计算机存储信息的基本单位是bit(比特)。二进制系统中,每个0或1就是一个bit。

日常行为:常常不以10进制而是以2进制进行计算。一些平常的日子在程序员眼里也变得很神奇,如程序员日就是每年的第256天(2^8),也有人推荐将每年的10月24日作为程序员日(2^10)。

例子:
Everything has to be in powers of 2.(一切皆为2的乘方)
Imagine you have 1,000 bucks; or better a round number—imagine you have 1,024 bucks.(假设你有1000块钱,最好这样说,假设你有1024块钱)

好啦,总结完毕了。

如果你有孩子,还会让他去当程序员么?

“我以后绝对不会让我的儿子也当程序员的。”三十二岁的程序猿老张心酸而又坚定的说。

“嗯,但是,”路人甲一针见血的指出了一个问题:“你有老婆吗?没有老婆怎么可能有儿子呢?”

老张:“……你大爷的!我的心好痛!”

注定孤独一生?

程序员A和程序员B的对话。

 

程序员A说:昨晚帮个美女装路由器,装到12点都没装好,美女对我说:“装不好就别装了,我们做点其他事情把!”我听了,顿时怒火就上来了,你他妈不是在考验我么?然后我快速的把路由器装好就回去睡觉了。

程序员B说:你做的对,昨晚我和一个女同事出差住旅馆,旅馆只有一张床了,我打算睡沙发,女同事对我说:“你跟我一起睡吧,不过不能做什么坏事情哦!”我听了,顿时怒火就上来了,你他妈这不是怀疑哥的人品么?然后我硬是在沙发睡了一晚。

简单说就是:“智商高 情商低?”

是呀,没事。就爱怼老板。

老板:汉字中,凡带三点水的,一定都有水,比如,江,河,湖,海……

程序猿:沙漠

老板:滚!

情商低的表现。

一个程序员骑着一个很漂亮的自行车到了公司,另一个程序员看到了他,问 到,“你是从哪搞到的这么漂亮的车的?”
骑车的那个程序员说, “我刚从那儿过来, 有一个秀丽的姑娘骑着这个车过来, 并停在我跟前,把衣裳全脱了,然后对我说,‘你想要什么都可以’”。
另一个程序员马上说到, “你必定做了一个正确的选择, 因为那姑娘的衣裳你并不一定穿得了”。

宅也是我们的属性表现啊。

“嘿,兄弟,犯什么事进来的?”

“入室偷窃。”

“咋啦,被人赃俱获?”

“屁!货还没到手呢,刚进屋就冲出两宅男,亏我还观察那屋三天!”

宅-没朋友-更宅-更没朋友的死循环。

 

【彩蛋】

小小编辑送给乱弹精英和程序员的礼物。

请戳(这里

 

【小树的世界之旅】

1、三天前,家住南京大厂某小区的盛先生带爱犬外出,结果爱犬被小轿车撞伤,车主驾车溜了。受伤的狗儿“盛怒之下”,将盛先生及妻子咬伤。夫妻被狗咬伤,又找不到肇事者,气愤的盛先生拨打12345政府热线求助。南京化工园公安分局扬子派出所民警接到工单后,通过监控找到了肇事车辆及车主,虽然车主否认,但车前的裂痕及粘着的狗毛“作证”,车主不得不承认这一事故。

南京真是个动物乐园。

2、10月12日,山东潍坊昌乐交警的一次查酒驾行动中,一名执勤交警被喝了酒的司机用车顶着狂奔了10分钟,最后从车前盖滚落下来,差点要了交警的命。司机行为令人发指,警方迅速展开抓捕。第二天早上7点45分,两名嫌疑人最终落网。经审讯,驾驶轿车的男子马某,和副驾驶位置男子徐某是朋友。为了庆祝自己入职,俩人中午就多喝了几杯。马某、徐某两人口口声声说着心里害怕,可是当天晚上两人醒酒后,并没有立即投案自首,而是一起再赴酒局。

刚入职就要去牢里上班了

3、10月17日晚,马先生朋友的父亲过生日,一家人前往位于宝塔区的延安中益嘉汇酒店吃饭。“由于桌上的女士较多,就说喝啤酒,刚好车上放有两箱啤酒,我就搬一箱。”马先生说,当时带啤酒进去时,服务员并没告知要收“开瓶费”,等吃完饭结账时发现,总共花了1330元,其中“服务费”就有100元。8日下午他已将此事反映给延安市宝塔区消费者协会,消协已经立案调查。

干脆,你用枪指着每一位进店的掏他钱包就是了。

 

【小树的角色Play剧场】

(本期剧本导演: @ 树和伊文 ,友情客串:@ 唐力个糖

看CCTV的普法栏目剧

一个貌似是坏女人对着男主角脱掉浴袍

镜头还马上切到坏女人的后背

没错露背了,虽然打了点朦胧的效果

然后男主角瞄了一眼,慢慢脱去西装并把身子靠过去

我勒个擦后面就是床啊心想央视这是要逆天了

男主角突然把脱去的外套披在坏女人身上

说:我警告你再有下次,滚

然后就走了,就走了

@ 唐力个糖 不禁叹息了一声,突然发现原来@ 唐力个糖 是和妈妈一起看啊

妈妈质问@ 唐力个糖 :“你唉什么?”

早已看惯云淡风轻的@ 唐力个糖 马上说道:

堂堂中央电视台居然要拍出这么俗的东西真是无话可说了

然后@ 唐力个糖 还不屑地摇摇头走开。

 

情绪不好?

关注同学们的生理心理健康

请进入大家喜闻乐见的【小树医生心理生理医务室】

“如何让‘二狗’这个外号有不一样的感觉?”

“犬次郎。 ”

“那‘狗蛋’呢?”

“犬丸。”

—- ———分割线————– ——

晚上稀里糊涂的做了个很奇怪的梦,

梦见自己有了个小女儿,

哄了大半夜,累得要死。

最冤的是,醒了之后,死活想不起来孩子她妈是谁。

—- ———分割线————– ——

小时候家里很穷,每当看见邻居家的狗吃的比我还好,

我就暗下决心,以后一定要好好学习、努力工作,

争取给自己找到一个有钱的主人。

—- ———分割线————– ——

无她,唯手熟尔。

 

【看片】

当你注视深渊的时候,深渊也在注视着你。

手机党少年们想看视频,请使劲儿戳(这里)。

 

Json Web Token 详解 [转]

Understanding JWT

JSON Web Tokens (JWT) are a standard way of representing security claims between the add-on and the Atlassian host product. A JWT token is simply a signed JSON object which contains information which enables the receiver to authenticate the sender of the request.

Table of contents

Structure of a JWT token

A JWT token looks like this:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEzODY4OTkxMzEsImlzcyI6ImppcmE6MTU0ODk1OTUiLCJxc2giOiI4MDYzZmY0Y2ExZTQxZGY3YmM5MGM4YWI2ZDBmNjIwN2Q0OTFjZjZkYWQ3YzY2ZWE3OTdiNDYxNGI3MTkyMmU5IiwiaWF0IjoxMzg2ODk4OTUxfQ.uKqU9dTB6gKwG6jQCuXYAiMNdfNRw98Hw_IWuA5MaMo

Once you understand the format, it’s actually pretty simple:

<base64url-encoded header>.<base64url-encoded claims>.<base64url-encoded signature>

In other words:

  • You create a header object, with the JSON format. Then you encode it in base64url
  • You create a claims object, with the JSON format. Then you encode it in base64url
  • You create a signature for the URI (we’ll get into that later). Then you encode it in base64url
  • You concatenate the three items, with the “.” separator

You shouldn’t actually have to do this manually, as there are libraries available in most languages, as we describe in the JWT libraries section. However it is important you understand the fields in the JSON header and claims objects described in the next sections:

Header

The header object declares the type of the encoded object and the algorithm used for the cryptographic signature. Atlassian Connect always uses the same values for these. The typ property will be “JWT” and the alg property will be “HS256”.

{
“typ”:”JWT”,
“alg”:”HS256″
}
Attribute Type Description
“typ” String Type for the token, defaulted to “JWT”. Specifies that this is a JWT token
“alg” (mandatory) String Algorithm. specifies the algorithm used to sign the token. In atlassian-connect version 1.0 we support the HMAC SHA-256 algorithm, which the JWT specificationidentifies using the string “HS256”.

Important

Your JWT library or implementation should discard any tokens which specify alg: none as this can provide a bypass of the token verification.

Claims

The claims object contains security information about the message you’re transmitting. The attributes of this object provide information to ensure the authenticity of the claim. The information includes the issuer, when the token was issued, when the token will expire, and other contextual information, described below.

{
“iss”: “jira:1314039”,
“iat”: 1300819370,
“exp”: 1300819380,
“qsh”: “8063ff4ca1e41df7bc90c8ab6d0f6207d491cf6dad7c66ea797b4614b71922e9”,
“sub”: “batman”,
“context”: {
“user”: {
“userKey”: “batman”,
“username”: “bwayne”,
“displayName”: “Bruce Wayne”
}
}
}
Attribute Type Description
iss(mandatory) String the issuer of the claim. Connect uses it to identify the application making the call. for example:

  • If the Atlassian product is the calling application: contains the unique identifier of the tenant. This is the clientKey that you receive in theinstalled callback. You should reject unrecognised issuers.
  • If the add-on is the calling application: the add-on key specified in the add-on descriptor
iat(mandatory) Long Issued-at time. Contains the UTC Unix time at which this token was issued. There are no hard requirements around this claim but it does not make sense for it to be significantly in the future. Also, significantly old issued-at times may indicate the replay of suspiciously old tokens.
exp(mandatory) Long Expiration time. It contains the UTC Unix time after which you should no longer accept this token. It should be after the issued-at time.
qsh(mandatory) String query string hash. A custom Atlassian claim that prevents URL tampering.
sub(optional) String The subject of this token. This is the user associated with the relevant action, and may not be present if there is no logged in user.
aud(optional) String or String[] The audience(s) of this token. For REST API calls from an add-on to a product, the audience claim can be used to disambiguate the intended recipients. This attribute is not used for JIRA and Confluence at the moment, but will become mandatory when making REST calls from an add-on to e.g. the bitbucket.org domain.
context(optional) Object The context claim is an extension added by Atlassian Connect which may contain useful context for outbound requests (from the product to your add-on). The current user (the same user in the sub claim) is added to the context. This contains the userKey, username and display name for the subject.

"context": {
    "user": {
        "userKey": "batman",
        "username": "bwayne",
        "displayName": "Bruce Wayne"
    }
}
  • userKey — the primary key of the user. Anytime you want to store a reference to a user in long term storage (eg a database or index) you should use the key because it can never change. The user key should never be displayed to the user as it may be a non human readable value.
  • username — a unique secondary key, but should not be stored in long-term storage because it can change over time. This is the value that the user logs into the application with, and may be displayed to the user.
  • displayName — the user’s name.

You should use a little leeway when processing time-based claims, as clocks may drift apart. The JWT specification suggests no more than a few minutes. Judicious use of the time-based claims allows for replays within a limited window. This can be useful when all or part of a page is refreshed or when it is valid for a user to repeatedly perform identical actions (e.g. clicking the same button).

Signature

The signature of the token is a combination of a hashing algorithm combined with the header and claims sections of the token. This provides a way to verify that the claims and headers haven’t been been compromised during transmission. The signature will also detect if a different secret is used for signing. In the JWT spec, there are multiple algorithms you can use to create the signature, but Atlassian Connect uses the HMAC SHA-256 algorithm. If the JWT token has no specified algorithm, you should discard that token as they’re not able to be signature verified.

JWT libraries

Most modern languages have JWT libraries available. We recommend you use one of these libraries (or other JWT-compatible libraries) before trying to hand-craft the JWT token.

Language Library
Java atlassian-jwt and jsontoken
Python pyjwt
Node.js node-jwt-simple
Ruby ruby-jwt
PHP firebase php-jwt and luciferous jwt
.NET jwt
Haskell haskell-jwt

The JWT decoder is a handy web based decoder for Atlassian Connect JWT tokens.

Creating a JWT token

Here is an example of creating a JWT token, in Java, using atlassian-jwt and nimbus-jwt (last tested with atlassian-jwt version 1.5.3 and nimbus-jwt version 2.16):

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import com.atlassian.jwt.*;
import com.atlassian.jwt.core.writer.*;
import com.atlassian.jwt.httpclient.CanonicalHttpUriRequest;
import com.atlassian.jwt.writer.JwtJsonBuilder;
import com.atlassian.jwt.writer.JwtWriterFactory;public class JWTSample {

public String createUriWithJwt()
throws UnsupportedEncodingException, NoSuchAlgorithmException {
long issuedAt = System.currentTimeMillis() / 1000L;
long expiresAt = issuedAt + 180L;
String key = “atlassian-connect-addon”; //the key from the add-on descriptor
String sharedSecret = “…”;    //the sharedsecret key received
//during the add-on installation handshake
String method = “GET”;
String baseUrl = “https://<my-dev-environment>.atlassian.net/”;
String contextPath = “/”;
String apiPath = “/rest/api/latest/serverInfo”;

JwtJsonBuilder jwtBuilder = new JsonSmartJwtJsonBuilder()
.issuedAt(issuedAt)
.expirationTime(expiresAt)
.issuer(key);

CanonicalHttpUriRequest canonical = new CanonicalHttpUriRequest(method,
apiPath, contextPath, new HashMap());
JwtClaimsBuilder.appendHttpRequestClaims(jwtBuilder, canonical);

JwtWriterFactory jwtWriterFactory = new NimbusJwtWriterFactory();
String jwtbuilt = jwtBuilder.build();
String jwtToken = jwtWriterFactory.macSigningWriter(SigningAlgorithm.HS256,
sharedSecret).jsonToJwt(jwtbuilt);

String apiUrl = baseUrl + apiPath + “?jwt=” + jwtToken;
return apiUrl;
}
}

Decoding and verifying a JWT token

Here is a minimal example of decoding and verifying a JWT token, in Java, using atlassian-jwt and nimbus-jwt (last tested with atlassian-jwt version 1.5.3 and nimbus-jwt version 2.16).

NOTE: This example does not include any error handling. See AbstractJwtAuthenticator from atlassian-jwt for recommendations of how to handle the different error cases.

import com.atlassian.jwt.*;
import com.atlassian.jwt.core.http.JavaxJwtRequestExtractor;
import com.atlassian.jwt.core.reader.*;
import com.atlassian.jwt.exception.*;
import com.atlassian.jwt.reader.*;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;

public class JWTVerificationSample {

public Jwt verifyRequest(HttpServletRequest request,
JwtIssuerValidator issuerValidator,
JwtIssuerSharedSecretService issuerSharedSecretService)
throws UnsupportedEncodingException, NoSuchAlgorithmException,
JwtVerificationException, JwtIssuerLacksSharedSecretException,
JwtUnknownIssuerException, JwtParseException {
JwtReaderFactory jwtReaderFactory = new NimbusJwtReaderFactory(
issuerValidator, issuerSharedSecretService);
JavaxJwtRequestExtractor jwtRequestExtractor = new JavaxJwtRequestExtractor();
CanonicalHttpRequest canonicalHttpRequest
= jwtRequestExtractor.getCanonicalHttpRequest(request);
Map requiredClaims = JwtClaimVerifiersBuilder.build(canonicalHttpRequest);
String jwt = jwtRequestExtractor.extractJwt(request);
return jwtReaderFactory.getReader(jwt).readAndVerify(jwt, requiredClaims);
}
}

Decoding a JWT token

Decoding the JWT token reverses the steps followed during the creation of the token, to extract the header, claims and signature. Here is an example in Java:

String jwtToken = …;//e.g. extracted from the request
String[] base64UrlEncodedSegments = jwtToken.split(‘.’);
String base64UrlEncodedHeader = base64UrlEncodedSegments[0];
String base64UrlEncodedClaims = base64UrlEncodedSegments[1];
String signature = base64UrlEncodedSegments[2];
String header = base64Urldecode(base64UrlEncodedHeader);
String claims = base64Urldecode(base64UrlEncodedClaims);

This gives us the following:

Header:

{
“alg”: “HS256”,
“typ”: “JWT”
}

Claims:

 {
“iss”: “jira:15489595”,
“iat”: 1386898951,
“qsh”: “8063ff4ca1e41df7bc90c8ab6d0f6207d491cf6dad7c66ea797b4614b71922e9”,
“exp”:
}

Signature:

uKqU9dTB6gKwG6jQCuXYAiMNdfNRw98Hw_IWuA5MaMo

Verifying a JWT token

JWT libraries typically provide methods to be able to verify a received JWT token. Here is an example using nimbus-jose-jwt and json-smart:

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jwt.JWTClaimsSet;
import net.minidev.json.JSONObject;public JWTClaimsSet read(String jwt, JWSVerifier verifier) throws ParseException, JOSEException
{
JWSObject jwsObject = JWSObject.parse(jwt);

if (!jwsObject.verify(verifier))
{
throw new IllegalArgumentException(“Fraudulent JWT token: ” + jwt);
}

JSONObject jsonPayload = jwsObject.getPayload().toJSONObject();
return JWTClaimsSet.parse(jsonPayload);
}

Creating a query string hash

A query string hash is a signed canonical request for the URI of the API you want to call.

1
qsh = `sign(canonical-request)`
2
canonical-request = `canonical-method + '&' + canonical-URI + '&' + canonical-query-string`

A canonical request is a normalised representation of the URI. Here is an example. For the following URL, assuming you want to do a “GET” operation:

"https://<my-dev-environment>.atlassian.net/path/to/service?zee_last=param&repeated=parameter 1&first=param&repeated=parameter 2"

The canonical request is

"GET&/path/to/service&first=param&repeated=parameter%201,parameter%202&zee_last=param"

To create a query string hash, follow the detailed instructions below:

  1. Compute canonical method
    • Simply the upper-case of the method name (e.g. "GET" or "PUT")
  2. Append the character '&'
  3. Compute canonical URI
    • Discard the protocol, server, port, context path and query parameters from the full URL.
      • For requests targeting add-ons discard the baseUrl in the add-on descriptor.
    • Removing the context path allows a reverse proxy to redirect incoming requests for"jira.example.com/getsomething" to "example.com/jira/getsomething" without breaking authentication. The requester cannot know that the reverse proxy will prepend the context path"/jira" to the originally requested path "/getsomething"
    • Empty-string is not permitted; use "/" instead.
    • Url-encode any '&' characters in the path.
    • Do not suffix with a '/' character unless it is the only character. e.g.
      • Canonical URI of "https://example.atlassian.net/wiki/some/path/?param=value" is"/some/path"
      • Canonical URI of "https://example.atlassian.net" is "/"
  4. Append the character '&'
  5. Compute canonical query string
    • The query string will use percent-encoding.
    • Sort the query parameters primarily by their percent-encoded names and secondarily by their percent-encoded values.
    • Sorting is by codepoint: sort(["a", "A", "b", "B"]) => ["A", "B", "a", "b"]
    • For each parameter append its percent-encoded name, the '=' character and then its percent-encoded value.
    • In the case of repeated parameters append the ',' character and subsequent percent-encoded values.
    • Ignore the jwt parameter, if present.
    • Some particular values to be aware of:
      • A whitespace character is encoded as "%20",
      • "+" as "%2B",
      • "*" as "%2A" and
      • "~" as "~".
        (These values used for consistency with OAuth1.)
  6. Convert the canonical request string to bytes
    • The encoding used to represent characters as bytes is UTF-8
  7. Hash the canonical request bytes using the SHA-256 algorithm
    • e.g. The SHA-256 hash of "foo" is `”2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae

Advanced: Creating a JWT token manually

Disclaimer

You should only need to read this section if you are planning to create JWT tokens manually, i.e. if you are not using one of the libraries listed in the previous section

More details on JWT tokens

The format of a JWT token is simple: <base64url-encoded header>.<base64url-encoded claims>.<signature>.

  • Each section is separated from the others by a period character (.).
  • Each section is base64url encoded, so you will need to decode each one to make them human-readable. Note that encoding with base64 and not base64url will result in an incorrect JWT token for payloads with non UTF-8 characters.
  • The header specifies a very small amount of information that the receiver needs in order to parse and verify the JWT token.
    • All JWT token headers state that the type is “JWT”.
    • The algorithm used to sign the JWT token is needed so that the receiver can verify the signature.
  • The claims are a list of assertions that the issuer is making: each says that “this named field” has “this value”.
    • Some, like the “iss” claim, which identifies the issuer of this JWT token, have standard names and uses.
    • Others are custom claims. We limit our use of custom claims as much as possible, for ease of implementation.
  • The signature is computed by using an algorithm such as HMAC SHA-256 plus the header and claims sections.
    • The receiver verifies that the signature must have been computed using the genuine JWT header and claims sections, the indicated algorithm and a previously established secret.
    • An attacker tampering with the header or claims will cause signature verification to fail.
    • An attacker signing with a different secret will cause signature verification to fail.
    • There are various algorithm choices legal in the JWT spec. In atlassian-connect version 1.0 we support HMAC SHA-256. Important: your implementation should discard any JWT tokens which specify alg: none as these are not subject to signature verification.

Steps to Follow

  1. Create a header JSON object
  2. Convert the header JSON object to a UTF-8 encoded string and base64url encode it. That gives you encodedHeader.
  3. Create a claims JSON object, including a query string hash
  4. Convert the claims JSON object to a UTF-8 encoded string and base64url encode it. That gives you encodedClaims.
  5. Concatenate the encoded header, a period character (.) and the encoded claims set. That gives you signingInput = encodedHeader+ “.” + encodedClaims.
  6. Compute the signature of signingInput using the JWT or cryptographic library of your choice. Then base64url encode it. That gives you encodedSignature.
  7. concatenate the signing input, another period character and the signature, which gives you the JWT token. jwtToken = signingInput + “.” + encodedSignature

Example

Here is an example in Java using gson, commons-codec, and the Java security and crypto libraries:

public class JwtClaims {
protected String iss;
protected long iat;
protected long exp;
protected String qsh;
protected String sub;
// + getters/setters/constructors
}
[…]
public class JwtHeader {
protected String alg;
protected String typ;
// + getters/setters/constructors
}
[…]
import static org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString;
import static org.apache.commons.codec.binary.Hex.encodeHexString;
import java.io.UnsupportedEncodingException;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import com.google.gson.Gson;
public class JwtBuilder {
public static String generateJWTToken(String requestUrl, String canonicalUrl,
String key, String sharedSecret)
throws NoSuchAlgorithmException, UnsupportedEncodingException,
InvalidKeyException {
JwtClaims claims = new JwtClaims();
claims.setIss(key);
claims.setIat(System.currentTimeMillis() / 1000L);
claims.setExp(claims.getIat() + 180L);
claims.setQsh(getQueryStringHash(canonicalUrl));
String jwtToken = sign(claims, sharedSecret);
return jwtToken;
}
private static String sign(JwtClaims claims, String sharedSecret)
throws InvalidKeyException, NoSuchAlgorithmException {
String signingInput = getSigningInput(claims, sharedSecret);
String signed256 = signHmac256(signingInput, sharedSecret);
return signingInput + “.” + signed256;
}
private static String getSigningInput(JwtClaims claims, String sharedSecret)
throws InvalidKeyException, NoSuchAlgorithmException {
JwtHeader header = new JwtHeader();
header.alg = “HS256”;
header.typ = “JWT”;
Gson gson = new Gson();
String headerJsonString = gson.toJson(header);
String claimsJsonString = gson.toJson(claims);
String signingInput = encodeBase64URLSafeString(headerJsonString
.getBytes())
+ “.”
+ encodeBase64URLSafeString(claimsJsonString.getBytes());
return signingInput;
}
private static String signHmac256(String signingInput, String sharedSecret)
throws NoSuchAlgorithmException, InvalidKeyException {
SecretKey key = new SecretKeySpec(sharedSecret.getBytes(), “HmacSHA256”);
Mac mac = Mac.getInstance(“HmacSHA256”);
mac.init(key);
return encodeBase64URLSafeString(mac.doFinal(signingInput.getBytes()));
}
private static String getQueryStringHash(String canonicalUrl)
throws NoSuchAlgorithmException,UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance(“SHA-256”);
md.update(canonicalUrl.getBytes(“UTF-8”));
byte[] digest = md.digest();
return encodeHexString(digest);
}
}
[…]
public class Sample {
public String getUrlSample() throws Exception {
String requestUrl =
“https://<my-dev-environment>.atlassian.net/rest/atlassian-connect/latest/license”;
String canonicalUrl = “GET&/rest/atlassian-connect/latest/license&”;
String key = “…”;     //from the add-on descriptor
//and received during installation handshake
String sharedSecret = “…”; //received during installation Handshake
String jwtToken = JwtBuilder.generateJWTToken(
requestUrl, canonicalUrl, key, sharedSecret);
String restAPIUrl = requestUrl + “?jwt=” + jwtToken;
return restAPIUrl;
}
}

Stateless Authentication implementation using JWT, Nginx+Lua and Memcached

If you already have an idea on stateless authentication and JWT then proceed with this implementation blog otherwise just go through the previous blog Stateless Authentication to get an idea.

As i mentioned in my previous blog JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA.

Client can access the the resources from different applications. So to validate the token at applications, we require the secret or a public/private key.

Problems of validating the token in every application

  1. We have to maintain the secret key in all the applications and have to write or inject the token validation logic in every application. The validation logic may include more than token validation like fingerprint mismatch, session idle time out and many more based on the requirement.
  2. If the applications are developed in different languages then we have to implement the token validation logic based on application technology stack and maintenance is very difficult.

Solution

Instead of maintaining the validation logic in every application, we can write our validation logic at one common place so that every request can make use of that logic irrespective of application (Note: Here Applications could be developed in any language). I have chosen reverse proxy server (Nginx) to maintain the validation logic with the help of Lua.

Advantages

  1. We don’t need to maintain the secret or private/public key in every application. Just maintain at authentication server side to generate a token and at proxy server (Nginx) to validate the token.
  2. Maintenance of the validation logic easy.

Before jumping in to the flow and implementation let’s see why we have chosen this technology stack.

Why JWT ? 

To achieve the stateless authentication we have chosen JWT (JSON Web Token). We can easily, securely transmitting information between parties as a JSON object. If we want to put some sensitive information in JWT token, we can encrypt the JWT payload itself using the JSON Web Encryption (JWE) specification.

Why Nginx + Lua ?

Nginx+Lua is a self-contained web server embedding the scripting language Lua. Powerful applications can be written directly inside Nginx without using cgi, fastcgi, or uwsgi. By adding a little Lua code to an existing Nginx configuration file, it is easy to add small features.

One of the core benefits of Nginx+Lua is that it is fully asynchronous. Nginx+Lua inherits the same event loop model that has made Nginx a popular choice of webserver. “Asynchronous” simply means that Nginx can interrupt your code when it is waiting on a blocking operation, such as an outgoing connection or reading a file, and run the code of another incoming HTTP Request.

Why Memcached ?

To keep the application more secured, along with the token validation we are doing the fingerprint check and handling idle time out as well. Means, if the user is idle for some time and not doing any action then user has to be logged out from the application. To do the fingerprint check and idle time out check, some information needs to be shared across the applications. To share the information across the applications we have chosen Memcached (Distributed Cache).

Note: If you don’t want to do fingerprint mismatch check and idle time out check, then you can simply ignore the Memcached component from the flow.

Flow

 

Untitled presentation (2)

 

Step 1

Client try to access the resource from the application with out JWT token or invalid token. As shown in the flow, request goes to the proxy server (Nginx).

Step 2

Nginx looks for the auth header (X-AUTH-TOKEN) and validates the token with the help of Lua.

 

Step 3

As token is not present or invalid, nginx sends below response to the client.

 

Step 4

Now user has to login in to the system, So client will load the login page.

Step 5

Client will send a request to the authenticate server to authenticate the user. Along with username and password client sends the fingerprint also. Here we are considering fingerprint to make sure that all the requests are initiating from the same device where user logged in to the system.

Sample authenticate request body

 

Step 6

Authenticate server validates the credentials and create a JWT token with TokenId (random generated UUID) as a claim and this tokenId is useful to uniquely identify the user. And set the JWT token in response header (X-AUTH-TOKEN).

Create JWT Token

Add this dependency to your pom.xml to work on JWT

While creating the token you can set any number of claims.

CustomClaim.java

Generated JWT token looks like below

And the JWT token payload looks like below. You can put what ever data you want like roles & permissions associated to him and so on…

 

Step 7

Put TokenId as a key and user meta information like fingerprint, last access time etc… as a value in memcached which is useful to verify the fingerprint and session idle time out at nginx side using Lua.

Sample Memcached content

 

Put Content in Memcached

Add this dependency to your pom.xml to work on Memcached

 

 

Step 8

Send back response to the client from authentication server with response header X-AUTH-TOKEN

 

Step 9

Fetch the token from response header and store it in local storage at client side. So that we can send this token in request header from next request onwards.

Step 10

Now client access the resource from application with valid JWT token. As shown in the flow request goes to the proxy server (Nginx). With every request client will send a fingerprint in some header and consider header name as “FINGER-PRINT”.

Step 11

Nginx validates the token. As token is valid, extract the TokenId from the JWT token to fetch the user meta information from memcached.

If there is no entry in the memcached with “TokenId” then Nginx simply senda a response as “LOGGED_OUT” to the client.

But in our case user is logged in into the system, So there will be an entry in memcached with TokenId. So fetch that user meta information to do the following checks.

Fingerprint mismatch : While sending the authenticate request, client is sending fingerprint along with username and password. We are storing that fingerprint value in memcached and we use this value to compare with the fingerprint which is coming in every request. If fingerprint matches, then it’s proceed further. Otherwise nginx will send a response to client saying that fingerprint is mismatched.

Session idle time out :  While successful authentication of a user at authentication server side, we are putting configured session_idle_timeout of a user in memcached. If it’s configured as “-1”, then we simply skip the session idle time out check. Otherwise for every request just we check whether session is idle or not. If session is not idle, we update the last_access_time value to current system time in memcached. If session is idle then Nginx send below response to the client.

Complete Validation Logic at Nginx using Lua

base-validation.lua

Step 12

Once the request gone through the above mentioned validation logic, Nginx proxy_pass the request to the application.

sample-nginx.conf

Step 13

Application sends a response of requested resource to the client.

How to achieve logout ?

There is a open question (unanswered) regarding how to achieve the log out at server side, if we go by the stateless authentication using JWT.

Mostly people are discussing about handling the log out at client side.

  • When user clicks on logout, simply client can remove the token from local storage.

But i come up with a solution to achieve the logout at server side by make use of Memcached.

  • When user clicks on logout, Remove the entry from Memcached which  we put it in Step 7. And client also can delete the token from local storage as well. If you see the validation logic which i have completely covered in Step 11, there i’m checking the entry in memcached. If there is no entry in memcached, means user logged out from the application.

2016 最佳 Linux 发行版排行榜

2015年,不管在企业市场还是个人消费市场都是 Linux非常重要的一年。作为一个自2005年起就开始使用 Linux的 Linuxer ,我门见证了 Linux在过去十年的成长。2016 Linux 将更加精彩,所以我们选择了一些大放异彩的发行版。现在 Linux Story小编就带你去领略一下各领域的风采吧!

最好的回归发行版:openSUSE

openSUSE 背后的 SUSE 公司是最老的 Linux 企业,它成立于 Linus Torvalds 宣布放出 Linux 的一年后。它其实早于 Red Hat 的诞生,它也是社区主导的发行版 openSUSE 的赞助商。

在2015,openSUSE 团队决定靠拢 SUSE Linux 企业版(SLE)以便用户可以共享企业服务版本的 DNA ,就像 CentOS 和 Ubuntu一样。之后,openSUSE 变成了 openSUSE Leap,直接基于 SLESP1 。这两个发行版将共享代码库以互惠互利,SUSE 将吸取 openSUSE 的优秀内容,反之亦然。通过这一举措,openSUSE 也抛弃了常规的发行周期,一个新的版本将和 SLE 保持一致。这意味着每个版本将有更长的生命周期。这一举措的结果是 openSUSE 将变成一个非常重要的发行版,因为潜在的 SLE 用户可以使用 openSUSE Leap。然而,这还不是全部,openSUSE 同时发布了一个纯粹的滚动发行版—— Tumbleweed 。可以参考Linux Story闻其详撰写的这篇文章《生命、宇宙以及Linux 系统的终极答案? openSUSE Leap 42.1 华丽发布》,所以现在用户可以使用超稳定的 openSUSE Leap和 始终保持最新的 openSUSE Tumbleweed。

在我记忆中没有其他发行版做了如此深刻的回归。

最可定制的发行版: Arch Linux

Arch Linux是现阶段最好的滚动发行版,好吧,我可能因为我是 Arch Linux用户而产生了偏见。更重要的是 Arch 在其他方面也表现良好,这也是为什么我选择它作为我的操作系统的原因。

Arch Linux 是一个为那些想了解 Linux 一切的人准备的发行版,因为你必须手动安装一切,它会让你学会基于 Linux 的操作系统的每个部分。Arch Linux 是最可定制的发行版,你获得的只是一个基础系统,然后你可以在它上面建立属于你个人的发行版。不论好坏,它都不像 openSUSE 和 Ubuntu,它没有额外的补丁和整合内容,你甚至可以获得上游开发者创建的内容。Arch Linux 也是最好的滚动发行版之一。他总是更新,用户始终使用最新的软件包,并且他们还可以通过稳定的存储库运行预发布软件。Arch 也因优异的文档闻名。 Arch Wiki 可以让我得到任何 Linux 相关的资料。Arch 中我最喜欢的内容是它提供的所有的包和软件都可在“任何” Linux 发行版上运行。感谢 Arch User Repository(AUR)。

最好看的发行版:elementary OS

不同的 Linux 发行版有不同的侧重点,在大多数情况下这都是技术差异。在很多 Linux 发行版中外观和感觉是无足轻重的——更像是一个边缘项目。不管什么角度,Linux Story 一直觉得它是一个非常漂亮的系统。

elementary OS正试图改变这一切。在它里面,设计走在了前列,其原因是很明显的。该发行版漂亮的图标是 Linux 世界闻名的设计师们设计开发的。elementary OS非常严格要求整体的外观和感觉。开发者已经创建了包括桌面环境在内的自己的组件,此外,他们只选择那些符合自己设计模式的应用程序。可以在该系统上看到 Mac OS X 的影子。

最佳新人:Solus

Solus操作系统最近已经获得了相当多的关注,它是一个从头开始创建的前瞻性操作系统。它并不是 Debian 或 Ubuntu的衍生物。它搭配了为集成 GNOME 从头开始构建的 Budgie 桌面环境。Solus 有和 Google Chrome OS相同的极简主义方法。Linux Story 完全认同 Solus 为最佳新人。

我没有使用太多 Solus,但它看起来很有希望。 Solus 不是一个“新的”操作系统,它曾经以不同的形式和名称存在。但是整个项目的新名称是在2015年才提出的。

最好的教育操作系统:ezgo Linux

ezgo是一套开源、公益、免费、面向教育的电脑操作系统,基于Linux 而开发,它包含有丰富的互动教学软件和开放教材、知识,涵盖了物理、化学、地理、天文、 生物、数学、计算机等学科,矢志帮助学校的学生和教师的教育信息化,帮助孩子们和家长、老师以最方便最有效的方式接触、获取全世界最先进的知识和智慧,这 是一个发源于台湾的开源项目,目前在国内是ezgo中国社区,重庆Linux用户组 ChongqingLUG 在维护、开发和推广。搜集了包括 PhET在内的大量开源教材,Linux Story 有幸也曾经报道过跟 ezgo 有关的消息,它的官方网站是 http://ezgolinux.org/。关心教育的家长、学生和老师值得关注。

最好的云操作系统:Chrome OS

Chrome OS不是一个典型的基于 Linux 的发行版,因为它是一个为在线活动设计的基于浏览器的操作系统。而且,由于它基于 Linux 同时它的源码是供所有人编译,所以它也很有吸引力。我每天都使用 Chrome OS ,这是一个对纯粹为网络活动而设计的极好的,免维护的,不断更新的操作系统。Chrome OS 和 Android 一起值得所有的新人来实现 PC 和其他平台的 Linux 普及。Linux Story 曾经也试用过 Acer Chromebook 11,感觉相当不错。

最好的笔记本操作系统:Ubuntu MATE

大多数笔记本没有非常高端的硬件,如果你正在运行一个非常消耗资源的桌面环境的话你将不会有太多的系统资源或电池续航来供你使用,因为系统已经占用了很多。这就是我发现为什么 Ubuntu MATE是一个优秀的操作系统。因为它是轻量级的,但也有应有尽有的内容给你提供不错的体验。正是由于它轻量级的设计,大部分的系统资源可供你去完成繁重的工作。我认为它在低端硬件上是一个真正优秀的发行版。

最好的旧硬件支持系统:Lubuntu

如果你有闲置的旧笔记本或者台式机,可以使用 Lubuntu来令它焕发生机。Lubuntu 使用 LXDE 桌面环境,但该项目已经和 Razor Qt 合并为 LXQt 项目了。尽管最新的15.04版本仍然使用 LXDE ,但是以后的版本将使用 LXQt 。Lubuntu 确实是一款适合旧硬件的操作系统。

最好的物联网操作系统:Snappy Ubuntu Core

Snappy Ubuntu Core是最好的物联网以及其他类似设备的基于 Linux 的操作系统。该操作系统有很大的潜力将近乎的所有东西都变成智能设备,比如路由器、咖啡机、无人驾驶飞机等等。优秀的软件管理和为增强安全性设计的容器化将它变得更加好玩。

最好的台式机操作系统:Linux Mint Cinnamon

Linux Mint Cinnamon是最好的台式机操作系统,它对硬件强大的笔记本也是最好的。我将它当成 Linux 世界的 Mac OS X 。老实说,我曾经因为 Cinnamon的不稳定而十分不愉快。但是,只要开发者选择 LTS 版本,它就变得难以置信的稳定。因为开发者不必花太多时间去跟上 Ubuntu,所以他们可以花更多时间去让 Cinnamon 更好。

最好的游戏系统:Steam OS

游戏一直是桌面版 Linux 的弱点,许多用户启动双系统的 Windows只是为了玩游戏。Valve Software 正在努力改变这一现状。Valve 是一个提供使游戏在不同平台上运行的客户端的游戏分销商。而且,为了创建基于 Linux 的游戏框架,Valve 已经创建了他们自己的开放式操作系统—— Steam OS。在2015年底,合作伙伴开始将 Steam 机器推向市场。

最好的隐私保护操作系统:Tails

当下大量的监视和营销者的跟踪(匿名跟踪的目标内容是可接受的)让隐私保护已经成为一个主要的问题。如果你的业务需要避免政府和营销机构的追踪,你就需要考虑一款从底层设计隐私保护的操作系统。

而且,在这一方面没有其他的能打败 Tails。它是基于 Debian 的设计用来实现隐私保护和匿名化的操作系统。Tails 非常棒,据报道,美国国家安全局(NSA)认为它是自己使命的重要威胁。

最好的多媒体制作系统:Ubuntu Studio

多媒体制作是基于 Linux 的操作系统的主要缺点之一,所有专业级的程序在 Windows和 Mac OS X 上都可找到。Linux 上却没有像样的音频/视频制作软件,但一个多媒体制作系统需要的不仅仅是像样的应用程序。它应该使用轻量级的桌面环境使宝贵的系统资源如 CPU、RAM 被系统尽量少的使用,以便用于多媒体制作程序。因此,最好的 Linux 多媒体制作系统是 Ubuntu Studio,它使用 Xfce 桌面环境并配备了众多的音频,视频和图像编辑应用程序。Linux Story 网站很长时间也用过它来制作一些影音多媒体素材。

最好的企业级系统:SLE/RHEL

企业用户不会四处寻找运行在自己服务器上的发行版。他们已经知道选择范围:Red Hat Enterprise Linux 或者 SUSE Linux Enterprise 。这两个名字已经成为企业级系统的代名词。这些公司也在设法在容器化和软件定义上的创新来推倒当前的壁垒。Linux Story 认为 RHEL 确实稳定,确实好用。

最好的服务器操作系统:Debian/CentOS

如果你正打算运行一个服务器,但是又不想为 RHEL 或 SLE 的维护付费,那么 Debian 或 CentOS 是你最好的选择。这些发行版是社区主导的服务器版本,它们有着黄金标准。而且,它们的支持周期很长,所以你不必担心经常升级系统。

最好的移动操作系统:Plasma Mobile

尽管基于 Linux 的操作系统—— Android 正在主宰移动领域,包括我在内的很多开源社区的成员仍然希望有一个发行版能够在移动设备上提供传统的 Linux 桌面应用程序。同时,它最好是由一个社区负责运营维护而不是一个公司以便让用户仍然是受关注的焦点,而不是以公司的财务目标为焦点。而这正是 KDE 的 Plasma Mobile带来的希望。

该版本是基于 Kubuntu 的,发布于2015年。因为 KDE 社区在公众环境中遵守标准和发展东西是众所周知的,所以我对 Plasma Mobile的未来充满希望。

最好的 ARM 设备发行版:Arch Linux ARM

随着 Android 的成功,我们已经被 ARM 设备所包围——从树莓派到 Chromebook 再到 Nvidia Shield。为 Intel/AMD 处理器编写的传统发行版将不能在这些设备上运行。虽然一些发行版专为 ARM 设计,但是大多数都只针对具体的硬件,比如为树莓派设计的 Raspbian 。这也是为什么 Arch Linux ARM(ALARM) 让人眼前一亮。因为它是一个纯粹由社区主导的基于 Arch Linux 的发行版,你可以在树莓派、Chromebook、Android 设备、Nvidia Shield 等上面运行它。这个发行版更有趣的是,因为 Arch User Repository(AUR)的原因,所以你可以安装许多你可能在其他发行版上无法获得的应用程序。

总结

当我完成这篇文章的时候我很惊讶和惊奇,非常令人兴奋的看到有适合每个人的 Linux 世界。如果这一年桌面版的 Linux 一直跳票也没关系,我们因 Linux 时刻高兴着!

最受欢迎编程语言又是谁?C 语言居首,大数据赢了

C语言占据榜首,但大数据类是最大赢家。

IEEE Spectrum的第三次“最受欢迎编程语言”交互式排行榜新鲜出炉。因为不可能顾及到每一个程序员的想法,Spectrum使用多样化、可交互的的指标权重来评测每一种语言的现行使用情况。

数据记者Nick Diakopoulos从10个线上资源中选取了12个指标,这其中的每一个都能反映某一种编程语言在某一方面的受欢迎程度,加权这些指标就能得出一个排名。

何为“交互式”排名?

因为我们每个人都可能会看重不同的东西,比如大众最热衷在开源代码中使用什么语言?哪种语言的客户需求量最大?Spectrum的“交互式编程语言排行”让用户可以根据自己的喜好调整不同评价指标所占的权重,从而得到所需的排名。

用户还能根据自己的需要过滤榜单中的结果,例如我们可以选择只显示用于嵌入式系统和移动终端的语言。当然,用户既可以定制榜单中的每一项权重,也可以使用榜单预设的评价方案。

榜单中的默认预设是根据IEEE成员的平均兴趣权重来设定的,那么2016年Spectrum评选出的排名前十的编程语言都有哪些呢?

在连续两年屈居亚军后,C语言终于替代了Java榜首的位置。放眼前五名,Python和C++在3、4名上互换了位置,C#跌出前五,其位置由近几年上升势头迅猛的R语言所取代。近年来,包括R在内的大数据类编程语言总体呈现出一种上升趋势。

谷 歌和苹果在榜单上同样你追我赶,最新的榜单显示谷歌的Go语言击败了苹果的Swift并杀入前十,但swift的上升同样不容小觑,其今年排到了第11 位,相比于去年上升了5个排名。值得一提的是,去年曾有若干新兴编程语言和Swift一起初涉榜单,但今年却不见了它们的踪影。

其 他引人瞩目的变化包括Ladder Logic,它从去年的39名上升到了今年的34名。LadderLogic用于PLC(可编程逻辑控制器),尤其是在工厂中的PLC上应用较广。通常人 们认为编程语言在制造业中无利可图,然而Ladder Logic的成功揭示了编程语言在制造业应用中的巨大商机。

另外HTML仍然流行,今年排名上升到了第16位,之前有用户甚至还在担忧其是否能入选榜单(为准确起见,我们秉承着实用至上的原则,并且将编程语言定义为一种给计算机下指令的特殊语法——就算这种语法只是用于数据的结构化——我们并不要求编程语言是图灵完备的)。

在 退步名单里,最出人意料的当属Shell的衰落(Shell是一种统称,指对脚本的直接创造,通常为系统管理员所钟爱,常见的有bash shell等),其下降了7个名次落到了第19位。这种趋势或许反映了用于云端数据中心的复杂系统的发展壮大,但现在我们还不能妄下结论,我们还需要观察 下一年的排名来确定这种趋势是否会持续,抑或仅是一种统计学上的偶然结果。

注:

IEEE Spectrum:一本IEEE(美国电气电子工程师学会)出版的旗舰杂志,其中文版名为《科技纵览》,旨在探讨未来技术发展趋势及其对社会和商业的影响,主要内容为报道国际航空航天、计算机和电信、生物医学工程、能源和消费电子等领域的最新技术进展和成果。

PLC:可编程逻辑控制器,是一种采用一类可编程的存储器,用于其内部存储程序,执行逻辑运算、顺序控制、定时、计数与算术操作等面向用户的指令,并通过数字或模拟式输入/输出控制各种类型的机械或生产过程。

图灵完备:Turing Completeness,一切可计算的问题都能计算,这样的虚拟机或者编程语言就叫图灵完备的。

稿源:dy.163.com

苹果的 Safari 已成为新的 IE

IE 一直以来都因为不兼容标准而遭人诟病,因为早期的 IE 占有率太高,IE 不支持的 html/js 特性网站就无法使用。

而现在 Safari 的状态和当时的 IE 非常相似,几乎也成了 HTML5 标准的公敌。

以 HTML5 的 Flexbox 为例,作为网页弹性布局重要的特性,开发者却因为 webkit 里存在大量 bug 而不能使用。

谷歌的 blink 引擎也从 webkit 继承了这些 bug,在两年时间里 blink 收到了数十个 bug 报告,bug 被修好后开发人员甚至提醒用户 safari 仍有 bug,建议不要使用。而谷歌之所以花一年多才修复也是因为 safari 不支持的特性没人会用,bug 优先级不高。

反观 safari,bug 出现一年后才有人提交报告,至今甚至都没有任何开发人员对 bug 进行 review 或评论,bug 状态仍是 new。经常有设计师在其他浏览器里做好的效果发现在 safari 布局完全错乱而不得不重新设计。和当年的 IE 一样,兼容标准对苹果并没有什么好处。迫使开发人员针对 iPhone 优化手机网页反而能增加用户粘性。比如网页在隐私模式下的行为,或者屏幕触摸事件的属性,等等功能,苹果都选择不遵照标准而采用自己的定义。

苹果发明了非标准的 viewport 标签用来定义网页在手机上的缩放,如今苹果自家对 viewport 的定义竟成了其他浏览器必须遵照特性。

回想当年乔布斯还反复强调 flash 要死,html5 是未来,简直滑稽可笑。

科技行业最有钱途 15 个职位:第一竟不是程序猿

北京时间8月21日消息,根据Comparably.com提供的数据,财经网站TheStreet列出了科技行业最赚钱的15个职位,看看你的工作在列吗,排在第几位?

销售工程师。平均工资:122110.18美元,平均奖金:38589.20美元,平均薪水总额:157510.19美元。BLS表示,销售工程师负责向其他企业出售“复杂的科技产品或服务”,这些专业人士必须广泛具有“产品部件和功能相关知识,必须系统了解制造这些产品的过程”。

创意总监。平均工资:136573.01美元,平均奖金:19913.54美元,平均薪水总额:146886.79美元。创意总监通常负责一个组织某一特定产品或服务的品牌战略及概念定位。创意总监在艺术、音乐、时尚和广告领域较为普遍,但现在的科技公司也逐渐引入了该职位。

销售经理。平均工资:101899.23美元,平均奖金:51843.01美元,平均薪水总额:145807.08美元。销售经理负责一个公司的销售团队。他们负责“制定销售目标,分析数据和开发培训项目”。

首席工程师。平均工资:134748.01美元,平均奖金:16580.14美元,平均薪水总额:143921.79美元。首席工程师头衔包括首席软件工程师和首席程序员,负责公司的一个或多个项目。

高级开发人员。平均工资:126663.10美元,平均奖金:19338.86美元,平均薪水总额:138234.22美元。开发人员代表了任何参与软件或Web开发的工程师,前面冠以“高级”,代表了领导角色。

数据科学家。平均工资:122356 .37美元,平均奖金:21284.69美元,平均薪水总额:135450.98美元。数据显示,数据科学家是2016年美国最好的工作之一。《哈佛商业评论》称该职业是“21世纪最性感的工作”。

销售代表。平均工资:78609.75美元,平均奖金:60841.21美元,平均薪水总额:131964.44美元。科技行业内销售代表的薪酬,是销售职业当中最高的。

高级营销经理。平均工资:118127.57美元,平均奖金:17080.30美元,平均薪水总额:130255.59美元。该职位职责包括产品开发、趋势监测、品牌管理、客户定位和收购等。BLS预测到2024年该职位需求增长将达到9%,高出平均水平。

项目经理。平均工资:116703.79美元,平均奖金:17625.52美元,平均薪水总额:127652.98美元。项目经理负责“项目提案、计划、状态报告和变更请求”,同时还需要具有良好的人际交往能力和谈判技巧。

DevOps。平均工资:117616.84美元,平均奖金:12869美元,平均薪水总额:124927.63美元。DevOps就是开发(Development) 和运维(Operations)这两个职位的合并,该职位强调软件开发和IT运营之间的沟通、协作和集成。

高级UI/UX设计师。平均工资:116038美元,平均奖金:12438.95美元,平均薪水总额:121946.50美元。UX(用户体验)设计师关心用户的对产品感觉如何,而UI(用户界面)设计师关注的是产品布局如何,不过二者的界限有利于模糊。

移动开发者。平均工资:111140.05美元,平均奖金:16225.41美元,平均薪水总额:117727.81美元。据ABI研究提供的数据显示,今年移动应用开发行业营收规模将达到460亿美元,意味该行业将对移动应用开发人员有着更高需求。

高级设计师。 平均工资:109901.03美元,平均奖金:14653.16美元,平均薪水总额:117422.99美元。硅谷图形设计师和计算机科学家约翰梅达 (John Maeda)称,由于设计和技术对用户体验的影响日益增强,两个领域的界限正在模糊。在软件开发领域,设计师的作用正显得愈发重要。

人力资源经理。平均工资:98893.25美元,平均奖金:13129美元,平均薪水总额:106860.77美元。BLS表示,到2024年,人力资源经理需求将增长9%,“确保公司能够赶上不断变化且复杂的就业法律”。

开发人员。 平均工资:96220.28美元,平均奖金:12358美元,平均薪水总额:102625美元。美国劳工统计局(BLS:Bureau of Labor Statistics)表示,由于不断增长的计算机软件需求,到2024年,软件开发人员需求将增长17%,远超其他所有职位增长平均水平。

出处:凤凰科技

最新最准确各大搜索引擎蜘蛛名称(转)

1、百度蜘蛛:Baiduspider
网上的资料百度蜘蛛名称有BaiduSpider、baiduspider等,都洗洗睡吧,那是旧黄历了。 百度蜘蛛最新名称为Baiduspider。日志中还发现了Baiduspider-image这个百度旗下蜘蛛,查了下资料(其实直接看名字就可以 了……),是抓取图片的蜘蛛。
常见百度旗下同类型蜘蛛还有下面这些:Baiduspider-mobile(抓取wap)、Baiduspider-image(抓取图片)、Baiduspider-video(抓取视频)、Baiduspider-news(抓取新闻)。
注:以上百度蜘蛛目前常见的是Baiduspider和Baiduspider-image两种。
2、谷歌蜘蛛:Googlebot
这个争议较少,但也有说是GoogleBot的。谷歌蜘蛛最新名称为“compatible; Googlebot/2.1;”。还发现了Googlebot-Mobile,看名字是抓取wap内容的。
3、360蜘蛛:360Spider,它是一个很“勤奋抓爬”的蜘蛛。
4、SOSO蜘蛛:Sosospider,也可为它颁一个“勤奋抓爬”奖的蜘蛛。
5、雅虎蜘蛛:“Yahoo! Slurp China”或者Yahoo!
名称中带“Slurp”和空格,名称有空格robots里名称可以使用“Slurp”或者“Yahoo”单词描述,不知道有效无效。
6、有道蜘蛛:YoudaoBot,YodaoBot(两个名字都有,中文拼音少了个U字母读音差别很大嘎,这都会少?)
7、搜狗蜘蛛:Sogou News Spider
搜狗蜘蛛还包括如下这些:Sogou web spider、Sogou inst spider、Sogou spider2、Sogou blog、Sogou News Spider、Sogou Orion spider,
(参考一些网站的robots文件,搜狗蜘蛛名称可以用Sogou概括,无法验证不知道有没有效)
看看最权威的百度的robots.txt ,http://www.baidu.com/robots.txt 就为Sogou搜狗蜘蛛费了不少字节,占了一大块领地。
“Sogou web spider;Sogou inst spider;Sogou spider2;Sogou blog;Sogou News Spider;Sogou Orion spider”目前6个,名称都带空格。
线上常见”Sogou web spider/4.0″ ;”Sogou News Spider/4.0″ ;”Sogou inst spider/4.0″ 可以为它颁个“占名为王”奖。
8、MSN蜘蛛:msnbot,msnbot-media(只见到msnbot-media在狂爬……)
9、必应蜘蛛:bingbot
线上(compatible; bingbot/2.0;)
10、一搜蜘蛛:YisouSpider
11、Alexa蜘蛛:ia_archiver
12、宜sou蜘蛛:EasouSpider
13、即刻蜘蛛:JikeSpider
14、一淘网蜘蛛:EtaoSpider
“Mozilla/5.0 (compatible; EtaoSpider/1.0; http://省略/EtaoSpider)”
根据上述蜘蛛中选择几个常用的允许抓取,其余的都可以通过robots屏蔽抓取。如果你暂时空间流量还足够使用,等流量紧张了就保留几个常用的屏蔽掉其它蜘蛛以节省流量。至于那些蜘蛛抓取对网站能带来有利用的价值,网站的管理者眼睛是雪亮的。
另外还发现了如 YandexBot、AhrefsBot和ezooms.bot这些蜘蛛,据说这些蜘蛛国外噶,对中文网站用处很小。那不如就节省下资源。

程序员入门必读:编程语言争霸 霸主是他

世界上的语言有千万种,但是却不只有汉语、英语、法语和俄语,还有Java、C++、Python和PHP。计算机的快速发展,使编程成为一种职业,程序员也成为近年来备受关注的一种职业。

语言争霸 谁为王?

在编程世界中,也有着不同的门派,各个门派都在强调自己是武林独尊,互不相让。今天笔者无意挑起武林争端,却要给那些想成为程序员的莘莘学子一个建议,参考备受认可的TIOBE编程语言社区最新排行榜,推荐十款备受关注的编程语言供大家选择,总有一款适合你的。

TIOBE世界编程语言排行榜(2016年3月)

1、Java

相信Java是很多非专业编程人员也听说过的语言,仅这一点看来,就足以证明Java的知名度。Java最初由SUN公司推出,并将其定位在简单、开放、高性能的语言。Java是一个纯粹面向对象的程序设计语言,与C++语言面向对象技术很像,同时Java虽然推出与1995年,属于编程语言中的“老者”,但是,Java一直在做内部的迭代,这也是Java经久不衰的重要原因。Java广泛应用在PC、数据中心、超算平台、游戏和移动等领域。

Java

2、C/C++

笔者这里将本是同根生的C语言和C++列到了一起,因为C++本就是C的增强版,但是其出现后迅速获得了大量的支持者,进而成为一种独立的语言。C++语言灵活,运算符的数据结构丰富、高效,且是一种可移植的多用途程序设计语言。他主要用于系统开发、引擎开发、嵌入式软件、高性能服务器和娱乐软件领域。C语言和C++分别位于TIOBE世界编程语言排行榜中的第二名和第三名,编程语言第一名为Java(以2016年3月为准)

C/C++

3、C#

C#是微软公司开发的面向对象的、运行于.NET Framework之上的高级程序设计语言。C#继承了C家族强大功能的同时,去除了其中复杂的特性。可能有人会说C#与Java太像了,的确,但是他同时借鉴了Delphi的特点:与com是直接集成的,同时它也是微软.NET windows网络框架的主角。更现代化的C#也曾一度挤入TIOBE世界编程语言排行榜的前三名,不过在最新一次的排行中,C#屈居第四。

C#

4、Python

Python是比Java更古老的语言,发明与1989年,是一款纯粹的自由软件。Python最大的特点莫过于其强大的库,Python丰富的第三方库资源就是它的优势,Python库能够简化程序员的编程过程,节省时间。

在2016年年初,Python火了一把。主要原因是,美国科学家成功监测出引力波,引力波研究机构LIGO在检测过程中使用了这个语言,并将其(GWPY)公布在GitHub上。根据第三方机构TIOBE的排名显示,Python与去年同期相比上升了三名,跻身前五。

Python

5、PHP

PHP也叫做超文本预处理器(Hypertext Preprocessor),其语法吸收了Java、C语言的优点,同时也自创了PHP新语法,支持几乎所有流行的数据库和操作系统。PHP属于开源脚本语言,所以是完全免费的,PHP源代码也能够看得到。PHP的便捷性让新手学习起来十分容易上手,而且程序开发快运行快,经常用于Web开发。

PHP

6、Visual Basic .NET

Visual Basic .NET在2014年开始挤入排行榜前十名,而在最新版当中,Visual Basic .NET更上升到第7名。Visual Basic .NET作为微软Visual Basic 6.0 version的继承者,一直备受压力,在发布之处甚至受到一些开发者抵制。很多开发者表示,VB.NET丢到了很多VB6中的constructs和用户界面功能,并没有很好的继承VB6的优点;但微软似乎在吧VB .NET作为一个全新的语言,目前看来也取得了不错的成绩。

Visual Basic .NET

7、JavaScript

这个看起来很像Java的编程语言JavaScript(以下简称:JS)是由Java压法公司Sun和Netscape合作完成的。主要目的是为了解决服务器端语言遗留的速度问题(如Perl),为用户提供更优的浏览效果。

同时,今年也是JS最受欢迎的库jQuery也迎来了自己十周岁生日,jQuery虽然只发布之日起就备受争议,但似乎已成为JB的“默认事实标准”。

JavaScript

8、Perl

Perl也被称为“实用报表提取语言”(Practical Extraction and Report Language),其最初设计者为为拉里·沃尔(Larry Wall),其貌不扬却拥有天才般的开发能力,拉里·沃尔曾表示:”无论你们怎么评论,我仍然爱她!”如今,Perl也从最初的发布到现在走过了近三十年。Perl最重要的特性就是内部集成了正则表达式的功能,拥有强大的第三方代码库CPAN。同时,Perl的解释程序是开放源代码的,所以使用者不用为费用问题而担心。

Perl

9、Ruby

Ruby有日本人研发,最初由于语言不通,受到很多人的诋毁,但随着Ruby的更新和非日文资料的增多,Ruby逐渐开始被接纳。Ruby也有红宝石的含义,其logo也是一颗红宝石,而其语言本身也如红宝石般优雅,十分美丽。与JAVA不同,Ruby是一种动态的,侧重于简单高效的开源的语言。Ruby的设计者认为,减少编程时不必要的琐碎时间很有必要,所以简便、人性化成为Ruby的一大特性。

Ruby

10、Swift

Swift虽然在最新的TIOBE榜单中排位14名,但是相比去年3月的24名,进步速度可谓飞快。Swift拥有Python的易用性,还有Objective-C、C++和Ruby的影子。Swift一直是苹果生态系统中的一员,直到去年WWDC大会上,苹果宣布开源自己的Swift语言;Swift语法十分简单,且高效强大,但是他同样有一个缺点就是,只能运行在苹果的系统中(OS X和iOS)。

你用的是哪个编程语言?

总结:所谓术业有专攻,不同的程序员选择了不同的语言种类,对于任何一个想要学习编程语言的人来说,应该去选择适合自己工作场景的语言。这里给读者推荐了现在最流行的十款编程语言,你可以选择最适合自己的那个进行学习。

2015 年 JavaScript 开发者调查报告

年底将至,JavaScript 开发者调查也已经结束,此次调查总共有 5000 份回复,我真的迫不及待要分享这次调查的细节,感谢所有的参与者,这是 JavaScript 社区伟大的时刻。

你写什么类型的 JavaScript?

97.4% 的受访者写 JavaScript 的 Web 浏览器,其中有 37% 写移动 Web 应用。

一些参与者回复,他们会在其他地方用 JavaScript,特别是在开发中的 CLI 和桌面应用。有少部分还会在 Pebble 和 Apple TV 上开发。这些归类到其他类别上,占总选票的 2.2%。

An screenshot of the percentages for the first question

你在哪使用 JavaScript?

不出我所料,94.9% 的投票者用 JavaScript 工作。然而,有 82.3% 的投票者也在其他项目中使用 JavaScript。其他回复包括教学,好玩或者非盈利目的使用。

An screenshot of the percentages for the second question

你写 JavaScript 多久了?

超 过 33% 的人写 JavaScript 代码超过六年了。除去那些精准回答的选票,5.2% 在一年前开始写 JavaScript,12.4% 两年前开始写 JavaScript,还有 15.1% 三年前写 JavaScript。总共有 32.7% 的人在近几年开始写 JavaScript。

An screenshot of the percentages for the third question

你使用哪种 complie-to-JavaScript 语言,如果有的话?

85% 参与者表示,他们将 ES6 编译为 ES5。同时有 15% 使用 CoffeeScript,有 15.2% 用 TypeScript,只有可怜的 1.1% 使用 Dart。

这是我想要进一步合作的问题之一,因为它有 13.8% 的“其他”回复。这个问题绝大多数的答案是 ClojureScript、elm、Flow 和 JSX。

An screenshot of the percentages for the fourth question

你喜欢哪种 JavaScript 文体选择?

JavaScript 开发者绝大多数似乎青睐分号,总共有 79.9%。相比之下,11% 的人表示他们不喜欢使用分号。说到逗号,44.9% 的人赞成放置后的表达,而 4.9% 的人喜欢用逗号第一语法。当涉及到缩进,65.5% 更喜欢空格,而 29.1% 的人更喜欢使用制表符。

An screenshot of the percentages for the fifth question

你使用 ES5 哪个功能?

有 79.2% 的人使用 Array methods,并且有 76.3% 的人使用 strict mode。30% 的人使用 Object.create,而 getter 和 setters 只有 28% 的人使用。

An screenshot of the percentages for the sixth question

你使用 ES6 哪个功能?

值得注意的是,Arrow functions 是本次调查中最常用的 ES6 特点,占了总票数的 79.6。Let and const
总共占 77.8% 的投票,Promise 功能依旧强劲,有 74.4 %的人选择了它。不出人意料的是,只有 4% 的人使用 proxies。只有 13.1% 的人用 Symbols,超过 30% 的人使用 Iterators。

https://i.imgur.com/okcvuos.png

你写测试吗?

有 21.7%  的人来不写任何测试,大多数人写一些测试,34.8% 经常写测试。

An screenshot of the percentages for the eighth question

你运行连续集成测试吗?

和 CI 一样,很多人不用 CI 服务器 —— 超过了 40%。有 60% 的人偶尔使用 CI,有 32% 的人在 CI 服务器上运行测试。

An screenshot of the percentages for the ninth question

你怎么运行测试

59% 的人喜欢运行和 PhantomJS 相似的自动化浏览器测试,51.3% 的人也喜欢在网络浏览器上人工测试。自动化服务器端测试则占了 53.3% 的得票。

An screenshot of the percentages for the tenth question

你用什么单元测试库?

大多数人要么选择 Mocha 要么选择 Jasmine 运行 JavaScript 测试,Tape 收到 9.8% 选票。

An screenshot of the percentages for the eleventh question

你用什么代码质量工具?

似乎参与者都在 ESLint 和 JSHint 之间纠结,不过 JSLint 经过了这么多年依旧坚挺,几乎有 30%。

An screenshot of the percentages for the 12th question

你怎么处理客户端的依赖?

Npm 接管客户端依赖管理体系,拥有 60% 的选票。Bower 依旧占据了 20% 的选票,而普通的 <script> 下载和插入获得13.7% 的选票。

An screenshot of the percentages for the 13th question

你首选的构建脚本解决方案是什么?

Gulp 最流行,超过 40% 的投票。接下来的是 NPM,为 27.8%, Grunt 获得了 18.5% 的选票。

An screenshot of the percentages for the 14th question

你首选的 JavaScript 加载工具时什么?

大多数参与者在 Browserify 和 Webpack 之间徘徊,而后者领先前者 7 个百分点。

An screenshot of the percentages for the 15th question

你用什么库?

jQuery 依旧强劲,占据票数 50% 以上,而 XHR 微库只有票数的 8%。

An screenshot of the percentages for the 16th question

你用什么框架?

不出人意料,React 和 Angular 处于领先地位。Backbone 也在靠前的位置,有 22.8% 的选票。

An screenshot of the percentages for the 17th question

你用 ES6 吗。。。

有 20% 的人几乎从不使用它,有 40% 的人偶尔使用,接近 30% 的人广泛使用。

An screenshot of the percentages for the 18th question

你知道 ES2016 有哪些特性吗?

粗略地说,有一半的人不知道 ES2016  有哪些新特性。

An screenshot of the percentages for the 19th question

你理解 ES6 吗?

超过 60% 的人理解基本的概念,有 10% 的人完全不理解,有 25% 的人理解 ES6。

An screenshot of the percentages for the 20th question

你会说 ES6  是一种进步吗?

近 95% 的人认为 ES6 是一种进步。

An screenshot of the percentages for the 21th question

你首选文本编辑器是什么?

超过一半的人喜欢 Sublime Text,超过 30% 喜欢 Atom 和它的开源复制版。超过 25%  WebStorm  和 vi/vim。

An screenshot of the percentages for the 22th question

你首选的开发系统是什么?

超过 60% 的人用的是 Mac,而 Linux 和 Windows 用户接近 20%。

An screenshot of the percentages for the 23th question

你如何找到可重用代码,库和工具?

受访者似乎赞成使用 Github 和搜索引擎,也有用博客、Twitter 和 npm  网站。

An screenshot of the percentages for the 24th question

你参与 JavaScript 社交事件吗?

近 60% 的人至少参加一个会议,而 74% 的人表示,他们喜欢去的聚会。

An screenshot of the percentages for the 25th question

你的 JavaScript 应用程序里支持什么浏览器?

很多样的答案,但幸运的是大多数的受访者没有使用 IE6 了

An screenshot of the percentages for the 26th question

你了解 JavaScript 的定期最新的功能吗?

当 JavaScript 有更新时,80% 受访者保持会去了解。

An screenshot of the percentages for the 27th question

你在哪里了解最新的 JavaScript 功能?

Mozilla 开发者网络在 JavaScript 领域和新闻更新上处于领先地位。JavaScript 周刊也非常流行,占了 40%。

An screenshot of the percentages for the 28th question

这些功能你听说过吗?

超过 85% 的选民听说过 ServiceWorker,我很好奇有多少人用它!

An screenshot of the percentages for the 29th question

除了 JavaScript,你还用什么语言?

有这么多的语言可供选择,我肯定会忘了一些,但结果不言自明。

An screenshot of the percentages for the 30th question

不管你在哪里上班,请记住以下黄金定律!

01. 不为模糊不清的未来担忧,只为清清楚楚的现在努力。

02. 只有先改变自己的态度,才能改变人生的高度。

03. 在抱怨自己赚钱少之前,先努力,学着让自己值钱。

04. 学历代表过去,学习能力才代表将来。

05. 耐得住寂寞才能守得住繁华,该奋斗的年龄不要选择了安逸。

06. 有些事情不是看到希望才去坚持,而是坚持了才看得到希望。

07. 压力不是有人比你努力,而是比你牛几倍的人依然在努力。

08. 你所做的事情,也许暂时看不到成功,但不要灰心,你不是没有成长,而是在扎根。

09. 现实和理想之间,不变的是跋涉,暗淡与辉煌之间,不变的是开拓。

跳槽穷半年,改行穷三年。献给每天喊辞职、想辞职的人或周期性喊辞职、想辞职的人!

1,不要轻易离开团队,否则你要从零做起 。

2,不要老想着做不顺就放弃,哪个团队都有问题,哪个团队都有优点。

3.跟对领导很重要,愿意教你的,放手让你做的领导,绝对要珍惜。

4.团队的问题就是你脱颖而出的机会,抱怨和埋怨团队就是打自己耳光,说自己无能,更是在放弃机会 !

5.心怀感恩之心,感谢系统给你平台,感谢伙伴给你配合。

6.创造利润是你存在的核心价值,创业不是做慈善 。

7.遇到问题请先思考,只反映问题是初级水平,思考并解决问题才是高级水平。

坚持不一定成功,坚持到底一定成功! 好好工作吧!

学会说话,给人温暖,给人鼓励,给人赞美,

给人信心,给人方便,给人希望,给人智慧!

2016年,不管你在哪里上班,请记住这个字!

第一则:

工作不养闲人,团队不养懒人。

第二则:

入一行, 先别惦记着能赚钱, 先学着让自己值钱。

第三则:

没有哪个行业的钱是好赚的。

第四则:

干工作,没有哪个是顺利的,受点气是正常的。

第五则:

赚不到钱,赚知识;

赚不到知识,赚经历;

赚不到经历,赚阅历;

以上都赚到了 就不可能赚不到钱。

第六则:

只有先改变自己的态度,才能改变人生的高度。

只有先改变自己的工作态度,才能有职业高度。

第七则:

让人迷茫的原因只有一个

——那就是本该拼搏的年纪,却想得太多,做得太少!

送君一个字:干!

本文整理自网络

版权归原作者所有,向原作者致敬!

curl上传文件的用法

用curl下载网页估计大家都会,但是模拟 multipart/form-data 形式的 form 上传文件则稍稍复杂些。命令行如下:

curl  -F "filename=@~/file.tar.gz" http://localhost/action.php

如果使用了-F参数,curl就会以 multipart/form-data 的方式发送POST请求。-F参数以name=value的方式来指定参数内容,如果值是一个文件,则需要以name=@file的方式来指定。

如果通过代理,上面的命令有可能会被代理拒绝,这时需要指定上传文件的MIME类型

curl -x myproxy.com:1080 -F "filename=@~/file.tar.gz;type=application/octet-stream" http://localhost/action.php

另外,如果不上传文件,则可以使用 -d 参数,这时curl会以application/x-www-url-encoded 方式发送 POST 请求。

url -d "action=del&name=archive" -d "id=12" http://localhost/action.php

如何在Git中撤销一切

翻译:李伟
审校:张帆
译自:Github

blob.png

任何一个版本控制系统中,最有用的特性之一莫过于 “撤销(undo)”操作。在Git中,“撤销”有很多种含义。

当你完成了一次新的提交(commit),Git会及时存储当前时刻仓库(repository)的快照(snapshot);你能够使用Git将项目回退到任何之前的版本。

下文中,我将列举几个常见的、需要“撤销”的场景,并且展示如何使用Git来完成这些操作。

一、撤销一个公共修改 Undo a “public” change

场景:你刚刚用git push将本地修改推送到了GitHub,这时你意识到在提交中有一个错误。你想撤销这次提交。

使用撤销命令:git revert

发生了什么:git revert将根据给定SHA的相反值,创建一个新的提交。如果旧提交是“matter”,那么新的提交就是“anti-matter”——旧提交中所有已移除的东西将会被添加进到新提交中,旧提交中增加的东西将在新提交中移除。

这是Git最安全、也是最简单的“撤销”场景,因为这样不会修改历史记录——你现在可以git push下刚刚revert之后的提交来纠正错误了。

二、修改最近一次的提交信息 Fix the last commit message

场景:你只是在最后的提交信息中敲错了字,比如你敲了git commit -m “Fxies bug #42″,而在执行git push之前你已经意识到你应该敲”Fixes bug #42″。

使用撤销命令:git commit –amend或git commit –amend -m “Fixes bug #42”

发生了什么:git commit –amend将使用一个包含了刚刚错误提交所有变更的新提交,来更新并替换这个错误提交。由于没有staged的提交,所以实际上这个提交只是重写了先前的提交信息。

三、撤销本地更改 Undo “local” changes

场景:当你的猫爬过键盘时,你正在编辑的文件恰好被保存了,你的编辑器也恰在此时崩溃了。此时你并没有提交过代码。你期望撤销这个文件中的所有修改——将这个文件回退到上次提交的状态。

使用撤销命令:git checkout —

发生了什么:git checkout将工作目录(working directory)里的文件修改成先前Git已知的状态。你可以提供一个期待回退分支的名字或者一个确切的SHA码,Git也会默认检出HEAD——即:当前分支的上一次提交。

注意:用这种方法“撤销”的修改都将真正的消失。它们永远不会被提交。因此Git不能恢复它们。此时,一定要明确自己在做什么!(或许可以用git diff来确定)

四、重置本地修改 Reset “local” changes

场景:你已经在本地做了一些提交(还没push),但所有的东西都糟糕透了,你想撤销最近的三次提交——就像它们从没发生过一样。

使用撤销命令:git reset或git reset –hard

发生了什么:git reset将你的仓库纪录一直回退到指定的最后一个SHA代表的提交,那些提交就像从未发生过一样。默认情况下,git reset会保留工作目录(working directory)。这些提交虽然消失了,但是内容还在磁盘上。这是最安全的做法,但通常情况是:你想使用一个命令来“撤销”所有提交和本地修改——那 么请使用–hard参数吧。

五、撤销本地后重做 Redo after undo “local”

场景:你已经提交了一些内容,并使用git reset –hard撤销了这些更改(见上面),突然意识到:你想还原这些修改!

使用撤销命令:git reflog和git reset, 或者git checkout

发生了什么:git reflog是一个用来恢复项目历史记录的好办法。你可以通过git reflog恢复几乎任何已提交的内容。

你或许对git log命令比较熟悉,它能显示提交列表。git reflog与之类似,只不过git reflog显示的是HEAD变更次数的列表。

一些说明:

1. 只有HEAD会改变。当你切换分支时,用git commit提交变更时,或是用git reset撤销提交时,HEAD都会改变。但当你用git checkout –时, HEAD不会发生改变。(就像上文提到的情形,那些更改根本就没有提交,因此reflog就不能帮助我们进行恢复了)

2.  git reflog不会永远存在。Git将会定期清理那些“不可达(unreachable)”的对象。不要期望能够在reflog里找到数月前的提交记录。

3.  reflog只是你个人的。你不能用你的reflog来恢复其他开发者未push的提交。

blob.png

因此,怎样合理使用reflog来找回之前“未完成”的提交呢?这要看你究竟要做什么:

1. 如果你想恢复项目历史到某次提交,那请使用git reset –hard

2. 如果你想在工作目录(working direcotry)中恢复某次提交中的一个或多个文件,并且不改变提交历史,那请使用git checkout–

3. 如果你想确切的回滚到某次提交,那么请使用git cherry-pick。

六、与分支有关的那些事 Once more, with branching

场景:你提交了一些变更,然后你意识到你正在master分支上,但你期望的是在feature分支上执行这些提交。

使用撤销命令:git branch feature, git reset –hard origin/master, 和 git checkout feature

发生了什么:你可能用的是git checkout -b来建立新的分支,这是创建和检出分支的便捷方法——但实际你并不想立刻切换分支。git branch feature会建立一个叫feature的分支,这个分支指向你最近的提交,但是你还停留在master分支上。

git reset –hard将master回退至origin/master,并忽略所有新提交。别担心,那些提交都还保留在feature上。

最后,git checkout将分支切换到feature,这个分支原封不动的保留了你最近的所有工作。

七、事半功倍处理分支 Branch in time saves nine

场景:你基于master新建了一个feature分支,但是master分支远远落后与origin/master。现在master分支与origin/master同步了,你期望此刻能在feature下立刻commit代码,并且不是在远远落后master的情况下。

使用撤销命令:git checkout feature和git rebase master

发生了什么:你也许已经敲了命令:git reset(但是没用–hard,有意在磁盘上保存这些提交内容),然后敲了git checkout -b,之后重新提交更改,但是那样的话,你将失去本地的提交记录。不过,一个更好的方法:

使用git rebase master可以做到一些事情:

1.首先,它定位你当前检出分支和master之间的共同祖先节点(common ancestor)。

2.然后,它将当前检出的分支重置到祖先节点(ancestor),并将后来所有的提交都暂存起来。

3.最后,它将当前检出分支推进至master末尾,同时在master最后一次提交之后,再次提交那些在暂存区的变更。

八、批量撤销/找回 Mass undo/redo

场景:你开始朝一个既定目标开发功能,但是中途你感觉用另一个方法更好。你已经有十几个提交,但是你只想要其中的某几个,其他的都可以删除不要。

使用撤销命令:git rebase -i

发生了什么:-i将rebases设置为“交互模式(interactive mode)”。rebase开始执行的操作就像上文讨论的一样,但是在重新执行某个提交时,它会暂停下来,让你修改每一次提交。

rebase –i将会打开你的默认文本编辑器,然后列出正在执行的提交,就像这样:

blob.png

前两列最关键:第一列是选择命令,它会根据第二列中的SHA码选择相应的提交。默认情况下,rebase –i会认为每个更改都正通过pick命令被提交。

要撤销一个提交,直接在编辑器删除对应的行就可以了。如果在你的项目不再需要这些错误的提交,你可以直接删除上图中的第1行和3-4行。

如 果你想保留提交但修改提交信息,你可以使用reword命令。即,将命令关键字pick换成reword(或者r)。你现在可能想立刻修改提交消息,但这 么做不会生效——rebase –i将忽略SHA列后的所有东西。现有的提交信息会帮助我们记住0835fe2代表什么。当你敲完rebase –i命令后,Git才开始提示你重写那些新提交消息。

如果你需要将2个提交合并,你可以用squash或者fixup命令,如下图:

blob.png

squash和fixup都是“向上”结合的——那些用了这些合并命令(编者按:指squash、fixup)的提交,将会和它之前的提交合并:上图中,0835fe2和6943e85将会合并成一个提交,而38f5e4e和af67f82将会合并成另一个提交。

当 你用squash时,Git将会提示是否填写新的提交消息;fixup则会给出列表中第一个提交的提交信息。在上图中,af67f82是一个 “Ooops”信息,因为这个提交信息已经同38f5e4e一样了。但是你可以为0835fe2和6943e85合并的新提交编写提交信息。

当你保存并退出编辑器时,Git将会按照从上到下的顺序执行你的提交。你可以在保存这些提交之前,修改提交的执行顺序。如果有需要,你可以将af67f82和0835fe2合并,并且可以这样排序:

blob.png

九、修复早先的提交 Fix an earlier commit

场景:之前的提交里落下了一个文件,如果先前的提交能有你留下的东西就好了。你还没有push,并且这个提交也不是最近的提交,因此你不能用commit –amend。

使用撤销命令:git commit –squash和git rebase –autosquash -i

发生了什么:git commit –squash将会创建一个新的提交,该提交信息可能像这样“squash! Earlier commit”。(你也可以手写这些提交信息,commit –squash只是省得让你打字了)。

如果你不想为合并的提交编写信息,也可以考虑使用命令git commit –fixup。这种情况下,你可能会使用commit –fixup,因为你仅希望在rebase中使用之前的提交信息。

rebase –autosquash –i将会启动rebase交互编辑器,编辑器会列出任何已完成的squash!和fixup!提交,如下图:

blob.png

当 使用–squash和–fixup时,你或许记不清你想修复的某个提交的SHA码——只知道它可能在一个或五个提交之前。你或许可以使用Git的^和~ 操作符手动找回。HEAD^表示HEAD的前一次提交。HEAD~4表示HEAD前的4次提交,加起来总共是前5次提交。

十、停止跟踪一个已被跟踪的文件 Stop tracking a tracked file

场景:你意外将application.log添加到仓库中,现在你每次运行程序,Git都提示application.log中有unstaged的提交。你在.gitignore中写上”*.log”,但仍旧没用——怎样告诉Git“撤销”跟踪这个文件的变化呢?

使用撤销命令: git rm –cached application.log

发生了什么:尽 管.gitignore阻止Git跟踪文件的变化,甚至是之前没被跟踪的文件是否存在,但是,一旦文件被add或者commit,Git会开始持续跟踪这 个文件的变化。类似的,如果你用git add –f来“强制”add,或者覆盖.gitignore,Git还是会继续监视变化。所以以后最好不要使用–f来add .gitignore文件。

如果你希望移除那些应当被忽略的文件,git rm –cached可以帮助你,并将这些文件保留在磁盘上。因为这个文件现在被忽略了,你将不会在git status中看到它,也不会再把这个文件commit了。

以上就是如何在Git上撤销的方法。如果你想学习更多Git命令用法,可以移步下面相关的文档:

原文地址:Github

译文地址:http://www.jointforce.com/jfperiodical/article/show/796?m=d03

常用Web Service汇总(天气预报、时刻表等)

现成的Web Service中有很多很好用的,比如天气预报,IP地址搜索,火车时刻表等等。本文汇总的一些常用Web Service,希望对大家有所帮助。

下面总结了一些常用的Web Service,是平时乱逛时收集的,希望对大家有用。

============================================

天气预报Web Service,数据来源于中国气象局

Endpoint

Disco

WSDL

IP地址来源搜索Web Service(是目前最完整的IP地址数据)

Endpoint

Disco

WSDL

随机英文、数字和中文简体字Web Service

Endpoint

Disco

WSDL

中国邮政编码 <-> 地址信息双向查询/搜索Web Service

Endpoint

Disco

WSDL

验证码图片Web Service 支持中文、字母、数字 图像和多媒体

Endpoint

Disco

WSDL

Email 电子邮件地址验证Web Service

Endpoint

Disco

WSDL

中文简体字 <->繁体字转换Web Service

Endpoint

Disco

WSDL

中文 <-> 英文双向翻译Web Service

Endpoint

Disco

WSDL

火车时刻表Web Service (第六次提速最新列车时刻表)

Endpoint

Disco

WSDL

中国股票行情数据Web Service(支持深圳和上海股市的基金、债券和股票)

Endpoint

Disco

WSDL

即时外汇汇率数据Web Service

Endpoint

Disco

WSDL

腾讯QQ在线状态Web Service

Endpoint

Disco

WSDL

中国电视节目预告(电视节目表)Web Service

Endpoint

Disco

WSDL

外汇-人民币即时报价Web Service

Endpoint

Disco

WSDL

中国股票行情分时走势预览缩略图Web Service

Endpoint

Disco

WSDL

国内飞机航班时刻表 Web Service

Endpoint

Disco

WSDL

中国开放式基金数据Web Service

Endpoint

Disco

WSDL

股票行情数据 Web Service(支持香港、深圳、上海基金、债券和股票;支持多股票同时查询)

Endpoint

Disco

WSDL

来源:http://developer.51cto.com/art/200908/147125.htm

[原创] Maven Surefire Plugin Using POJO Tests 使用 Junit 或 TestNg 测试类默认命名规范

开始时候 运行测试用例发现只有部分运行了,始终找不到原因

原来在单元测试时候默认 规范可以使用三种,但是网上找到的都是互相抄袭地错误方法

JUnit 4以及TestNG。

在默认情况下,maven-surefire-plugin的test目标会自动执行测试源码路径

(默认为src/test/java/)下所有符合一组命名模式的测试类。这组模式为:

**/Test*.java:任何子目录下所有命名以Test开关的Java类。

**/*TestCase.java:任何子目录下所有命名以TestCase结尾的Java类。

**/*Test.java:任何子目录下所有命名以Test结尾的Java类。

但是 Maven Surefire 只支持一种: 如果需要其他规则要手动写到配置文件里

POJO tests look very much like JUnit or TestNG tests, though they do not require dependencies on these artifacts. A test class should be named **/*Test and should contain test* methods which will each be executed by Surefire.

https://maven.apache.org/surefire/maven-surefire-plugin/examples/pojo-test.html

另外有返回值的方法, TestNG 需要使用 <suite allow-return-values=”true”> 配置,默认会跳过

[转][Google Guava] 强大的集合工具类:java.util.Collections中未包含的集合工具

原文链接 译文链接 译者:沈义扬,校对:丁一

尚未完成: Queues, Tables工具类

任何对JDK集合框架有经验的程序员都熟悉和喜欢java.util.Collections包含的工具方法。Guava沿着这些路线提供了更多的工具方法:适用于所有集合的静态方法。这是Guava最流行和成熟的部分之一。

我们用相对直观的方式把工具类与特定集合接口的对应关系归纳如下:

集合接口 属于JDK还是Guava 对应的Guava工具类
Collection JDK Collections2:不要和java.util.Collections混淆
List JDK Lists
Set JDK Sets
SortedSet JDK Sets
Map JDK Maps
SortedMap JDK Maps
Queue JDK Queues
Multiset Guava Multisets
Multimap Guava Multimaps
BiMap Guava Maps
Table Guava Tables

在找类似转化、过滤的方法?请看第四章,函数式风格。

静态工厂方法

在JDK 7之前,构造新的范型集合时要讨厌地重复声明范型:

List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<TypeThatsTooLongForItsOwnGood>();

我想我们都认为这很讨厌。因此Guava提供了能够推断范型的静态工厂方法:

List<TypeThatsTooLongForItsOwnGood> list = Lists.newArrayList();
Map<KeyType, LongishValueType> map = Maps.newLinkedHashMap();

可以肯定的是,JDK7版本的钻石操作符(<>)没有这样的麻烦:

List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<>();

但Guava的静态工厂方法远不止这么简单。用工厂方法模式,我们可以方便地在初始化时就指定起始元素。

Set<Type> copySet = Sets.newHashSet(elements);
List<String> theseElements = Lists.newArrayList("alpha", "beta", "gamma");

此外,通过为工厂方法命名(Effective Java第一条),我们可以提高集合初始化大小的可读性:

List<Type> exactly100 = Lists.newArrayListWithCapacity(100);
List<Type> approx100 = Lists.newArrayListWithExpectedSize(100);
Set<Type> approx100Set = Sets.newHashSetWithExpectedSize(100);

确切的静态工厂方法和相应的工具类一起罗列在下面的章节。

注意:Guava引入的新集合类型没有暴露原始构造器,也没有在工具类中提供初始化方法。而是直接在集合类中提供了静态工厂方法,例如:

Multiset<String> multiset = HashMultiset.create();

Iterables

在可能的情况下,Guava提供的工具方法更偏向于接受Iterable而不是Collection类型。在Google,对于不存放在主存的集合 ——比如从数据库或其他数据中心收集的结果集,因为实际上还没有攫取全部数据,这类结果集都不能支持类似size()的操作 ——通常都不会用Collection类型来表示。

因此,很多你期望的支持所有集合的操作都在Iterables类中。大多数Iterables方法有一个在Iterators类中的对应版本,用来处理Iterator。

截至Guava 1.2版本,Iterables使用FluentIterable进行了补充,它包装了一个Iterable实例,并对许多操作提供了”fluent”(链式调用)语法。

下面列出了一些最常用的工具方法,但更多Iterables的函数式方法将在第四章讨论。

常规方法

concat(Iterable<Iterable>) 串联多个iterables的懒视图* concat(Iterable...)
frequency(Iterable, Object) 返回对象在iterable中出现的次数 与Collections.frequency (Collection,   Object)比较;Multiset
partition(Iterable, int) 把iterable按指定大小分割,得到的子集都不能进行修改操作 Lists.partition(List, int)paddedPartition(Iterable, int)
getFirst(Iterable, T default) 返回iterable的第一个元素,若iterable为空则返回默认值 与Iterable.iterator(). next()比较;FluentIterable.first()
getLast(Iterable) 返回iterable的最后一个元素,若iterable为空则抛出NoSuchElementException getLast(Iterable, T default)
FluentIterable.last()
elementsEqual(Iterable, Iterable) 如果两个iterable中的所有元素相等且顺序一致,返回true 与List.equals(Object)比较
unmodifiableIterable(Iterable) 返回iterable的不可变视图 与Collections. unmodifiableCollection(Collection)比较
limit(Iterable, int) 限制iterable的元素个数限制给定值 FluentIterable.limit(int)
getOnlyElement(Iterable) 获取iterable中唯一的元素,如果iterable为空或有多个元素,则快速失败 getOnlyElement(Iterable, T default)

*译者注:懒视图意味着如果还没访问到某个iterable中的元素,则不会对它进行串联操作。

Iterable<Integer> concatenated = Iterables.concat(
        Ints.asList(1, 2, 3),
        Ints.asList(4, 5, 6)); // concatenated包括元素 1, 2, 3, 4, 5, 6
String lastAdded = Iterables.getLast(myLinkedHashSet);
String theElement = Iterables.getOnlyElement(thisSetIsDefinitelyASingleton);
//如果set不是单元素集,就会出错了!

与Collection方法相似的工具方法

通常来说,Collection的实现天然支持操作其他Collection,但却不能操作Iterable。

下面的方法中,如果传入的Iterable是一个Collection实例,则实际操作将会委托给相应的Collection接口方法。例如,往 Iterables.size方法传入是一个Collection实例,它不会真的遍历iterator获取大小,而是直接调用 Collection.size。

方法 类似的Collection方法 等价的FluentIterable方法
addAll(Collection addTo,   Iterable toAdd) Collection.addAll(Collection)
contains(Iterable, Object) Collection.contains(Object) FluentIterable.contains(Object)
removeAll(Iterable   removeFrom, Collection toRemove) Collection.removeAll(Collection)
retainAll(Iterable   removeFrom, Collection toRetain) Collection.retainAll(Collection)
size(Iterable) Collection.size() FluentIterable.size()
toArray(Iterable, Class) Collection.toArray(T[]) FluentIterable.toArray(Class)
isEmpty(Iterable) Collection.isEmpty() FluentIterable.isEmpty()
get(Iterable, int) List.get(int) FluentIterable.get(int)
toString(Iterable) Collection.toString() FluentIterable.toString()

FluentIterable

除了上面和第四章提到的方法,FluentIterable还有一些便利方法用来把自己拷贝到不可变集合

ImmutableList
ImmutableSet toImmutableSet()
ImmutableSortedSet toImmutableSortedSet(Comparator)

Lists

除了静态工厂方法和函数式编程方法,Lists为List类型的对象提供了若干工具方法。

方法 描述
partition(List, int) 把List按指定大小分割
reverse(List) 返回给定List的反转视图。注: 如果List是不可变的,考虑改用ImmutableList.reverse()
List countUp = Ints.asList(1, 2, 3, 4, 5);
List countDown = Lists.reverse(theList); // {5, 4, 3, 2, 1}
List<List> parts = Lists.partition(countUp, 2);//{{1,2}, {3,4}, {5}}

静态工厂方法

Lists提供如下静态工厂方法:

具体实现类型 工厂方法
ArrayList basic, with elements, from Iterable, with exact capacity, with expected size, from Iterator
LinkedList basic, from Iterable

Sets

Sets工具类包含了若干好用的方法。

集合理论方法

我们提供了很多标准的集合运算(Set-Theoretic)方法,这些方法接受Set参数并返回SetView,可用于:

  • 直接当作Set使用,因为SetView也实现了Set接口;
  • copyInto(Set)拷贝进另一个可变集合;
  • immutableCopy()对自己做不可变拷贝。
方法
union(Set, Set)
intersection(Set, Set)
difference(Set, Set)
symmetricDifference(Set,   Set)

使用范例:

Set<String> wordsWithPrimeLength = ImmutableSet.of("one", "two", "three", "six", "seven", "eight");
Set<String> primes = ImmutableSet.of("two", "three", "five", "seven");
SetView<String> intersection = Sets.intersection(primes,wordsWithPrimeLength);
// intersection包含"two", "three", "seven"
return intersection.immutableCopy();//可以使用交集,但不可变拷贝的读取效率更高

其他Set工具方法

方法 描述 另请参见
cartesianProduct(List<Set>) 返回所有集合的笛卡儿积 cartesianProduct(Set...)
powerSet(Set) 返回给定集合的所有子集
Set<String> animals = ImmutableSet.of("gerbil", "hamster");
Set<String> fruits = ImmutableSet.of("apple", "orange", "banana");

Set<List<String>> product = Sets.cartesianProduct(animals, fruits);
// {{"gerbil", "apple"}, {"gerbil", "orange"}, {"gerbil", "banana"},
//  {"hamster", "apple"}, {"hamster", "orange"}, {"hamster", "banana"}}

Set<Set<String>> animalSets = Sets.powerSet(animals);
// {{}, {"gerbil"}, {"hamster"}, {"gerbil", "hamster"}}

静态工厂方法

Sets提供如下静态工厂方法:

具体实现类型 工厂方法
HashSet basic, with elements, from Iterable, with expected size, from Iterator
LinkedHashSet basic, from Iterable, with expected size
TreeSet basic, with Comparator, from Iterable

Maps

Maps类有若干值得单独说明的、很酷的方法。

uniqueIndex

Maps.uniqueIndex(Iterable,Function)通常针对的场景是:有一组对象,它们在某个属性上分别有独一无二的值,而我们希望能够按照这个属性值查找对象——译者注:这个方法返回一个Map,键为Function返回的属性值,值为Iterable中相应的元素,因此我们可以反复用这个Map进行查找操作。

比方说,我们有一堆字符串,这些字符串的长度都是独一无二的,而我们希望能够按照特定长度查找字符串:

ImmutableMap<Integer, String> stringsByIndex = Maps.uniqueIndex(strings,
    new Function<String, Integer> () {
        public Integer apply(String string) {
            return string.length();
        }
    });

如果索引值不是独一无二的,请参见下面的Multimaps.index方法。

difference

Maps.difference(Map, Map)用来比较两个Map以获取所有不同点。该方法返回MapDifference对象,把不同点的维恩图分解为:

entriesInCommon() 两个Map中都有的映射项,包括匹配的键与值
entriesDiffering() 键相同但是值不同值映射项。返回的Map的值类型为MapDifference.ValueDifference,以表示左右两个不同的值
entriesOnlyOnLeft() 键只存在于左边Map的映射项
entriesOnlyOnRight() 键只存在于右边Map的映射项
Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
MapDifference<String, Integer> diff = Maps.difference(left, right);

diff.entriesInCommon(); // {"b" => 2}
diff.entriesInCommon(); // {"b" => 2}
diff.entriesOnlyOnLeft(); // {"a" => 1}
diff.entriesOnlyOnRight(); // {"d" => 5}

处理BiMap的工具方法

Guava中处理BiMap的工具方法在Maps类中,因为BiMap也是一种Map实现。

BiMap工具方法 相应的Map工具方法
synchronizedBiMap(BiMap) Collections.synchronizedMap(Map)
unmodifiableBiMap(BiMap) Collections.unmodifiableMap(Map)

静态工厂方法

Maps提供如下静态工厂方法:

具体实现类型 工厂方法
HashMap basic, from Map, with expected size
LinkedHashMap basic, from Map
TreeMap basic, from Comparator, from SortedMap
EnumMap from Class, from Map
ConcurrentMap:支持所有操作 basic
IdentityHashMap basic

Multisets

标准的Collection操作会忽略Multiset重复元素的个数,而只关心元素是否存在于Multiset中,如containsAll方法。为此,Multisets提供了若干方法,以顾及Multiset元素的重复性:

方法 说明 Collection方法的区别
containsOccurrences(Multiset   sup, Multiset sub) 对任意o,如果sub.count(o)<=super.count(o),返回true Collection.containsAll忽略个数,而只关心sub的元素是否都在super中
removeOccurrences(Multiset   removeFrom, Multiset toRemove) 对toRemove中的重复元素,仅在removeFrom中删除相同个数。 Collection.removeAll移除所有出现在toRemove的元素
retainOccurrences(Multiset   removeFrom, Multiset toRetain) 修改removeFrom,以保证任意o都符合removeFrom.count(o)<=toRetain.count(o) Collection.retainAll保留所有出现在toRetain的元素
intersection(Multiset,   Multiset) 返回两个multiset的交集; 没有类似方法
Multiset<String> multiset1 = HashMultiset.create();
multiset1.add("a", 2);

Multiset<String> multiset2 = HashMultiset.create();
multiset2.add("a", 5);

multiset1.containsAll(multiset2); //返回true;因为包含了所有不重复元素,
//虽然multiset1实际上包含2个"a",而multiset2包含5个"a"
Multisets.containsOccurrences(multiset1, multiset2); // returns false

multiset2.removeOccurrences(multiset1); // multiset2 现在包含3个"a"
multiset2.removeAll(multiset1);//multiset2移除所有"a",虽然multiset1只有2个"a"
multiset2.isEmpty(); // returns true

Multisets中的其他工具方法还包括:

copyHighestCountFirst(Multiset) 返回Multiset的不可变拷贝,并将元素按重复出现的次数做降序排列
unmodifiableMultiset(Multiset) 返回Multiset的只读视图
unmodifiableSortedMultiset(SortedMultiset) 返回SortedMultiset的只读视图
Multiset<String> multiset = HashMultiset.create();
multiset.add("a", 3);
multiset.add("b", 5);
multiset.add("c", 1);

ImmutableMultiset highestCountFirst = Multisets.copyHighestCountFirst(multiset);
//highestCountFirst,包括它的entrySet和elementSet,按{"b", "a", "c"}排列元素

Multimaps

Multimaps提供了若干值得单独说明的通用工具方法

index

作为Maps.uniqueIndex的兄弟方法,Multimaps.index(Iterable, Function)通常针对的场景是:有一组对象,它们有共同的特定属性,我们希望按照这个属性的值查询对象,但属性值不一定是独一无二的。

比方说,我们想把字符串按长度分组。

ImmutableSet digits = ImmutableSet.of("zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine");
Function<String, Integer> lengthFunction = new Function<String, Integer>() {
    public Integer apply(String string) {
        return string.length();
    }
};

ImmutableListMultimap<Integer, String> digitsByLength= Multimaps.index(digits, lengthFunction);
/*
*  digitsByLength maps:
*  3 => {"one", "two", "six"}
*  4 => {"zero", "four", "five", "nine"}
*  5 => {"three", "seven", "eight"}
*/

invertFrom

鉴于Multimap可以把多个键映射到同一个值(译者注:实际上这是任何map都有的特性),也可以把一个键映射到多个值,反转Multimap也会很有用。Guava 提供了invertFrom(Multimap toInvert,
Multimap dest)
做这个操作,并且你可以自由选择反转后的Multimap实现。

注:如果你使用的是ImmutableMultimap,考虑改用ImmutableMultimap.inverse()做反转。

ArrayListMultimap<String, Integer> multimap = ArrayListMultimap.create();
multimap.putAll("b", Ints.asList(2, 4, 6));
multimap.putAll("a", Ints.asList(4, 2, 1));
multimap.putAll("c", Ints.asList(2, 5, 3));

TreeMultimap<Integer, String> inverse = Multimaps.invertFrom(multimap, TreeMultimap<String, Integer>.create());
//注意我们选择的实现,因为选了TreeMultimap,得到的反转结果是有序的
/*
* inverse maps:
*  1 => {"a"}
*  2 => {"a", "b", "c"}
*  3 => {"c"}
*  4 => {"a", "b"}
*  5 => {"c"}
*  6 => {"b"}
*/

forMap

想在Map对象上使用Multimap的方法吗?forMap(Map)把Map包装成SetMultimap。这个方法特别有用,例如,与Multimaps.invertFrom结合使用,可以把多对一的Map反转为一对多的Multimap。

Map<String, Integer> map = ImmutableMap.of("a", 1, "b", 1, "c", 2);
SetMultimap<String, Integer> multimap = Multimaps.forMap(map);
// multimap:["a" => {1}, "b" => {1}, "c" => {2}]
Multimap<Integer, String> inverse = Multimaps.invertFrom(multimap, HashMultimap<Integer, String>.create());
// inverse:[1 => {"a","b"}, 2 => {"c"}]

包装器

Multimaps提供了传统的包装方法,以及让你选择Map和Collection类型以自定义Multimap实现的工具方法。

只读包装 Multimap ListMultimap SetMultimap SortedSetMultimap
同步包装 Multimap ListMultimap SetMultimap SortedSetMultimap
自定义实现 Multimap ListMultimap SetMultimap SortedSetMultimap

自定义Multimap的方法允许你指定Multimap中的特定实现。但要注意的是:

  • Multimap假设对Map和Supplier产生的集合对象有完全所有权。这些自定义对象应避免手动更新,并且在提供给Multimap时应该是空的,此外还不应该使用软引用、弱引用或虚引用。
  • 无法保证修改了Multimap以后,底层Map的内容是什么样的。
  • 即使Map和Supplier产生的集合都是线程安全的,它们组成的Multimap也不能保证并发操作的线程安全性。并发读操作是工作正常的,但需要保证并发读写的话,请考虑用同步包装器解决。
  • 只有当Map、Supplier、Supplier产生的集合对象、以及Multimap存放的键值类型都是可序列化的,Multimap才是可序列化的。
  • Multimap.get(key)返回的集合对象和Supplier返回的集合对象并不是同一类型。但如果Supplier返回的是随机访问集合,那么Multimap.get(key)返回的集合也是可随机访问的。

请注意,用来自定义Multimap的方法需要一个Supplier参数,以创建崭新的集合。下面有个实现ListMultimap的例子——用TreeMap做映射,而每个键对应的多个值用LinkedList存储。

ListMultimap<String, Integer> myMultimap = Multimaps.newListMultimap(
    Maps.<String, Collection>newTreeMap(),
    new Supplier<LinkedList>() {
        public LinkedList get() {
            return Lists.newLinkedList();
        }
    });

Tables

Tables类提供了若干称手的工具方法。

自定义Table

堪比Multimaps.newXXXMultimap(Map, Supplier)工具方法,Tables.newCustomTable(Map, Supplier<Map>)允许你指定Table用什么样的map实现行和列。

// 使用LinkedHashMaps替代HashMaps
Table<String, Character, Integer> table = Tables.newCustomTable(
Maps.<String, Map<Character, Integer>>newLinkedHashMap(),
new Supplier<Map<Character, Integer>> () {
public Map<Character, Integer> get() {
return Maps.newLinkedHashMap();
}
});

transpose

transpose(Table<R, C, V>)方法允许你把Table<C, R, V>转置成Table<R, C, V>。例如,如果你在用Table构建加权有向图,这个方法就可以把有向图反转。

包装器

还有很多你熟悉和喜欢的Table包装类。然而,在大多数情况下还请使用ImmutableTable

Unmodifiable Table RowSortedTable

Oracle 数据泵详解[转]

一、EXPDP和IMPDP使用说明

Oracle Database 10g引入了最新的数据泵(Data Dump)技术,数据泵导出导入(EXPDP和IMPDP)的作用

1)实现逻辑备份和逻辑恢复.

2)在数据库用户之间移动对象.

3)在数据库之间移动对象

4)实现表空间搬移.

二、数据泵导出导入与传统导出导入的区别

在10g之前,传统的导出和导入分别使用EXP工具和IMP工具,从10g开始,不仅保留了原有的EXP和IMP工具,还提供了数据泵导出导入工具EXPDP和IMPDP.使用EXPDP和IMPDP时应该注意的事项:

1)EXP和IMP是客户端工具程序,它们既可以在可以客户端使用,也可以在服务端使用。

2)EXPDP和IMPDP是服务端的工具程序,他们只能在ORACLE服务端使用,不能在客户端使用。

3)IMP只适用于EXP导出文件,不适用于EXPDP导出文件;IMPDP只适用于EXPDP导出文件,而不适用于EXP导出文件。

数据泵导出包括导出表,导出方案,导出表空间,导出数据库4种方式.

三、Expdp参数

EXPDP命令行选项,可通过expdp help=y查看:

E:\emp>expdp help=y

Export: Release 10.2.0.1.0- Production on 星期日, 03 5月, 2009 17:54:49

Copyright (c) 2003, 2005, Oracle.  All rights reserved.

数据泵导出实用程序提供了一种用于在 Oracle 数据库之间传输

数据对象的机制。该实用程序可以使用以下命令进行调用:

示例: expdp scott/tigerDIRECTORY=dmpdir DUMPFILE=scott.dmp

您可以控制导出的运行方式。具体方法是: 在 ‘expdp’ 命令后输入

各种参数。要指定各参数, 请使用关键字:

格式: expdp KEYWORD=value 或 KEYWORD=(value1,value2,…,valueN)

示例: expdp scott/tigerDUMPFILE=scott.dmp DIRECTORY=dmpdir SCHEMAS=scott

或 TABLES=(T1:P1,T1:P2), 如果 T1 是分区表

USERID 必须是命令行中的第一个参数。

关键字               说明 (默认)

——————————————————————————

ATTACH                连接到现有作业, 例如 ATTACH [=作业名]。

COMPRESSION           减小有效的转储文件内容的大小

关键字值为: (METADATA_ONLY) 和 NONE。

CONTENT               指定要卸载的数据, 其中有效关键字为:

(ALL), DATA_ONLY 和 METADATA_ONLY。

DIRECTORY             供转储文件和日志文件使用的目录对象。

DUMPFILE              目标转储文件 (expdat.dmp) 的列表,

例如 DUMPFILE=scott1.dmp, scott2.dmp,dmpdir:scott3.dmp。

ENCRYPTION_PASSWORD   用于创建加密列数据的口令关键字。

ESTIMATE              计算作业估计值, 其中有效关键字为:

(BLOCKS) 和 STATISTICS。

ESTIMATE_ONLY         在不执行导出的情况下计算作业估计值。

EXCLUDE               排除特定的对象类型, 例如EXCLUDE=TABLE:EMP。

FILESIZE              以字节为单位指定每个转储文件的大小。

FLASHBACK_SCN         用于将会话快照设置回以前状态的 SCN。

FLASHBACK_TIME        用于获取最接近指定时间的 SCN 的时间。

FULL                  导出整个数据库 (N)。

HELP                  显示帮助消息 (N)。

INCLUDE               包括特定的对象类型, 例如INCLUDE=TABLE_DATA。

JOB_NAME              要创建的导出作业的名称。

LOGFILE               日志文件名 (export.log)。

NETWORK_LINK          链接到源系统的远程数据库的名称。

NOLOGFILE             不写入日志文件 (N)。

PARALLEL              更改当前作业的活动 worker 的数目。

PARFILE               指定参数文件。

QUERY                 用于导出表的子集的谓词子句。

SAMPLE                要导出的数据的百分比;

SCHEMAS               要导出的方案的列表 (登录方案)。

STATUS                在默认值 (0) 将显示可用时的新状态的情况下,

要监视的频率 (以秒计) 作业状态。

TABLES                标识要导出的表的列表 – 只有一个方案。

TABLESPACES           标识要导出的表空间的列表。

TRANSPORT_FULL_CHECK  验证所有表的存储段 (N)。

TRANSPORT_TABLESPACES 要从中卸载元数据的表空间的列表。

VERSION               要导出的对象的版本, 其中有效关键字为:

(COMPATIBLE), LATEST 或任何有效的数据库版本。

下列命令在交互模式下有效。

注: 允许使用缩写

命令               说明

——————————————————————————

ADD_FILE              向转储文件集中添加转储文件。

CONTINUE_CLIENT       返回到记录模式。如果处于空闲状态, 将重新启动作业。

EXIT_CLIENT           退出客户机会话并使作业处于运行状态。

FILESIZE              后续 ADD_FILE 命令的默认文件大小 (字节)。

HELP                  总结交互命令。

KILL_JOB              分离和删除作业。

PARALLEL              更改当前作业的活动 worker 的数目。

PARALLEL=<worker 的数目>。

START_JOB             启动/恢复当前作业。

STATUS                在默认值 (0) 将显示可用时的新状态的情况下,

要监视的频率 (以秒计) 作业状态。

STATUS[=interval]

STOP_JOB              顺序关闭执行的作业并退出客户机。

STOP_JOB=IMMEDIATE 将立即关闭

数据泵作业。

1)ATTACH

该选项用于在客户会话与已存在导出作用之间建立关联.语法如下

ATTACH=[schema_name.]job_name

Schema_name用于指定方案名,job_name用于指定导出作业名.注意,如果使用ATTACH选项在命令行除了连接字符串和ATTACH选项外,不能指定任何其他选项,示例如下:

Expdp scott/tiger ATTACH=scott.export_job

2) CONTENT

该选项用于指定要导出的内容.默认值为ALL

CONTENT={ALL | DATA_ONLY | METADATA_ONLY}

当设置CONTENT为ALL 时,将导出对象定义及其所有数据.为DATA_ONLY时,只导出对象数据,为METADATA_ONLY时,只导出对象定义

Expdp scott/tiger DIRECTORY=dumpDUMPFILE=a.dump

CONTENT=METADATA_ONLY

3) DIRECTORY

指定转储文件和日志文件所在的目录

DIRECTORY=directory_object

Directory_object用于指定目录对象名称.需要注意,目录对象是使用CREATE DIRECTORY语句建立的对象,而不是OS 目录

Expdp scott/tiger DIRECTORY=dumpDUMPFILE=a.dump

建立目录:

SQL> createdirectory dump_dir as ‘d:\dump’;

目录已创建。

SQL> grantread,write on directory dump_dir to scott;

授权成功。

查询创建了那些子目录:

SELECT * FROM dba_directories;

4) DUMPFILE

用于指定转储文件的名称,默认名称为expdat.dmp

DUMPFILE=[directory_object:]file_name [,….]

Directory_object用于指定目录对象名,file_name用于指定转储文件名.需要注意,如果不指定directory_object,导出工具会自动使用DIRECTORY选项指定的目录对象

Expdp scott/tiger DIRECTORY=dump1DUMPFILE=dump2:a.dmp

5.)ESTIMATE

指定估算被导出表所占用磁盘空间分方法.默认值是BLOCKS

EXTIMATE={BLOCKS | STATISTICS}

设置为BLOCKS时,oracle会按照目标对象所占用的数据块个数乘以数据块尺寸估算对象占用的空间,设置为STATISTICS时,根据最近统计值估算对象占用空间

Expdp scott/tiger TABLES=empESTIMATE=STATISTICS

DIRECTORY=dump DUMPFILE=a.dump

6.)EXTIMATE_ONLY

指定是否只估算导出作业所占用的磁盘空间,默认值为N

EXTIMATE_ONLY={Y | N}

设置为Y时,导出作用只估算对象所占用的磁盘空间,而不会执行导出作业,为N时,不仅估算对象所占用的磁盘空间,还会执行导出操作.

Expdp scott/tiger ESTIMATE_ONLY=yNOLOGFILE=y

7.)EXCLUDE

该选项用于指定执行操作时释放要排除对象类型或相关对象

EXCLUDE=object_type[:name_clause] [,….]

Object_type用于指定要排除的对象类型,name_clause用于指定要排除的具体对象.EXCLUDE和INCLUDE不能同时使用

Expdp scott/tiger DIRECTORY=dumpDUMPFILE=a.dup EXCLUDE=VIEW

8)FILESIZE

指定导出文件的最大尺寸,默认为0,(表示文件尺寸没有限制)

9. FLASHBACK_SCN

指定导出特定SCN时刻的表数据

FLASHBACK_SCN=scn_value

Scn_value用于标识SCN值.FLASHBACK_SCN和FLASHBACK_TIME不能同时使用

Expdp scott/tiger DIRECTORY=dumpDUMPFILE=a.dmp

FLASHBACK_SCN=358523

10)FLASHBACK_TIME

指定导出特定时间点的表数据

FLASHBACK_TIME=”TO_TIMESTAMP(time_value)”

Expdp scott/tiger DIRECTORY=dumpDUMPFILE=a.dmp FLASHBACK_TIME=

“TO_TIMESTAMP(’25-08-200414:35:00’,’DD-MM-YYYYHH24:MI:SS’)”

11)FULL

指定数据库模式导出,默认为N

FULL={Y | N}

为Y时,标识执行数据库导出.

12)HELP

指定是否显示EXPDP命令行选项的帮助信息,默认为N

当设置为Y时,会显示导出选项的帮助信息.

Expdp help=y

13)INCLUDE

指定导出时要包含的对象类型及相关对象

INCLUDE = object_type[:name_clause] [,… ]

14)JOB_NAME

指定要导出作用的名称,默认为SYS_XXX

JOB_NAME=jobname_string

15)LOGFILE

指定导出日志文件文件的名称,默认名称为export.log

LOGFILE=[directory_object:]file_name

Directory_object用于指定目录对象名称,file_name用于指定导出日志文件名.如果不指定directory_object.导出作用会自动使用DIRECTORY的相应选项值.

Expdp scott/tiger DIRECTORY=dumpDUMPFILE=a.dmp logfile=a.log

16)NETWORK_LINK

指定数据库链名,如果要将远程数据库对象导出到本地例程的转储文件中,必须设置该选项.

17)NOLOGFILE

该选项用于指定禁止生成导出日志文件,默认值为N.

18)PARALLEL

指定执行导出操作的并行进程个数,默认值为1

19)PARFILE

指定导出参数文件的名称

PARFILE=[directory_path] file_name

20)QUERY

用于指定过滤导出数据的where条件

QUERY=[schema.] [table_name:] query_clause

Schema用于指定方案名,table_name用于指定表 名,query_clause用于指定条件限制子句.QUERY选项不能与 CONNECT=METADATA_ONLY,EXTIMATE_ONLY,TRANSPORT_TABLESPACES等选项同时使用.

Expdp scott/tiger directory=dumpdumpfiel=a.dmp

Tables=emp query=’WHERE deptno=20’

21)SCHEMAS

该方案用于指定执行方案模式导出,默认为当前用户方案.

22)STATUS

指定显示导出作用进程的详细状态,默认值为0

23)TABLES

指定表模式导出

TABLES=[schema_name.]table_name[:partition_name][,…]

Schema_name用于指定方案名,table_name用于指定导出的表名,partition_name用于指定要导出的分区名.

24)TABLESPACES

指定要导出表空间列表

25)TRANSPORT_FULL_CHECK

该选项用于指定被搬移表空间和未搬移表空间关联关系的检查方式,默认为N.

当设置为Y时,导出作用会检查表空间直接的完整关联关系,如果表空间所在表空间或其索 引所在的表空间只有一个表空间被搬移,将显示错误信息.当设置为N时,导出作用只检查单端依赖,如果搬移索引所在表空间,但未搬移表所在表空间,将显示出 错信息,如果搬移表所在表空间,未搬移索引所在表空间,则不会显示错误信息.

26)TRANSPORT_TABLESPACES

指定执行表空间模式导出

27)VERSION

指定被导出对象的数据库版本,默认值为COMPATIBLE.

VERSION={COMPATIBLE | LATEST |version_string}

为COMPATIBLE时,会根据初始化参数COMPATIBLE生成对象元数据;为LATEST时,会根据数据库的实际版本生成对象元数据.version_string用于指定数据库版本字符串.

 

四、EXPDP用法

使用EXPDP工具时,其转储文件只能被存放在DIRECTORY对象对应的OS目录中,而不能直接指定转储文件所在的OS目录.因此,使用EXPDP工具时,必须首先建立DIRECTORY对象.并且需要为数据库用户授予使用DIRECTORY对象权限.

CREATE DIRECTORY dump_dir AS ‘/tmp’;

GRANT READ, WRITE ON DIRECTORY dump_dir TO scott;

1、导出表

Expdp scott/tiger DIRECTORY=dump_dir DUMPFILE=dept.dmpTABLES=dept

注:在unix下要注意directory目录的读写权限问题,如:

查看dump_dir所在的目录:用sys用户查看数据字典dba_directories

更该该文件夹的权限:chown–R oracle:dba /exp,问题解决

2、导出方案

expdp scott/tiger directory=dump_dirdumpfile=schema.dmp logfile=schema.log schemas=system

3、导出表空间

expdp scott/tiger directory=dump_dirdumpfile=tb.dmp logfile=tb.log tablespaces=users

4、导出数据库

Expdp system/manager DIRECTORY=dump_dirDUMPFILE=full.dmp FULL=Y

Expdp scott/tiger DIRECTORY=dump_dirDUMPFILE=full.dmp FULL=Y

注:提示scott用户没有相应的权限,给scott相应的权限或使用system来做全库导出 。

SQL> grant exp_full_database to scott;

Grant succeeded.

然后在做全库的导出:

五、IMPDP参数

IMPDP与EXPDP的不同参数:

1、REMAP_DATAFILE

该选项用于将源数据文件名转变为目标数据文件名,在不同平台之间搬移表空间时可能需要该选项.

REMAP_DATAFIEL=source_datafie:target_datafile

2、REMAP_SCHEMA

该选项用于将源方案的所有对象装载到目标方案中.

REMAP_SCHEMA=source_schema:target_schema

3、REMAP_TABLESPACE

将源表空间的所有对象导入到目标表空间中

REMAP_TABLESPACE=source_tablespace:target:tablespace

4、REUSE_DATAFILES

该选项指定建立表空间时是否覆盖已存在的数据文件.默认为N

REUSE_DATAFIELS={Y | N}

5、SKIP_UNUSABLE_INDEXES

指定导入是是否跳过不可使用的索引,默认为N

6、SQLFILE

指定将导入要指定的索引DDL操作写入到SQL脚本中

SQLFILE=[directory_object:]file_name

Impdp scott/tiger DIRECTORY=dumpDUMPFILE=tab.dmp SQLFILE=a.sql

7、STREAMS_CONFIGURATION

指定是否导入流元数据(StreamMatadata),默认值为Y.

8、TABLE_EXISTS_ACTION

该选项用于指定当表已经存在时导入作业要执行的操作,默认为SKIP

TABBLE_EXISTS_ACTION={SKIP | APPEND |TRUNCATE | FRPLACE }

当设置该选项为SKIP时,导入作业会跳过已存在表处理下一个对象;当设置为 APPEND时,会追加数据,为TRUNCATE时,导入作业会截断表,然后为其追加新数据;当设置为REPLACE时,导入作业会删除已存在表,重建表 并追加数据,注意,TRUNCATE选项不适用与簇表和NETWORK_LINK选项

9、TRANSFORM

该选项用于指定是否修改建立对象的DDL语句

TRANSFORM=transform_name:value[:object_type]

Transform_name用于指定转换名,其中 SEGMENT_ATTRIBUTES用于标识段属性(物理属性,存储属性,表空间,日志等信息),STORAGE用于标识段存储性,VALUE用于指定 是否包含段属性或段存储属性,object_type用于指定对象类型.

Impdp scott/tiger directory=dumpdumpfile=tab.dmp

Transform=segment_attributes:n:table

10、TRANSPORT_DATAFILES

该选项用于指定搬移空间时要被导入到目标数据库的数据文件

TRANSPORT_DATAFILE=datafile_name

Datafile_name用于指定被复制到目标数据库的数据文件

Impdp system/manager DIRECTORY=dumpDUMPFILE=tts.dmp

TRANSPORT_DATAFILES=’/user/data/tbs1.f’

六、IMPDP用法

1、导入表

impdp hsiufo/hsiufo directory=dump_dirdumpfile=full.dmp tables=scott.emp remap_schema=scott:scott

注:上图为为有一个全库的逻辑备份 full.dmp,然后删除用户scott的emp表,在full.dmp中导入emp到用户scott

impdp hsiufo/hsiufo directory=dump_dirdumpfile=full.dmp tables=scott.test remap_schema=scott:system

第一种方法表示将EMP表导入到SCOTT方案中,第二种方法表示将test表导入的SYSTEM方案中.

注意,如果要将表导入到其他方案中,必须指定REMAP SCHEMA选项.

2、导入方案

impdp hsiufo/hsiufodirectory=dump_dir dumpfile=full.dmp schemas=scott

Impdp system/manager DIRECTORY=dump_dirDUMPFILE=schema.dmp

SCHEMAS=scott REMAP_SCHEMA=scott:system

3、导入表空间

Impdp system/manager DIRECTORY=dump_dirDUMPFILE=tablespace.dmp

TABLESPACES=user

4、导入数据库

Impdp system/manager DIRECTORY=dump_dirDUMPFILE=full.dmp FULL=y

来源:http://blog.csdn.net/jojo52013145/article/details/7966047

免费好用的MySQL数据库客户端图形界面管理工具

1. Workbench
MySQL Workbench — 可视化数据库设计
MySQLWorkbench 是一款可视化的数据库设计工具,它将SQL开发、管理和数据库设计、创建和维护融合到一个简单的开发环境中,它源自fabFORCE.net,是 DBDesigner4的接班人,并且更换了mysql GUI工具绑定。当前的版本是5.2,最开始的版本是5.0, 需要强调的 是,MySQLWorkbench是被视为DBDesinger 4的继承者来开发的。

下载地址:http://dev.mysql.com/downloads/workbench/

2. HeidiSQL

ConnectionHeidiSQL 之前被称为mySQL-Front,是由德国程序员AnsgarBecker和一些在Delhi领域有突出贡献的人开发的一款免费的开源客户端。用 HeidiSQL管理数据库,用户必须通过验证登录一个本地或者远程的MySQL服务器,创建一个会话(session). 在这个会话里,用户可以通过 连接MySQL服务器管理MySQL 数据库,会话结束会断开与服务器的连接。它的特征集对于大部分普通和高级的数据库,表和数据操作来说已经足够了,但 是为了让它趋向完美,它依然保持积极的开发状态。

一个由Java, jHeidi编写的版本,被设计用来工作在Mac和Linux电脑上,不幸的是,这个项目在2010年三月被叫停了。

官方网站:http://www.heidisql.com/

3.phpMyAdmin10-best-mysql-gui-tools5

PhpMyAdmin是由PHP编写的,目的在于通过Internet管理MySQL,PhpMyAdmin支持对MySQL的大范围的操作,最频繁的使用是数据库的管理、表格、字段、关系、索引、用户、权限。你也可以直接执行SQL语句。

官方网站:http://www.phpmyadmin.net/home_page/

4. Sequel Pro

10-best-mysql-gui-tools6Sequel Pro是一款免费的开源项目,它是CocoaMySQL 数据库管理系统的继承者, CocoaMySQL是LorenzTextor脑力劳动的产物, 而Lorenz Textor是从2003年开始,CocoaMySQL主要的开发者。

SequelPro用来管理MySQL数据库(本地或者internet),它允许你增加、删除数据库和表,更改字段、索引和视图,过滤table内容,增加、编辑和删除列,执行自定义查询和转存table和整个数据库
它兼容MySQL 3.x, 4 or 5.

官方网站:http://www.sequelpro.com/

5. MySQL Browser

MySQLBrowser的优点是简单,极其简单,安装之后能够立刻上手,马上就能使用的那种,布局也很简陋,功能也很简陋,简单使用没有问题,尤其是刚开始学习mysql的童鞋,可以尝试一下。

官方下载地址: http://dev.mysql.com/downloads/gui-tools/5.0.html

2015 年开源前端框架盘点 TOP 20

2015年已经过去了,作为一个前端开发者,我觉得有必要把过去一年帮助过我或朋友们的优秀开源前端框架做个盘点,希望这些项目能够越来越好,帮助到更多的前端开发者们。

此榜单根据github上star数作为排名依据,一个人力量有限,如果收集有遗漏欢迎补充。

 

1、名称:Bootstrap

类别/语言:HTML、CSS、JavaScript

创建者: Twitter

人气:在Github上有91007 stars

描述:主流框架中毋庸置疑的老大,Bootstrap 是基于 HTML、CSS、JavaScript 的,它简洁灵活,使得 Web 开发更加快捷。

核心概念/原则: RWD 和移动优先制。

浏览器支持: Firefox, Chrome, Safari, IE8+ (你需要 Respond.js for IE8)

响应式: Yes

模块化: Yes

官网地址:http://getbootstrap.com/

Github地址:https://github.com/twbs/bootstrap

 

2、名称:html5-boilerplate

类别/语言:HTML、CSS、JavaScript

创建者:Paul Irish

人气:在Github上有32,349 stars

描述:HTML5 Boilerplate 帮你构建 快速, 健壮, 并且 适应力强 的web app或网站。

核心概念/原则:响应式

浏览器支持:Firefox, Chrome, Safari, IE8+,Edge,Opera

预处理器:None

响应式:Yes

模块化:Yes

官网地址:https://html5boilerplate.com/

Github地址:https://github.com/h5bp/html5-boilerplate

 

3、名称:Meteor

类别/语言:HTML、CSS、JavaScript

创建者:immir

人气:在Github上有31,092 stars

描述:Meteor是新一代的开发即时web应用的开源框架,它能帮助你在最少的时间内完成开发。

核心概念/原则:响应式

预处理器: Less

响应式: Yes

模块化: Yes

官网地址:https://www.meteor.com

Github地址:https://github.com/meteor/meteor/

4、名称:Semantic UI

类别/语言:HTML、CSS、JavaScript

创建者: Jack Lukic

人气: 在Github上有22,325 stars

描述: “基于自然语言有效原则的UI组件框架”

核心概念/原则: 语义,标签的矛盾性、响应式

浏览器支持:Firefox, Chrome, Safari, IE10+ (IE9 with browser prefix only), Android 4, Blackberry 10。

预处理器: Less

响应式: Yes

模块化: Yes

官网地址:http://semantic-ui.com/

Github地址:https://github.com/Semantic-Org/Semantic-UI

5、名称:Foundation

类别/语言:HTML、CSS、JavaScript

创建者: ZURB
人气: 在Github上有22,206+ stars
描述: “世界上最优秀的响应式前端框架”
核心概念/原则: RWD 、手机优先、语义的

浏览器支持: Chrome, Firefox, Safari, IE9+; iOS, Android, Windows Phone 7+
预处理器: Sass
响应式: Yes
模块化: Yes

官网地址:http://foundation.zurb.com/

Github地址:https://github.com/zurb/foundation-sites

6、名称:Materialize

类别/语言:CSS

创建者:Google

人气:在Github上有15,288stars

描述:Materialize是一个个基于材料设计的一个现代化的响应式前端框架。他们做了最繁重的工作,为您提供默认的样式,结合了您的自定义组件。此外,他们还改进动画和过渡,为开发人员提供流畅的体验。

核心概念/原则:响应式

预处理器:Sass

响应式:Yes

模块化:Yes

官网地址:http://materializecss.com

Github地址:https://github.com/Dogfalo/materialize

浏览器支持:Chrome 35+, Firefox 31+, Safari 7+, IE 10+

7、名称:Pure

类别/语言:CSS

创建者: Yahoo

人气: 在Github上有13,161 stars

描述: “您可以在每一个web项目中使用的一组小的和响应式的CSS模块”

核心概念/原则:SMACSS,极简的.

浏览器支持:Firefox的最新版本, Chrome, Safari; IE7+; iOS 6.x, 7.x; Android 4.x

预处理器: None

响应式: Yes
模块化: Yes

官网地址:http://purecss.io/

Github地址:https://github.com/yahoo/pure

 

8、名称:Vue

类别/语言:CSS、JavaScript

创建者:尤雨溪

人气:在Github上有12,214 stars

描述:Vue.js 是用于构建交互式的 Web 界面的库。它提供了 MVVM 数据绑定和一个可组合的组件系统,具有简单、灵活的 API。

核心概念/原则:响应式

浏览器支持:Firefox, Chrome, Safari, IE10+,Android 4.2+,iOS 7+

预处理器:None

响应式:Yes

模块化:Yes

官网地址:http://vuejs.org/

Github地址:https://github.com/vuejs/vue

9、名称:Skeleton

类别/语言:CSS、JavaScript

创建者:Dave Gamache

人气:在Github上有10,622stars

描述:Skeleton 是一个小的 JS 和 CSS 文件的集合,可帮你快速开发漂亮的网站,适合各种屏幕设备包括手机。Skeleton 基于 960 grid 开发。它是一个 UI 框架。

核心概念/原则:响应式

浏览器支持:Firefox, Chrome, Safari, IE10+,Opera

预处理器:None

响应式:Yes

模块化:Yes

官网地址:http://www.getskeleton.com

Github地址:https://github.com/dhg/Skeleton

10.名称: Amaze UI

类别/语言:HTML、CSS、JavaScript

创建者:云适配

最后更新时间:2015年12月

人气:在Github上有6425 stars

描述:国内首个开源HTML5跨屏前端框架,中文排版支持更优、本土化组件丰富。

并在2015年11月推出基于 React.js 的专属移动端 Web 组件库Amaze UI touch。

核心概念/原则:组件化、移动优先、轻量级、高性能。

浏览器支持: Firefox, Chrome, Safari, IE8+

响应式: Yes

模块化: Yes

官网地址:http://amazeui.org/

Github地址:https://github.com/amazeui/amazeui

 

11、名称:UIkit

类别/语言:HTML、CSS、JavaScript

创建者: YOOtheme

人气: 在Github上有6,050+ stars

描述: “一个轻量级的和模块化的前端框架,用于快速开发和功能强大的web接口。”

核心概念/原则:RWD, 手机优先.

预处理器: Less, Sass

响应式: Yes

模块化: Yes

官网地址:http://getuikit.com/

Github地址:https://github.com/uikit/uikit

浏览器支持: Chrome, Firefox, Safari, IE9+

12、名称:Yui

类别/语言:CSS、JavaScript

创建者:Yahoo

人气:在Github上有3,200+ stars

描述:Yahoo! UI Library (YUI) 是一个开放源代码的 JavaScript 函数库,为了能建立一个高互动的网页,它采用了AJAX, DHTML 和 DOM 等程式码技术。它也包含了许多 CSS 资源。使用授权为 BSD许可证

核心概念/原则:响应式

预处理器: None

响应式:Yes

模块化:Yes

官网地址:http://yuilibrary.com/

Github地址:https://github.com/yui/yui3

浏览器支持:Firefox, Chrome, Safari, IE10+,Opera

13.名称:kissy

类别/语言: JavaScript

创建者:淘宝前端

最后更新时间:2015年7月

人气:在Github上有2035 stars

描述:KISSY 是一款跨终端、模块化、高性能、使用简单的 JavaScript 框架。

框架大小: 37 KB

核心概念/原则: 模块化,跨终端,高扩展性

模块化: Yes

官网地址:http://docs.kissyui.com/

Github地址:https://github.com/kissyteam/kissy/

14.名称:MUI

类别/语言: HTML、CSS、JavaScript

创建者:Dclould

最后更新时间:2016年1月

人气:在Github上有2012 stars

描述:MUI-最接近原生App体验的前端框架框架。

核心概念/原则: 多端发布、高性能

响应式: NO

模块化: Yes

官网地址:http://dev.dcloud.net.cn/mui/

Github地址:https://github.com/dcloudio/mui

15.名称:Arale

类别/语言: JavaScript

创建者:支付宝前端

最后更新时间:2015年7月

人气:在Github上有1252 stars

描述:Arale 是一个开放、简单、易用的前端基础类库。

框架大小:未知

核心概念/原则: 开放、简单、易用

浏览器支持:Firefox, Chrome, Safari, IE6+

响应式: Yes

模块化: Yes

官网地址:http://aralejs.org/

Github地址:https://github.com/aralejs/aralejs.org/

16.名称:JX

类别/语言:Javascript

创建者:腾讯前端

最后更新时间:2015年12月

人气:在Github上有952 stars

描述:JX 是模块化的非侵入式Web前端框架,特别适合构建和组织大规模、工业级的Web App。

框架大小: 未知

核心概念/原则: 保持最优执行效率

浏览器支持: 兼容主流浏览器

模块化: Yes

官网地址:http://alloyteam.github.io/JX/

Github地址:https://github.com/AlloyTeam/JX

 

17.名称:GMU

类别/语言:HTML、CSS、JavaScript

创建者:百度前端

最后更新时间:2015年12月

人气:在Github上有940stars

描述:GMU是基于zepto的mobile UI组件库,提供webapp、pad端简单易用的UI组件! Web App。

核心概念/原则: 简单易用、轻量级

模块化: Yes

官网地址:http://gmu.baidu.com/

Github地址:https://github.com/fex-team/GMU

 

18.名称:ZUI

类别/语言: HTML、CSS、JavaScript

创建者:蝉道

最后更新时间:2015年7月

人气:在Github上有616 stars

描述:开源HTML5前端框架

核心概念/原则:简单易用、轻量级、易于定制

浏览器支持:未知

官网地址:http://zui.sexy/

Github地址:https://github.com/easysoft/zui

19.名称:Clouda Touch.js

类别/语言:JavaScript

创建者:百度云

人气:在Github上有387 stars

描述:Touch.js是移动设备上的手势识别与事件库,也是在百度内部广泛使用的开发。

核心概念/原则: 无入侵设计、媲美原生的交互、极简的API

模块化: Yes

官网地址:http://touch.code.baidu.com/

Github地址:https://github.com/Clouda-team/touch.code.baidu.com

20.名称:Arkui

类别/语言:HTML、CSS、JavaScript

创建者:豆瓣

人气:在Github上有129 stars

模块化: Yes

官网地址:http://mockee.com/arkui/

Github地址:https://github.com/mockee/arkui

来源:http://www.oschina.net/news/69788/2015-opensource-frontend-framework-top20

15 位健在的牛叉程序员,你知道哪几位?

现如今程序员是越来越多了,所以优秀的程序员也是越来越多了。但是他们中哪些才是顶尖中的顶尖呢?

其实要明确地指出“哪一个”程序员是最优秀的,这几乎不太可能,但是业内的开发者们还是对这个话题乐此不疲。ITworld 就通过投票,以及对其他国外社区(比如 Quora、Reddit)中的数据进行分析,来判断排名和分析是否一致。结果,有一些名字确实在大家的讨论中反复出现。

下面就让我们来看看依然健在的最受大家认可的 15 位优秀程序员:

(小编先补充声明,下面排序并不是按个人成就。如果你喜欢的大牛排在后面了,别纠结别激动 ~≧▽≦~ )

1. Margaret Hamilton

主要成就:阿波罗计划飞行控制软件的幕后英雄

上榜理由:作为 Charlse Stark Draper 实验室软件工程部门的主任,她领导她的小组为 NASA 的阿波罗计划和Skylab任务设计并开发了飞行控制软件。基于在阿波罗计划中的工作成就,她随后研发了通用系统语言和 DBTF 开发范式。她开创性地提出了“异步软件、优先调度、以及高可信度软件设计”等概念。这些都成为日后“软件工程”的基础。她是1986年Augusta Ada Lovelace奖的获得者,并且在2003年获得了NASA杰出空间表现奖。

网友评价

  • ford_beeblebrox:Hamilton发明了软件测试,她可以算得上是美国计算机工程的创始人。
  • Dan Allen:我认为在她所做出成就之前(恕我冒昧,因为Knuth也被包括在这个范围当中),计算机编程(以及其相关的东西)都还只是数学的一个分支。然后一套航天飞行器的飞行控制软件清晰地把编程带向了一个不同的范式领域。
  • David Hamilton: …是她创造了“软件工程”这个词,然后又用例子告诉大家怎么做
  • Drukered:她太厉害了

推荐阅读

《就是这个美女程序员,写出了让阿波罗成功登陆月球的代码!》

(旁边是「著作等身」的阿波罗制导系统的代码)

2. Donald Knuth

主要成就:《计算机编程艺术》的作者

上榜理由:他写了一本关于计算机编程理论的决定性著作,发明了 TeX 数字排版系统。他是1971年第一届ACM Grace Murray Hopper奖的获得者(译者注:美国海军女少将 Grace Murray Hopper 也绝对是载入史册的计算机科学家和顶级程序员,可惜她已经去世,因此没有列入本文名单)。并且是计算机最高奖ACM图灵奖获得者(1974)(要知道当时 他才36岁),还是1979年美国国家科学奖章获得者以及IEEE冯诺依曼奖章获得者(1995)。并在1998年被任命为计算机历史博物馆名人堂成员。

网友评价:

  • 匿名:写《计算机编程艺术》这本书,估计是有史以来关于计算机编程最复杂的工作。
  • Jaap Weel:在我用过的计算机软件里面,只有一种是几乎没有 bug 的,那就是Don Knuth编写的TeX。这太让人印象深刻了。
  • 伯小乐补充:关于 TeX 几乎没 Bug,是真事。高德纳再一次用行动宣告,我这个东西(TeX),不可能再有什么大的改进了,最多只能小修小补,使其趋近完美。他还专门设立了奖金:谁发 现Tex的一个Bug,就付他2.56美元,第二个错误5.12美元,第三个10.24美元。请看此文:《程序员单枪匹马做的最复杂/重要的程序,是哪 个?》。不过真的有人拿到他的支票了。
  • Mitch Ree-Jones:让我评价他的话,那就是优秀得让人难以置信。

推荐阅读:

《程序员单枪匹马做的最复杂/重要的程序,是哪个?》、《高德纳谈计算机程序设计艺术(上)》和《高德纳谈计算机程序设计艺术(下)》

3. Ken Thompson

主要成就:Unix 缔造者

上榜理由:和 Dennis Ritchie 一起,共同缔造了Unix操作系统。他是 B 语言的发明人,以及 UTF-8 字符编码规范和 ed 文本编辑器的发明人。同时他还是 Go 编程语言的共同开发者之一。他和 Dennis Ritchie 一起获得了1983年的ACM图灵奖,1994年的IEEE计算机先锋奖和1998年的美国国家技术奖章。1997年他正式成为美国计算机历史博物馆名人 堂成员。

网友评价:

  • Pete Prokopowice:…他很可能是有史以来最成就卓著的程序员。(他的成就包括:)Unix内核,Unix工具,计算机国际象棋世界冠军Belle、Plan 9、Go语言.”
  • Jan Jannink:Ken的贡献远远超过了我们的想象,他的工作是业界的根基,其作用之大,持续时间之久,时至今日还在影响着我们的生活。

4. Richard Stallman

主要成就:Emacs 和 GCC 的缔造者

上榜理由:他创立了GNU项目,并为其开发了很多核心工具,例如Emacs、GCC、GDB 等等,还有 GNU Make。他还创立了自由软件基金会。他是1990年ACM Grace Murray Hopper奖获得者,1998年EFF先锋奖获得者。

网友评价:

  • Srinivasan Krishnan:…在当年Symbolic公司和LMI公司的那场Lisp Machine纠纷中,他展示出了以一当百的编程实力
  • (黄小非补充:这是一个非常传奇的故事,当年Richard Stallman在麻省理工(MIT)的人工智能实验室工作,该实验室的重要成果之一就是Lisp Machine。后来,实验室中的两拨科学家分别下海创业,创立了Lisp Machine Inc. ,也即是LMI,以及Symbolic公司。这两家公司的主要业务都是基于Lisp Machine的,而且和MIT也签了约,说好了MIT授权他们使用Lisp Machine,而两家对Lisp Machine做的改进也授权MIT使用,互惠互利。可是,没想到后来Symbolic公司想另起炉灶,于是仿照Lisp Machine的功能自己重新研发了一个仿制品,日后再开发的软件产品就是基于这个仿制品系统而不是MIT的Lisp Machine了,这样也就不用与MIT和LMI再相互交换成果了。这个举动让Richard Stallman非常愤怒,他决定收拾一下Symbolic这个被金钱冲昏头脑的公司,于是他就盯着Symbolic的新产品推出情况,只要 Symbolic一发布新产品,他就马上在动手在Lisp Machine上做一个功能一样的送给MIT和LMI使用。一般Sybmolic推出的新软件,Richard Stallman自己一个人花个几天就能做出一个功能一模一样的。他的这种方式和工作效率曾经让Symbolic公司一度非常恼火。)
  • Dan Dunay:“他对编程的理解和他思想的光辉是如此强大,以致于形成了一套完整的计算机编程亚文化体系”
  • Marko Poutiainen:他是个伟大的,虽然我并不是对他百分百的认同,但是必定是历史上最重要的程序员之一,无论在他身前身后都是如此。
  • John Burnette:你想想假设Linux写出来的时候,GNU项目还不存在的话,会是什么情况?所以Stallman才是老大,耶~

5. Anders Hejlsberg

主要贡献:Turbo Pascal 的缔造者、C# 之父

上榜理由:他是Turbo Pascal的真正创始人。Turbo Pascl可谓是历史上最受欢迎的编译器之一,也是首个集成开发环境(IDE)。随后,他主导开发了Turbo Pascal的继任者——Delphi。他还是 C# 的首席构架师。2001年,他获得了Dr. Dobb’s杂志颁发的“杰出编程奖”。

网友评价:

  • Steve Wood:他当年用汇编语言代码写了Pascal编译器,同时支持当时PC机上的两种主流操作系统(DOS和CP/M)。他的编译器把编译,链接程序的时间从分钟级别提速到了秒级别。
  • Stefan Kiryazov:我崇拜这个家伙,在我成长为职业软件工程的三个关键阶段,每个阶段最喜爱的工具都出自他的创造。

6. Doug Cutting

主要成就:Lucene 的缔造者

上榜理由:他开发了Lucene搜索引擎,Nutch网络爬虫引擎以及Hadoop分布式大数据处理工具。他是开源项目的拥趸(Lucene,Nutch和Hadoop都是开源的)。他还担任过Apache软件基金会的总监。

网友评价:

  • Rajesh Rao:…他就是写出杰出搜索引擎框架(Lucene/Solr)的那个人。他为世界打开了大数据之门(Hadoop)。
  • Amit Nithianandan:他在Lucene和Hadoop上的创新性工作(当然也包括其他项目),为世界创造了巨大的财富和众多就业机会…

推荐阅读:

《Lucene五分钟教程》

7. Jeff Dean

主要成就:

Goolge搜索索引技术的幕后大脑。

上榜理由:他参与设计和实现了Google许多大型分布式系统,包括网络爬虫,索引和搜索,AdSense, MapReduce, BigTable和Spanner。他被选获得2009年的美国国家工程学院奖。2012年获得ACM SIGOPS Mark Weiser奖和ACM-InfoSys基础奖(计算机科学类)。

网友评价:

  • Natu Lauchande:…他在数据挖掘方面取得了重大突破(GFS, MapReduce, BigTable)
  • Erik Goldman: …他设计,实现并部署了MapReduce和BigTable,还有无数其他的东西。
  • 伯小乐补充:「Jeff Dean 是直接写二进制机器代码的,他写源代码,是为了给其他开发人员作参考」。这句是出自《趣文:谷歌大牛Jeff Dean的那些“惊人真相”》的趣评。

推荐阅读:

《谷歌大牛Jeff Dean是如何成为互联网战神的》和《趣文:谷歌大牛Jeff Dean的那些“惊人真相”》

8. Sanjay Ghemawat

主要成就:举足轻重的Google架构师

上榜理由:他参与设计和实现了Google的大型分布式系统,包括MapReduce、Bigtable、Spanner和 Google文件系统。他还编写过Unix的ical日历系统。他于2009年获选进入的美国国家工程院。2012年赢得了ACM计算机科学信息系统基础 类奖。

网友评价:

  • Ahmet Alp Balkan:他是 Jeff Dean 的左膀右臂。

9. Linus Torvalds

主要成就:Linux 之父

上榜理由:他创建了Linux 内核 以及 Git(一个开源的版本控制系统)。他是众多奖项和荣誉的获得者,包括:1998年EFF先锋奖,英国计算机社区Lovelace奖章 (2000年),千禧技术奖金(2012年)以及IEEE计算机社区计算机先锋奖(2014年)。他还于2008年被提名计算机历史博物馆名人堂成员,以 及2012年Internet名人堂成员。

网友评价:

  • Erich Ficker:「为了说明他的成就,让我们来做个对比吧。他花了几年的时间就完成了Linux内核的编写,与此同时GNU Hurd项目(一个GNU自己开发的内核项目)已经发展了25年了,却还只停留在预发布的demo阶段。」
  • Dan Allen:「Torvald是程序员中的程序员。」
  • Alok Tripathy:「他太他*的优秀了!」

推荐阅读:

《Linus:23年前我开发Linux仅仅是因为好玩》和《Git 10 周年访谈:Linus 讲述背后故事》,更多请点击这里。

10. John Carmack | 约翰·卡马克

主要荣誉:Doom 之父

主要成就:他是id Software的联合创始人,他开发出了极具影响力的FPS游戏:《德军总部3D》、《毁灭战士》和《雷神之锤》。他是计算机图形技术领域的先锋,在图 形学上多次取得重要突破:包括自适应性图块刷新(adaptive tile refresh),二叉空间分割(BSP),以及表面缓存技术等等。他在2001年入选交互式艺术与科学学院名人堂,并在2007年和2008年两次获得 艾美奖工程和技术类奖项,并于2010年获得游戏开发者选择终身成就奖。

网友评价:

  • Alex Dolinsky:”他在20岁之前就写出了第一个渲染引擎。这家伙是个天才。我希望我有他1/4的功力就好了。“
  • dniblock:「《德军总部3D》、《毁灭战士》和《雷神之锤》在那个时代都是革命级的游戏,并且影响了一代游戏设计师。」
  • Greg Naugthon:”给他一个周末,他能做出任何东西。“
  • Chris Morris:”他就是编程界的莫扎特”

推荐阅读:

《大牛约翰·卡马克语录》和《卡马克:用C++进行函数式编程》

11. Fabrice Bellard

主要成就:QEMU 缔造者

上榜理由:他是许多著名开源软件程序的作者,包括QEMU——一个硬件模拟和虚拟化平台,FFmpeg——用于处理多媒体数据,以及一个Tiny C编译器,还有LZEXE,一个可执行程序压缩器。他是2000年和2001年混乱C代码竞赛的冠军,以及2011年Google-O’Reilly开源 奖获得者。他还曾经是计算圆周率位数最多的世界纪录保持者。

网友评价:

  • raphinou:“我觉得Fabrice Bellard的工作实在是太卓著和令人印象深刻了”
  • Pavan Yara:“Fabrice Bellard是全世界最高产的程序员…”
  • Micheal Valladolid:”他是软件工程界的尼古拉特斯拉“
  • Michael Biggins:”他是20世纪80年代以来产生的一位持续高产的程序员“

推荐阅读:

《天才程序员 Fabrice Bellard》

12. Jon Skeet

主要成就:StackOverflow 上的传奇贡献者

上榜理由:他是Google工程师,《C# in Depth》的作者。他保持者StackOverflow有史以来的最高声望,他平均每个月在StackOverflow上回答390个问题。

网友评价:

  • Steven A. Lowe:”Jon Skeet根本不需要调试器,他只要一直瞪着代码,然后代码就会自己出来坦白哪里出错了。“
  • Dan Dyer:”Jon Skeet的代码如果无法通过编译,那编译器就该出来道歉了。“
  • 匿名:”Jon Skeet的代码不需要遵守任何代码规范,因为他的代码本身就是规范。“
  • 伯小乐补充:上面这些评价,和《趣文:谷歌大牛Jeff Dean的那些“惊人真相”》这篇文章的趣评一个风格呀。

13. Adam D’Angelo

主要成就:Quora 联合创始人

上榜理由:他是Facebook的工程师,为Facebook构建了News Feeds 的最初基础设施。后来他成为了Facebook的CTO以及工程副总裁,接着他从Facebook离职联合创立了Quora。2001年,他以高中生的身 份成为了美国奥利匹克信息竞赛排名第八的选手。在2004年的ACM国际大学生编程竞赛中,他是加州理工大学银牌优胜队的成员之一。他还在2005年 Topcoder大学生挑战赛中闯入了算法编程竞赛的最终决赛轮。

网友评价:

  • 匿名:”他是一个‘全能’程序员”
  • Mark Zuckerberg:“他是我说的六个人之一。”
  • (黄小非补充:在创立Facebook之初,Mark Zuckerberg认为世界上只有6个人能够理解他创立Facebook的思想,当时他就盯上了在加州理工上学的Adam D’Angelo,认为他是6个人之一。)

14. Petr Mitrechev

主要荣誉:全世界最有竞赛能力的程序员

上榜理由:国际奥林匹克信息竞赛两次金牌得主(2000,2002)。2006年,他赢得了Google代码挑战赛和TopCode算法公开赛冠 军。另外,他还是两次Facebook Hacker Cup的得主(2011,2013)。在这篇文章发布的时候,他是TopCoder上算法总排名第二的参赛者(id叫Petr)并且在 Codeforces的总排名也是第二。

网友评价:

  • Kavish Dwivedi:「他就是竞赛型程序员的偶像,即使是在我们印度…」

15. Gennady Korotkevich

主要成就:编程竞赛的奇才

上榜理由:他是国际奥林匹克信息竞赛创办以来最年轻的参赛者(11岁)以及6次金牌获得者(2007-2012)。2013年ACM国际大学生编程 竞赛优胜队的成员之一,2014年Facebook Hacker Cup的赢得者。在本文编写是,他是Codeforces排名第一的选手(id:Tourist)以及Topcode算法竞赛者中的第一名

本文转载自: http://www.techug.com/good-programmers
(本站只作转载,不代表本站同意文中观点或证实文中信息)