使用Intellij IDEA插件生成使用Guava的equals、hashCode 和toString方法

本文为翻译文章,原文为:Let your IntelliJ IDEA generate good looking equals, hashCode and toString with Google Guava

问题

在Java编程里,我们需要经常编写equals, hashCode 和 toString方法。老实讲,这通常只需要一个模板就能完成。

托各种优秀IDE的福,我们已经不需要自己手动来编写这些代码了。我们可以让IDE使用插件来帮我们完成这些工作。但是仍然有一个问题。通常由IDE自动生成的这些代码都非常难看。让我们来看下面一个POJO:

public class Beer {

    private String brand;
    private String type;
    private int degrees;
    private double alcoholPercentage;
    private List<String> ingredients;

    // constructor
    // getters, setters if needed

}

通用做法

我注意到几乎所有的主流IDE都能够生成符合需求的方法的代码,但是生成的equals、hashCode和toString方法代码通常看起来就像下面这样:

1. equals – long list of IF statements …

@Override
public boolean equals(final Object o) {
    if (this == o) {
        return true;
    }
    if (!(o instanceof Beer)) {
        return false;
    }

    final Beer beer = (Beer) o;

    if (Double.compare(beer.alcoholPercentage, alcoholPercentage) != 0) {
        return false;
    }
    if (degrees != beer.degrees) {
        return false;
    }
    if (!brand.equals(beer.brand)) {
        return false;
    }
    if (!ingredients.equals(beer.ingredients)) {
        return false;
    }
    if (!type.equals(beer.type)) {
        return false;
    }

    return true;
}

2. hashCode – confusing magic numbers, xors and shifts

@Override
public int hashCode() {
    int result;
    long temp;
    result = brand.hashCode();
    result = 31 * result + type.hashCode();
    result = 31 * result + degrees;
    temp = alcoholPercentage != +0.0d ? Double.doubleToLongBits(alcoholPercentage) : 0L;
    result = 31 * result + (int) (temp ^ (temp >>> 32));
    result = 31 * result + ingredients.hashCode();
    return result;
}

3. toString – nasty string concatenation

@Override
public String toString() {
    return "Beer{" +
            "brand='" + brand + '\'' +
            ", type='" + type + '\'' +
            ", degrees=" + degrees +
            ", alcoholPercentage=" + alcoholPercentage +
            ", ingredients=" + ingredients +
            '}';
}

使用Guava库来解决

你有可能已经听过说或者已经使用过Google Guava,但是无论怎样,Google Guava都是一个提供了很多非常使用Java工具的精巧的库。我们可以使用Google Guava来重写上面的三个方法来使得代码显得更好看:

1. equals – army of IF statements transformed to chained call

@Override
public boolean equals(final Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null || getClass() != obj.getClass()) {
        return false;
    }
    final Beer other = (Beer) obj;
    return Objects.equal(this.brand, other.brand) && Objects
            .equal(this.type, other.type) && Objects
            .equal(this.degrees, other.degrees) && Objects
            .equal(this.alcoholPercentage, other.alcoholPercentage) && Objects
            .equal(this.ingredients, other.ingredients);
}

2. hashCode – 一行搞定

@Override
public int hashCode() {
    return Objects.hashCode(brand, type, degrees, alcoholPercentage, ingredients);
}

3. toString – consistent chained call

@Override
public String toString() {
    return Objects.toStringHelper(this)
            .add("brand", brand)
            .add("type", type)
            .add("degrees", degrees)
            .add("alcoholPercentage", alcoholPercentage)
            .add("ingredients", ingredients)
            .toString();
}

安装Intellij IDEA插件

对于equals和hashCode方法,在IDEA中还可以使用由Michal Jedynak编写的Equals and HashCode Deluxe Generator来生成代码。你可以在IDEA的插件库中搜索该该插件:

search plugin

使用这个插件非常简单,你只需要在代码编辑器内弹出鼠标右键就可以看到增加的插件选单,或者你也可以使用ALT+INSERT(MAC下使用CTRL+N)快捷键,如图所示:

context menu

至于toString方法,我们只需要在IDEA中增加一个模板即可。使用ALT+INS 快捷键然后选择toString()菜单选项。点击设置按钮并切换到模板(Templates)选项卡。在模板选单页点击”+”按钮:

add toString template

填写新模板的名称(诸如guava tostring等),然后把下面的代码拷贝到模板编辑页里。

public String toString() {
    #set ($autoImportPackages = "com.google.common.base.Objects")
    return Objects.toStringHelper(this)
    #foreach ($member in $members)
        .add("$member.name", $member.accessor)
    #end
        .toString();
}

