Servlet, Struts2 Action, SpringMVC Control是否单例测试结果


同事咨询Servlet, Struts2 Action, SpringMVC Control的应用情况,针对是否单例,运行工程实际测试了一下。

测试方法:

  • 在Servlet.service方法中打印对象的hashcode值
  • 在Action.excute方法中打印对象的hashcode值
  • 在Control.XXX方法中打印对象的hashcode值

测试结果:

  • Servlet是单例的,多个请求共用一个对象。
  • Struts2 Action是多例的,每次请求都新生成一个实例对象。
  • SpringMVC Control是单例的,多个请求共用一个对象。

结论:

对于高并发的Web应用,建议不使用Struts,每个请求新生成一个对象,是个比较大的开销,同时Struts在开发上限制太多和直接写Servlet无太大区别,缺乏灵活性。

 

使用POI输出超过65536行大Excel(SXSSF技术)


一直以来都用POI做Excel导出,之前导出的Excel格式都是2003版的——XLS,最近客户要求导出超过65536条数据,超出了XLS的上限,所以研究起XSSFWorkbook的用法。

原本以为只是把HSSFWorkbook替换成XSSFWorkbook就能导出数据,无奈总是报告内存溢出。放狗查找资料,最终锁定SXSSFWorkbook类。

首先参考Upgrading to POI 3.5, including converting existing HSSF Usermodel code to SS Usermodel (for XSSF and HSSF)完成HSSFWorkbook转换为XSSFWorkkbook的转换,注意使用CreationHelper类。

再参考SXSSF (Streaming Usermodel API)完成大文件的输出

import junit.framework.Assert;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

public static void main(String[] args) throws Throwable {
    SXSSFWorkbook wb = new SXSSFWorkbook(100); // keep 100 rows in memory, exceeding rows will be flushed to disk
    Sheet sh = wb.createSheet();
    for(int rownum = 0; rownum < 1000; rownum++){
        Row row = sh.createRow(rownum);
        for(int cellnum = 0; cellnum < 10; cellnum++){
            Cell cell = row.createCell(cellnum);
            String address = new CellReference(cell).formatAsString();
            cell.setCellValue(address);
        }

    }

    // Rows with rownum < 900 are flushed and not accessible
    for(int rownum = 0; rownum < 900; rownum++){
      Assert.assertNull(sh.getRow(rownum));
    }

    // ther last 100 rows are still in memory
    for(int rownum = 900; rownum < 1000; rownum++){
        Assert.assertNotNull(sh.getRow(rownum));
    }

    FileOutputStream out = new FileOutputStream("/temp/sxssf.xlsx");
    wb.write(out);
    out.close();    // dispose of temporary files backing this workbook on disk
    wb.dispose();
}

写在最后

  • SXSSF通过把数据缓存到磁盘临时文件,完成超大Excel的输出。
  • 一个Sheet对应一个临时文件
  • 通过SXSSFWorkbook构造函数指定多少条写入临时文件,实际测试证明,维持默认100条能够获得较好的性能。
  • 最后不要忘记使用SXSSFWorkbook.dispose()方法清除临时文件,该方法返回true,则表示所有的临时文件都已经清除。
    该方法实际最终执行SheetDataWriter.dispose(),此方法内部执行java.io.Writer.close()方法释放资源,同时执行java.io.File.delete()方法删除临时文件。
  • 如果碰到临时文件空间的问题,可以尝试启动GZIP,用CPU来换空间了。

GZIP启用方法:

SXSSFWorkbook wb = new SXSSFWorkbook(); 
  wb.setCompressTempFiles(true); // temp files will be gzipped

开车感受(二)


今天租了雪铁龙爱丽舍三厢1.6手动挡,去了一趟房山,路上还去了一些其他的地方,一共跑了160公里,满油发车,回来加了80块钱油跳枪
路上一半开窗,一半空调

感受:
喇叭位置怪异,一开始以为方向盘下是喇叭按钮,结果按了半天没反应,然后打电话问客服,客服帅哥说是在转向灯拨杆上,晕~

2,3,4,倒档清晰,有吸入感,1,5挡难挂。或许是租车,可能磨合得不好,3,4及倒档和之前开的奇瑞A516差不多,甚至更好,但是1,5挡太难挂了,档位不清晰

变速箱挡把始终抖动,和之前的瑞虎一样,抖动厉害,按摩器了

时速100公里后方向盘感觉变轻,来回颤动,发飘,不知道是不是车的养护问题

空调效果不好,和瑞虎差不多,没有什么效果,还不如开窗,还好今天不热

离合器结合点高,半离合点行程短,感觉只有一点,过了那一点就全咬合了(是不是都是这样子,可能自己开车的方法不对,现在也在总结,半离合保持不动几秒钟,车子5,6公里的样子再全抬起来)

离合器上方有东西阻挡抬脚,如果不用脚尖踩离合器,而用前脚掌踩离合器,后脚跟不动,抬离合器时,还没有到结合点,脚就被挡住了。

隔音效果还行,和凯越差不多

开车感受(一)


最近开了一些车,记录下来,以后做参考用

别克凯越1.6自动档
油耗:
油老虎,综合路况没有开空调,算下来到了1块钱一公里;
噪音:
高速隔音效果尚可;
问题:
刹车至半联动时有点闯;出现过几次踩油门踏板无反应的情况,松油门后再踩才有

奇瑞瑞虎1.6手动档(非DVVT发动机)
动力:
首先是动力太差了,加上离合器接合点太高,刚开这车,起步容易熄火;
噪音:
高速隔音太差,噪音主要来自于两个方面,一个是胎噪,一个风噪
问题:
空调太不给力,长沙艳阳高照,气温30几度,空调开了一点效果都没有;
离合器接合点太高,跟车累;
挂档感觉太差,档位不清晰,松松垮垮;
刹车太软,感觉刹不住;
早晨启动时发动机在700左右抖动,抖动几次后怠速1000转才稳定