使用新模板也非常简单,使用ALT+INS快捷键,选择toString(),然后确认选择正确的模板即可:

enter image description here

Enjoy code!

NodeJS教程–基于ExpressJS框架的文件上传

本文是翻译的一篇文章,原文地址:Handle File Uploads in Express (Node.js).

在NodeJS发展早期上传文件是一个较难操作的功能,随后出现了formidable。它开了一个好头,然而上传文件仍然不是那么容易。在此之后又出现了基于原文作者的教程(tutorial on handling POST requests in Express)而实现的工具connect-form。它让文件上传的过程显得简单了一些。

随着NodeJS社区的飞速发展,让上传文件这个功能变得简单得以实现肯定不会需要太长时间。现在这个功能已经得以实现—在ExpressJS中你可以很容易的上传文件。

在Express中上传文件时不再需要依赖其他的模块,文件上传可以很好工作于Express框架内。就像使用req.body一样,现在你可以使用req.files来获得你上传的文件中的具体信息。

如果你不需要指定上传文件的目录,那么你不需要对app.js做任何的改变,文件将默认上传到’/tmp’目录。但是如果你希望对你上传的文件指定特定目录,你仅仅需要修改一下内容:

app.use(express.bodyParser());

修改为 :

app.use(express.bodyParser({uploadDir:'./uploads'}));

这一配置项可以再ExpressJS的V2.5.4之后的版本中发现,具体可以参看ExpressJS的源代码,具体在express.bodyParser的第16行。在上面的示例中。文件将被上传到与express应用同级目录下的uploads目录中。

为了更好说明在POST过程中文件上传时一些细节,我们建立如下的一个表单提交页面:

<form method="post" enctype="multipart/form-data" action="/file-upload">
  <input type="text" name="username">
  <input type="password" name="password">
  <input type="file" name="thumbnail">
  <input type="submit">
</form>

服务端在处理上面的表单提交时的方法如下:

app.post('/file-upload', function(req, res, next) {
  console.log(req.body);
  console.log(req.files);
});

看看就是这么简单!

在上面的示例中,我们可以通过调用req.files.thumbnail对象来获得我们上传的文件的具体信息,对象的名称取决你上在form表单的定义。如上所示,我们使用的名称是thumbnail,因此我们可以通过req.files.thumbnail来获得它的信息。

一个文件包含以下常用的属性信息:

  • size —- 文件大小(bytes)
  • path —- 文件上传后的路径
  • name —- 文件的原始文件名称.
  • type —-文件类型

针对上面的示例来说, 文件大小:req.files.thumbnail.size
文件类型: req.files.thumbnail.type
原文件名: req.files.thumbnail.name

需要注意的是,默认的上传目录或你指定的上传目录都只是临时目录,因此你还需要将上传的文件移动相应的文件目录。下面的示例代码演示了如何将上传的文件移动到’/images’目录下:

   // 移动文件需要使用fs模块
   var fs = require('fs');
   app.post('/file-upload', function(req, res) {
     // 获得文件的临时路径
     var tmp_path = req.files.thumbnail.path;
    // 指定文件上传后的目录 - 示例为"images"目录。 
    var target_path = './public/images/' + req.files.thumbnail.name;
    // 移动文件
    fs.rename(tmp_path, target_path, function(err) {
      if (err) throw err;
      // 删除临时文件夹文件, 
      fs.unlink(tmp_path, function() {
         if (err) throw err;
         res.send('File uploaded to: ' + target_path + ' - ' + req.files.thumbnail.size + ' bytes');
      });
    });
  };

你可以将上传目录指定为任何你可以在当前操作系统环境下可以访问的目录。如果你希望这些文件可以被公开访问,你可以将文件拷贝到应用的静态目录’/public’下。需要注意的是,如果需要将文件拷贝到public或其子目录下,请确保文件夹存在,且可以被写入。否则会出现’Error: ENOENT, no such file’等异常信息。

现在在ExpressJS中上传文件将是一件非常简单的事情。如果你的原有应用需要使用文件上传,那么我建议你将应用升级到最新的ExpressJS框架,并且修改你的程序以保证功能可以正常工作。

Oracle10g中过程(PROCEDURE )重建的增强

作者:eygle |English Version 【转载时请以超链接形式标明文章出处和作者信息及本声明】

链接:http://www.eygle.com/archives/2007/04/oracle10glastddl_time.html

dcba上周有了一个新的发现,在Oracle10g中,当重建一个存储过程时,Oracle的行为和以前有所不同。

在Oracle9i中,即使一个完全相同的过程的重建,Oracle也需要重新编译过程,这个可以从LASTDDLTIME看出:

[oracle@jumper oracle]$ sqlplus eygle/eygle


SQL*Plus: Release 9.2.0.4.0 - Production on Sat Mar 31 17:52:55 2007

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.


Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning option
JServer Release 9.2.0.4.0 - Production

SQL> create or replace PROCEDURE pining
2 IS
3 BEGIN
4 NULL;
5 END;
6 /

Procedure created.

SQL> select object_name,last_ddl_time from dba_objects where object_name='PINING';

OBJECT_NAME LAST_DDL_TIME
------------------------------ -------------------
PINING 2007-03-31 17:52:58

SQL> create or replace PROCEDURE pining
2 IS
3 BEGIN
4 NULL;
5 END;
6 /

Procedure created.

SQL> select object_name,last_ddl_time from dba_objects where object_name='PINING';

OBJECT_NAME LAST_DDL_TIME
------------------------------ -------------------
PINING 2007-03-31 17:54:35

在Oracle10g中,这个LASTDDLTIME不再变化,这说明在10g中,当我们执行create or replace PROCEDURE 时,Oracle现在先尝试进行过程检查,如果内容没有变化,则不需要对过程进行重新编译,这可以减少Cache中的Invalidation,从而可以减少竞争:

$ sqlplus eygle/eygle


SQL*Plus: Release 10.2.0.1.0 - Production on Sat Mar 31 17:44:46 2007

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


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options

SQL> create or replace PROCEDURE pining
2 IS
3 BEGIN
4 NULL;
5 END;
6 /

Procedure created.

SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';

Session altered.

SQL> col object_name for a30
SQL> select object_name,last_ddl_time from dba_objects where object_name='PINING';

OBJECT_NAME LAST_DDL_TIME
------------------------------ -------------------
PINING 2007-03-31 17:45:25

SQL> create or replace PROCEDURE pining
2 IS
3 BEGIN
4 NULL;
5 END;
6 /

Procedure created.

SQL> select object_name,last_ddl_time from dba_objects where object_name='PINING';

OBJECT_NAME LAST_DDL_TIME
------------------------------ -------------------
PINING 2007-03-31 17:45:25

这个我已经在实际过程确认是存在的。

如何使用DBMS_LOB从文件中加载CLOB数据

作者:eygle |English Version 【转载时请以超链接形式标明文章和作者信息及本声明
链接:

BFILE包含二进制数据,所以当通过BFILE方式加载数据到CLOB/NCLOB时,Oracle不进行字符集转化。
如果字符集是可变长的,例如UTF-8或ZHS16GBK,Oracle使用UCS2存储LOB数据。所以如果想BFILE文件数据能够正确加载入数据库,那么文件需要以USC2字符集存储。
那么还有一点需要注意的是,如果以Unicode模式存储文件,那么文件会增加两个字节:
‘FF FE’.
在加载文件时我们需要跳过这两个字节。
在Windows上我们存储文件时选择Unicode方式,我输入的字符为:

test测试
Oracle BFile数据加载问题
研究

 

Unicode.File.jpg

然后我们可以加载这个文件的内容,注意比较前后两个过程不同之处:

SQL> create table t (
  2  name       varchar2(30),
  3  content clob
  4  )
  5  /
 
Table created.
 
SQL> 
SQL> 
SQL> create or replace directory dir1 as '/opt/oracle';
 
Directory created.
 
SQL> 
SQL> declare
  2          l_bfile bfile;
  3          l_clob  clob;
  4          l_str   varchar2(1000);
  5  begin
  6          insert into t (name,content)
  7          values ('b.txt',empty_clob())
  8          returning content into l_clob;
  9  
 10          l_bfile := bfilename('DIR1','b.txt');
 11  
 12          dbms_lob.fileopen(l_bfile);
 13          dbms_lob.loadfromfile(l_clob,l_bfile,dbms_lob.getlength(l_bfile));
 14          dbms_lob.fileclose(l_bfile);
 15          commit;
 16          exception when others then
 17          l_str:=sqlerrm(sqlcode);
 18          dbms_output.put_line(l_str);
 19  end;
 20  /
 
PL/SQL procedure successfully completed.
 
SQL> select * from t;  
 
NAME                           CONTENT
------------------------------ ----------------------------------------------
b.txt                          ?test测试
                               Oracle BFile数据加载问题
                               研究
 
 
SQL> 
SQL> declare
  2          l_bfile bfile;
  3          l_clob  clob;
  4          l_str   varchar2(1000);
  5  begin
  6          insert into t (name,content)
  7          values ('b.txt',empty_clob())
  8          returning content into l_clob;
  9  
 10          l_bfile := bfilename('DIR1','b.txt');
 11  
 12          dbms_lob.fileopen(l_bfile);
 13          dbms_lob.loadfromfile(l_clob,l_bfile,dbms_lob.getlength(l_bfile)-2,
 14                            src_offset => 3);
 15          dbms_lob.fileclose(l_bfile);
 16          commit;
 17          exception when others then
 18          l_str:=sqlerrm(sqlcode);
 19          dbms_output.put_line(l_str);
 20  end;
 21  /
 
PL/SQL procedure successfully completed.
 
SQL> select * from t;
 
NAME                           CONTENT
------------------------------ --------------------------------------
b.txt                          ?test测试
                               Oracle BFile数据加载问题
                               研究
 
b.txt                          test测试
                               Oracle BFile数据加载问题
                               研究

 

以上内容,仅供参考。

使用存储过程(PL/SQL)向数据库中存储BLOB对象

作者:eygle |English Version 【转载时请以超链接形式标明文章和作者信息及本声明
链接:

以下存储过程用于向数据库加载BLOB对象
1.创建directory并授权
关于Directory可以参考: Using Create directory & UTL_FILE in Oracle

C:\>sqlplus "/ as sysdba"
 
SQL*Plus: Release 10.1.0.3.0 - Production on Tue Apr 26 07:11:51 2005
 
Copyright (c) 1982, 2004, Oracle.  All rights reserved.
 
 
Connected to:
Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Data Mining options
 
SQL> create user eygle identified by eygle default tablespace users;
 
User created.
 
SQL> grant connect ,resource,dba to eygle;
 
Grant succeeded.
 
SQL> connect / as sysdba
Connected.
SQL> create or replace directory BLOBDIR as 'D:\oradata\Pic';
 
Directory created.
 
SQL> grant read on directory BLOBDIR to eygle;
 
Grant succeeded.
 
SQL>

2.创建测试表

SQL> connect eygle/eygle
Connected.
SQL> CREATE TABLE eygle_blob (
  2  fid    number,
  3  fname       varchar2(50),
  4  fdesc  varchar2(200),
  5  fpic        BLOB)
  6  /
 
Table created.
 
SQL>
SQL> create sequence S_EYGLE_SEQ
  2  start with 1
  3  increment by 1
  4  /
 
Sequence created.
 
SQL>

 

3.创建存储过程

SQL> CREATE OR REPLACE PROCEDURE eygle_load_blob (pfname VARCHAR2,pdesc varchar2)
  2  IS
  3  src_file BFILE;
  4  dst_file BLOB;
  5  lgh_file BINARY_INTEGER;
  6  BEGIN
  7     src_file := bfilename('BLOBDIR', pfname);
  8
  9     INSERT INTO eygle_blob (fid,fname,fdesc,fpic)
 10     VALUES (S_EYGLE_SEQ.Nextval,pfname,pdesc,EMPTY_BLOB())
 11     RETURNING fpic INTO dst_file;
 12
 13     SELECT fpic INTO dst_file
 14     FROM eygle_blob  WHERE fname = pfname FOR UPDATE;
 15
 16     dbms_lob.fileopen(src_file, dbms_lob.file_readonly);
 17     lgh_file := dbms_lob.getlength(src_file);
 18     dbms_lob.loadfromfile(dst_file, src_file, lgh_file);
 19
 20    UPDATE eygle_blob  SET fpic = dst_file
 21    WHERE fname = pfname;
 22
 23    dbms_lob.fileclose(src_file);
 24    commit;
 25  END eygle_load_blob;
 26  /
 
Procedure created.
 
SQL> col segment_name for a30
SQL> select segment_name,segment_type,bytes/1024/1024 from dba_segments where owner='EYGLE';
 
SEGMENT_NAME                   SEGMENT_TYPE       BYTES/1024/1024
------------------------------ ------------------ ---------------
SYS_IL0000050545C00004$$       LOBINDEX                     .0625
SYS_LOB0000050545C00004$$      LOBSEGMENT                   .0625
EYGLE_BLOB                     TABLE                        .0625

4.加载Blob对象

SQL> exec eygle_load_blob('ShaoLin.jpg','少林寺-康熙手书');
 
PL/SQL procedure successfully completed.
 
SQL> select segment_name,segment_type,bytes/1024/1024 from dba_segments where owner='EYGLE';
 
SEGMENT_NAME                   SEGMENT_TYPE       BYTES/1024/1024
------------------------------ ------------------ ---------------
SYS_IL0000050545C00004$$       LOBINDEX                     .0625
SYS_LOB0000050545C00004$$      LOBSEGMENT                       4
EYGLE_BLOB                     TABLE                        .0625
 
SQL> exec eygle_load_blob('DaoYing.jpg','倒映');
 
PL/SQL procedure successfully completed.
 
SQL> select segment_name,segment_type,bytes/1024/1024 from dba_segments where owner='EYGLE';
 
SEGMENT_NAME                   SEGMENT_TYPE       BYTES/1024/1024
------------------------------ ------------------ ---------------
SYS_IL0000050545C00004$$       LOBINDEX                     .0625
SYS_LOB0000050545C00004$$      LOBSEGMENT                       7
EYGLE_BLOB                     TABLE                        .0625
 
 
SQL> col fname for a20
SQL> col fdesc for a30
SQL> select fid,fname,fdesc,dbms_lob.getlength(fpic) siz from eygle_blob;
 
       FID FNAME                FDESC                                 SIZ
---------- -------------------- ------------------------------ ----------
         1 ShaoLin.jpg          少林寺-康熙手书                   1768198
         2 DaoYing.jpg          倒映                              2131553
 
 
D:\oradata\Pic>ls -l
-rwxrwxrwa   1 gqgai           None            2131553 Apr 19 10:12 DaoYing.jpg
-rwxrwxrwa   1 gqgai           None            1768198 Apr 19 10:12 ShaoLin.jpg

通过以上方式,我们可以很容易的把大对象存储到数据库中。

闹钟Alarm – 很有生活气息且材质做得非常出色的动画

本文原始地址http://www.ipc.me/alarm-video.html   我可耻的转摘了。

《Alarm》中文是闹钟的意思,故事非常简单但也很有生活气息,可能每个人都有这样的经验,早上闹钟响起之后,迷迷糊糊之中似乎自己已经起床,穿衣服,洗漱,吃早餐,穿鞋出门……有时甚至能碰到同学都走到教室或者回到公司……坐下的一瞬间……突然惊醒,原来自己还没起床,而已经迟到半小时了……

闹钟Alarm

这部短片有着非常出色的材质与动画,720P高清视频的每一个截图都可以直接拿来作为壁纸,确实是非常漂亮 的材质,灯光与渲染……

本片非常的具有韩国风格,2009 SIGGRAPH 参展作品,请欣赏..

Alarm 官方网站 :www.mesai.co.kr
里面包含很多关于Alarm的资料,包括故事版,高清视频下载,测试渲染图等……有兴趣的可以去看看。网站也做得不错噢。

我和世界不一样 – Nick Vujicic

在一个小时以前,我并不知道Nick Vujicic是何方人物,
但是就在过去的一小时里,围脖开复老师的转摘让我看到下面的视频简介以及完整的视频片段。

从他出生到他懂事,相信的父母经历一种坚强的抉择。并且在他懂事以后帮助他建立自己的信念。

真心希望他能找到知心爱人,现在他是一个神父,全世界的传教中…..

所以请你也耐心的看完下面的片段。

或者你也可以前往官方网站Life Without Limbs :: Nick Vujicic

便槽协议的脆弱性

这篇文章是我在很早之前Gracecode上看到翻译文档,当时只是觉得有点意思。现在再看,发觉里面涉及的东西如果再往里研究可能涉及到社会学,社会心理学方面的知识了。还好原作者并没有深入探究这些方面的问题。

下面两个地址分别中文翻译原始地址和英文原始地址:便槽协议的脆弱性,Urinal protocol vulnerability

 

当我们内急的时候,走进厕所你通常会选择哪个便槽方便?这可是个国际性的话题。一般基本的情 况是第一个先来家伙自由选择了便槽,那么后面来的哥们会尽量选取离他相对较远的便槽。也就是 说,这样至少要能间隔一个便槽,以免尴尬的发生(老外有偷窥别人的“铅笔” Size 癖好?)。

继续阅读“便槽协议的脆弱性”

施瓦辛格:用藏头诗终结你

一直以为藏头诗文只是中国人的专利,没想到终结者州长施大叔也会,还用的如此美轮美奂,在给三番市议员Tom Ammiano的这封简短的信中,不仅清楚地表达对其提案的否决态度,还第2、3自然段的开头埋下F字头炸弹,不可谓不高明。 尽管施大叔的秘书马上出来撇清说这只是个巧合,但这事正发生在Tom Ammiano冲施大叔高喊:“Kiss my gay ass!”之后,就显得越描越黑了。

Kiss my gay ass