奇瑞A516手动档
动力够用,油门响应即时,要有就有;
同样是奇瑞的车,这款车的离合器接合点低,半联动舒适;挂档感觉也比瑞虎好稍好一些,但还是有些入档不清晰的感觉,国产车的变速箱还有很长一段路需要走。

Intel Rapid Start 安装配置方法


Intel Rapid Start:Intel 推出的一种快速恢复技术,能够保证笔记本在深度睡眠的时候维持接近于0W的功耗,同时又提供快速恢复能力,恢复能力接近于从内存直接恢复系统的速度,当然,这一切除了去年年底上市的芯片组以外,还需要SSD的支持。

困扰了我两天的Intel Rapid Start安装配置终于解决,笔记本官方以及Intel都没有放出有效的安装方法,最后在Dell的英文支持论坛找到答案,简单翻译一下,供大家参考。

安装成功条件:
1. 确认 BIOS 支持 Intel Rapid Start Technologies,并且已经选择了 Enable。
2. SSD硬盘必须分配和内存大小相同的睡眠分区。
3. 安装厂商提供的Intel Rapid Start Technologies软件程序

详细安装步骤(以Window 7为例):
1. 右击开始菜单里的“计算机”打开磁盘管理工具。
2. 在磁盘管理工具里选中你SSD所在硬盘,选择一个空闲空间最大的分区,右击,选择压缩卷。
3. 分配和内存大小相同的磁盘空间。比如我的是4GB内存,则输入4096,计算方法:1024 * 4。

在开始菜单搜索cmd,并选择以管理员身份打开,然后输入以下命令
a) Diskpart
b) Select disk 0 (这个命令是选择磁盘,为了确保选择的是SSD,可以首先通过list disk查看磁盘情况,从0开始计数)
c) create partition primary size=4096 id=84
命令执行完成后,可以在磁盘管理工具中看到新增了一个和内存大小相同的睡眠分区。
最后一步:重启系统,然后安装Intel Rapid Start Technologies软件

参考:http://en.community.dell.com/support-forums/laptop/f/3518/p/19410148/19963290.aspx

Centos 6 配置 NFS 注意事项


Centos6默认已经安装了NFS所需软件包,只是没有启动。

通过修改/etc/exports文件,设置NFS共享文件目录,

/nfsdata 10.32.0.22(rw,root_squash,sync) 10.32.0.23(rw,root_squash,sync)

重新载入exportfs

# exportfs -arv

然后重启nfs服务。

# service nfs start

以上几步虽然可以启动nfs服务,但是却存在一些问题,第一是nfs防火墙配置,nfs有一部分端口默认是动态的,需要设置为固定端口号;其次是nfs server默认通过文件的uid和gid判断当前用户是否具备文件读写权限。如果有多台服务器共享同一个目录,那么需要确保多台服务器访问共享路径的用户uid和gid相同,否则将提示权限错误。

设置固定端口号

# vim /etc/sysconfig/nfs

解开以下行的注释

LOCKD_TCPPORT=32803
LOCKD_UDPPORT=32769
MOUNTD_PORT=892
RQUOTAD_PORT=875
STATD_PORT=662
STATD_OUTGOING_PORT=2020

重新启动nfs服务

# service nfs restart

配置防火墙

# vim /etc/sysconfig/iptables
-A INPUT -s 10.32.0.0/24 -m state --state NEW -p udp --dport 111 -j ACCEPT
-A INPUT -s 10.32.0.0/24 -m state --state NEW -p tcp --dport 111 -j ACCEPT
-A INPUT -s 10.32.0.0/24 -m state --state NEW -p tcp --dport 2049 -j ACCEPT
-A INPUT -s 10.32.0.0/24 -m state --state NEW -p tcp --dport 32803 -j ACCEPT
-A INPUT -s 10.32.0.0/24 -m state --state NEW -p udp --dport 32769 -j ACCEPT
-A INPUT -s 10.32.0.0/24 -m state --state NEW -p tcp --dport 892 -j ACCEPT
-A INPUT -s 10.32.0.0/24 -m state --state NEW -p udp --dport 892 -j ACCEPT
-A INPUT -s 10.32.0.0/24 -m state --state NEW -p tcp --dport 875 -j ACCEPT
-A INPUT -s 10.32.0.0/24 -m state --state NEW -p udp --dport 875 -j ACCEPT
-A INPUT -s 10.32.0.0/24 -m state --state NEW -p tcp --dport 662 -j ACCEPT
-A INPUT -s 10.32.0.0/24 -m state --state NEW -p udp --dport 662 -j ACCEPT

重启防火墙

# service iptables restart

客户端挂载

# mount -t nfs 10.32.0.10:/nfsdata /mnt/nfsdata

确认两台nfs客户端的uid和gid一致,例如:

# id java

如果id不一致可以通过usermod和groupmod命令修改id,id修改之后,用户关联的文件需要重新设定用户和用户组

Subversion pre-commit hooks


pre-commit内容如下

#!/bin/sh

REPOS="$1"
TXN="$2"

# Make sure that the log message contains some text.
SVNLOOK=/usr/bin/svnlook
LOGMSG=`$SVNLOOK log -t "$TXN" "$REPOS" | wc -c`

if [ "$LOGMSG" -lt 5 ];
then
  echo -e "***** Comment must be at least 5 characters. *****" 1>&2
  exit 1
fi# All checks passed, so allow the commit.
exit 0

添加完成之后需要修改文件具备执行权限,否则会提示

svn: Commit blocked by pre-commit hook (exit code 255) with no output.