淘宝商城(天猫)高级技术专家.3年研发+3年性能测试调优/系统测试+4年团队管理与测试架构、研发系统实践. 新舞台新气象, 深化测试基础架构及研发架构,希望能在某个技术领域成为真正的技术大牛。欢迎荐才http://bbs.51testing.com/viewthread.php?tid=120496&extra=&page=1 .邮件: jianzhao.liangjz@alibaba-inc.com,MSN:liangjianzhao@163.com.微博:http://t.sina.com.cn/1674816524

发布新日志

  • [论坛] jmeter 之短板以及建议解决方案

    2009-02-14 10:51:27

    随着JMeter的应用,发现JMeter的局限性越来越多,急需进一步扩展改进
           
    一 几百兆的sample 日志解析出现OutOfMemory

    最近的几个项目都是Java sample 日志,应用都是高达300 tps的,而响应时间都在百毫秒级别,所以在 <60分钟的运行过程中,生成JMeter 采样日志到达几百兆。
    用JMeter gui解析日志,多次出现OutOfMemory,不爽。
    规避但不治本方法:
    1) 放到>4G 内存的LINUX 机器上, 设置-Xmx2048m甚至更高启动JMeter.sh
    2) 放到64位的java 版本上
    3) 减少java sample运行时间或者次数,减少日志尺寸
    4) 对要求长时间的场景,采用shell 方式启动-关闭jmeter-重命名生成日志 的方式减少日志尺寸

    最根本方法:改写jmeter日志解析部分为NONE GUI,或者用C/c++效率更高的语言解析有规律日志

    二 分布式多台监控机器

    这个也不是jmeter 的长处。尤其是要求监控iowait%,netstat 连接数,NAS 上监控数据。

    解决办法:
    用loadrunner monitor+扩展DLL。

    三 被测程序为client API

    由于JMeter 运行消耗资源较大,无法清晰区分client api本身是否有短期对象、内存泄漏。

    在确认Client api自身没有并发问题、内存泄漏、短期对象问题后,
    可以client api内部加入一些度量数据输出到excel  +  结合jmeter获取更多的平均值、标准差等数据

    四  面向目标的场景控制

    比如要求控制服务器的资源在一定负载下。如要求linux 机器load 接近5时,求解TPS为多少?

    由于系统受到应用CACHE,OS CACHE,NAS CACHE 等影响,单纯采用JMeter 将耗费极大精力。

    解决方法:
    用java 多线程程序发起压力+另外线程检索/proc 目录数据视负载增加/减少压力线程数。同时将变化的线程数与资源负载输出到文件,将这些数据做趋势分析。

    再用线程数应用在jmeter上 反馈验证
  • [论坛] 测试计划考虑的几点

    2009-02-13 22:08:11

    测试计划最终结果把WBS有控制完成。测试计划符合SMART原则。

    1 选人:
    从几个纬度考虑
    (1) 尽量发挥技术特长
    (2) 结合项目兴趣
    (3) 技能高+ 技能低些的结合。涵盖项目所需技能。或者不完全具备,需要有学习能力强的排头兵

    2 工时估算

    这个是一个很难估算准确的活。因为一个项目充满变数。
    学会工作分解,然后再按每个功能点/测试范围乘一个冗余系数
    可以采用project, mindmap, excel等

    3 风险分析与规避
    通常测试项目风险
    1) 研发提交代码质量不高,冒烟测试失败
    2) 研发更改频繁,送测版本过多
    3) 需求文档或者设计书不够明确,QA 和需求/研发细化耗时
    4) QA 测试分析不够全面
    5) 性能问题分析以及调整影响面过大
    6) 测试的覆盖率过低
    7) 技术难题或者测试环境资源问题
    ...

    4 确定测试范围

    由于项目有外部耦合模块,要非常明确影响范围十分困难。
    通常做法: 用工具绘制调用网状图。或者分析正相关的模块结合自动化测试脚本确定测试范围

    5 确定测试策略

    确认系统是否需要性能测试,安全测试,兼容性测试,本地化测试...

    以及是否需要验证系统的高可用方案, 新旧系统平滑过渡方案 ,可扩展容量估算公式...。

    6 项目的工作约定

    比如采用的模版,沟通方式(IM/周会。。。),项目出现问题的解决流程
  • [论坛] 一次性能测试结果排查过程

    2009-02-13 01:09:28

    一个测试环境受到外部不预期的干扰,性能测试结果将出现不预期的数据,导致分析困难甚至错误结论。
    最近碰到一个CASE,将一个sevice  插入测试环境的网站应用中,然后对比是否加入这个service的性能影响。
    多台测试机器,每台机器部署多个应用,所有应用共享一个DB。

      系统架构: java + webx+ ibatis+ oracle。

            另外,这个service采用几百K的数据运行速度也在毫秒级别。
           
            呵呵,差点掉到沟沟里,特记录下。
           
    一 制定测试方案

    和service开发的dev 评审测试方案。 没有和网站应用的架构师核对。
    被测服务器 load 已经大于 1 。


    二 性能测试执行过程

    选取一个post 产品的流程做性能测试脚本。性能测试数据从几百个byte-几K.
    调整JAVA应用参数与生产环境同。

    1) 删除用户数据
    2) 删除日志
    3) 重启应用
    4)交替执行service上与不上场景.
    5)多次执行去性能数据平均值

    性能测试选择在晚上人少时执行。


    三 性能测试结果分析

    性能测试发现average response time,上与不上service 相差无几,都是0.13秒左右 。甚至同样并发数时,上service的response time 比不上service的response time还要低。
    其他load <2 ,cpu%约20% ,iowait% <1%,内存充足都相近。这个结果似乎有点解释不通。

    另外比较反常的是:average reponse time图(非graph average)上偶尔有锯齿型的到达0.2 甚至0.4的高点,尺度延续时间40多秒。average response time的 std dev(标准方差)约 0.13甚至更高。
    经web page break down分析图片这个数据更加清晰可见。


    经咨询网站的同事,架构师,DBA,可能多台机器上有应用定时器(quartz框架)或者DB自身定时器干扰,与网络无关。
    选择关闭上述所有应用定时器以及DB层定时器后,晚上重新执行多个场景的性能测试,并手工定期检查DB执行SQL。


    再分析性能测试结果,依然有锯齿型数据且性能结果且很接近之前结果,但这个数据是可控程度高的数据。
    用SQL查询性能测试期间DB 日志:
    select SEQUENCE#,FIRST_TIME from v$log_history
      2  where
      3  FIRST_TIME >=to_date('20090209 19:00:00','yyyymmdd hh24:mi:ss')
      4  and FIRST_TIME<to_date('20090209 23:00:00','yyyymmdd hh24:mi:ss')

    发现有4个日志切换过程。

    对比average reponse time拐点与日志切换时间点,部分与之吻合,但average reponse time拐点长度偏大。
    经咨询每次日志切换约有20-50毫秒事务挂起。

    另外部分不吻合部分,是service处理数据长度随机变化有关。

    四 常见工具

    再回头看看确认环境干净,参数配置预期正确的工具。

    毫无疑问,好用的脑子是最强的武器。

    1) OS 层面
    ps ,top 看进程
    ipcs    看进程间通讯
    netstat 看网络连接
    nmblookup,nbtstat 连接的人

    sysctl,/proc  看系统参数
    ulimit   系统软、硬限制

    2)apache 层

    httpd.conf

    3) mod_jk 层
    几个 property文件

    4)JBOSS 层
    run.conf,run.sh以及应用配置参数

    另外就是检查对应启动的服务,可以借助 web-console
    5) JVM 参数

    6) DB 层面
    oracle init file
    mysql show variables

    7) 其他关联服务。
    如 memcached

    ...

    从上例看到,性能测试排除干扰很重要,在系统日趋复杂的情况下需勤开口、善借外力,力争一次把事情做对、做好

    [ 本帖最后由 liangjz 于 2009-2-13 01:06 编辑 ]
  • jdk1.5.0_14+Eclipse SDK3.4.1+TPTP部署

    2009-01-20 13:15:13

    http://www.eclipse.org/tptp/home/downloads/

    下载tptp allinon包: tptp.runtime.allInOne.win32.win32.x86-TPTP-4.5.1.zip

     

    偶尝试了一下逐一安装TPTP,结果是失败。

     

    下载 agntctrl.win_ia32-TPTP-4.5.1.zip  (runtime版本)设置agntctrl

    D:\eclipse_tptp\agntctrl.win_ia32-TPTP-4.5\bin 放到PATH环境变量

    然后执行setconfig.bat设置环境变量

     

    启动代理 acserver

    D:\eclipse_tptp\agntctrl.win_ia32-TPTP-4.5.0\bin>acserver

     

    下载javaprofiler.win_ia32-TPTP-4.5.1.zip   (runtime版本)

    按照说明设置环境变量:

     

    a) Set TPTP_AC_HOME=<<Agent Controller Home>>

    b) Set JAVA_PROFILER_HOME=%TPTP_AC_HOME%\plugins\org.eclipse.tptp.javaprofiler

    c) Set PATH=%JAVA_PROFILER_HOME%;%PATH%;%TPTP_AC_HOME%\bin

    d) Set PATH=%PATH%;%JAVA_HOME%\bin

     

     

    启动JAVA 程序: java -XrunpiAgent:server=enabled CarModel

     

    eclipse 工程可以看到agent

     

     

     

    这里不支持probe insertion

     

     

    远程profile TOMCAT

    catalina.bat java 启动参数加入:-XrunpiAgent:server=enabled

     

    如:

    rem Execute Java with the applicable properties

    if not "%JPDA%" == "" goto doJpda

    if not "%SECURITY_POLICY_FILE%" == "" goto doSecurity

    echo "run OK"

    %_EXECJAVA% %JAVA_OPTS%  -XrunpiAgent:server=enabled

     

     

    然后eclipse ->run->profile configuration->attach to  agent

     

     

     

    实例:

    http://www.eclipse.org/tptp/home/documents/tutorials/profilingtool/profilingexample_32.html

  • 利用easyMock模拟JDBC查询

    2009-01-03 23:40:39

    参考:http://solnone.blogspot.com/search/label/Java

    mock,就是假的意思。easymock或者jmock之类的框架最常用于减少外部重量级资源依赖。

     

    import java.sql.Connection;

    import java.sql.PreparedStatement;

    import java.sql.ResultSet;

    import java.sql.SQLException;

    import java.util.ArrayList;

    import java.util.List;

     

    public class DBImpl {

        public List query(Connection conn) throws SQLException {

           List list = new ArrayList();

           PreparedStatement ps = conn.prepareStatement("select user from user");

           try {

               ResultSet rs = ps.executeQuery();

               try {

                  while (rs.next()) {

                      list.add(rs.getString(1));

                  }

               } finally {

                  rs.close();

               }

           } finally {

               ps.close();

           }

           return list;

        }

    }

     

     

    import static org.easymock.EasyMock.createControl;

    import static org.easymock.EasyMock.expect;

    import static org.easymock.EasyMock.matches;

     

    import static org.junit.Assert.assertEquals;

    import java.sql.Connection;

    import java.sql.PreparedStatement;

    import java.sql.ResultSet;

    import java.sql.SQLException;

    import java.util.Arrays;

    import java.util.List;

    import org.easymock.IMocksControl;

    import org.junit.After;

    import org.junit.Before;

    import org.junit.Test;

     

    public class DBImplTest {

        private DBImpl dbimpl;

     

        @Before

        public void setUp() throws Exception {

           dbimpl = new DBImpl();

        }

     

        @After

        public void tearDown() throws Exception {

           dbimpl = null;

        }

     

        @Test

        public void testQuery() throws SQLException {

           IMocksControl control = createControl();

            // 建立模擬物件

           Connection conn = control.createMock(Connection.class);

           PreparedStatement ps = control.createMock(PreparedStatement.class);

           ResultSet rs = control.createMock(ResultSet.class);

           // 模擬物件預期行為

     

           expect(conn.prepareStatement(matches("select user from user")))

                  .andReturn(ps);

           expect(ps.executeQuery()).andReturn(rs);

           expect(rs.next()).andReturn(true);

           expect(rs.getString(1)).andReturn("root");

           expect(rs.next()).andReturn(true);

           expect(rs.getString(1)).andReturn("tester");

           expect(rs.next()).andReturn(true);

           expect(rs.getString(1)).andReturn("中文");

           expect(rs.next()).andReturn(false);

           rs.close();

           ps.close();

           // 錄製完成,切到 replay 狀態

           control.replay();

           // 調用方法

           List expected = Arrays.asList(new String[]{"root", "tester","中文"});

          

           //这个conn是假的

           List  result = dbimpl.query(conn);

           assertEquals(expected, result);

           // 驗證

           control.verify();

        }

    }

     

     

    CLASSPATH加入easymock.jarcglib-2.2.jar 以及easymockclassextension.jar.

    调试上述程序,dbimpl.query(conn)如期执行真正的查询操作,无须建立真正的数据库联接。

     

     

  • P-unit0.15 应用

    2009-01-02 13:22:43

     

     

    参考:http://zhanghuangzhu.blogspot.com/search/label/p-unit

    http://blog.csdn.net/zhanghuangzhu/

     

    https://sourceforge.net/projects/p-unit 下载.

    Samples 文件编译 runner.runVMs 失败,不再支持runVMs.

    加入libsjar以及p-unit-0.15.319.jar, p-unit-0.15.319-extension.jar

    从执行结果看,p-unitjunitperf 是不同的。P-unit 有内存消耗图片。

    Junitperf并发执行控制粒度控制更加细致。

     

    ParamTestClass.java内容:

     

    package samples;

    import org.punit.reporter.chart.OverviewReporter;

    import org.punit.reporter.chart.image.ImageRender;

    import org.punit.reporter.chart.pdf.PDFRender;

    import org.punit.reporter.stream.file.FileLogger;

    import org.punit.runner.*;

    import org.punit.type.*;

    import org.punit.watcher.MemoryWatcher;

     

    public class ParamTestClass implements Parameterized {

     

        public static void main(String[] args) {

           ConcurrentRunner runner = new ConcurrentRunner();

           //加入内存消耗监控

           runner.methodRunner().addWatcher(new MemoryWatcher());

     

           runner.addEventListener(new FileLogger());

           runner.addEventListener(new OverviewReporter(new ImageRender()));

           runner.addEventListener(new OverviewReporter(new PDFRender()));

           //利用多核特性

           runner.setExecutorPool(new ExecutorPoolImpl(2));

     

           runner.run(ParamTestClass.class);

        }

     

        public Parameter[] parameters() {

           return new Parameter[] { new ParameterImpl(2), new ParameterImpl(10),

                  new ParameterImpl(30) };

        }

     

        public void testA(ParameterImpl param) {

           System.out.println("testA count = " + param.count()); //$NON-NLS-1$

           SampleUtil.doSomething(param.count());

        }

     

       

        public void setUpAfterWatchers(Parameter param) throws Exception {

     

        }

     

        public void setUpBeforeWatchers(Parameter param) throws Exception {

     

        }

     

        public void tearDownAfterWatchers(Parameter param) throws Exception {

     

        }

     

        public void tearDownBeforeWatchers(Parameter param) throws Exception {

     

        }

     

        static class ParameterImpl implements Parameter {

           private int _count;

     

           ParameterImpl(int count) {

               _count = count;

           }

     

           public int count() {

               return _count;

           }

     

           public String toString() {

               return String.valueOf(_count);

           }

        }

    }

     

     

    SampleUtil.java内容

    package samples;

     

    import java.util.*;

     

    import org.punit.util.*;

     

    public class SampleUtil {

                 

           private static Random _random = new Random();

          

           public static void consumeMemory(int length) {

                  byte[] data = new byte[length];

                  for(int i = 0, j = 0; i < data.length; ++i) {

                         ++j;

                  }

           }

          

           public static void consumeTime(int time) {

                  ThreadUtil.sleepIgnoreInterruption(time);

           }

          

           public static void doSomething() {

                  consumeTime(Math.abs(_random.nextInt()) % 500);

                  consumeMemory(Math.abs(_random.nextInt()) % 100000);

           }

           public static void doSomething(int count) {

                  for(int i=0;i<count;i++)

                  {

                  consumeTime(Math.abs(_random.nextInt()) % 500);

                  consumeMemory(Math.abs(_random.nextInt()) % 100000);

                  }

           }

          

    }

     

    控制台执行时间,与内存消耗值。

    testA(30) - [9741.979497ms,504864.0bytes]

    total: 3, failures:0 (GREEN) - 16922.606365ms

     

    执行目录下result 下生成pdf,txt,png格式的文件结果

     

  • HTTPUnit对部分中文网页JS检测出错的处理方法

    2009-01-01 18:43:36

      2009年第一天第一篇测试相关文档:)

     httpUnit在内部公共框架测试上应用。

     参考:http://www.blogjava.net/relax/archive/2005/01/27/743.html

     

     

    httpunit/jars 目录下jar都加入classpath,否则运行时出错。

     

    wc = new WebConversation();// 初始化httpunit

           try {

               GetMethodWebRequest req = new GetMethodWebRequest(

                  //  "http://www.google.cn/search?h1=zh-CN&q=mp4");

                      "http://www.sina.com.cn");

     

               //HttpUnitOptions.setExceptionsThrownOnscrīptError(false);

               WebResponse rep = wc.getResponse(req);

               assertTrue(true);

               WebLink[] links=rep.getLinks();

               for (int i=0;i < links.length;i++)

               {

                  System.out.println(links[i].getURLString());

               }

              

               WebResponse n_rep=links[4].click();

              

               System.out.println(n_rep.getText());

           } catch (Exception e) {

               e.printStackTrace();

               assertFalse(false);

           }

     

    发请求给www.sina.com.cn异常1

     

    org.mozilla.javascrīpt.EcmaError: TypeError: Cannot call method "toLowerCase" of undefined (httpunit

    at com.meterware.httpunit.javascrīpt.scrīptingEngineImpl.handlescrīptException(scrīptingEngineImpl.java:64)

     

    发请求给www.alibaba.com.cn 异常2

    at com.meterware.httpunit.javascrīpt.scrīptingEngineImpl.handlescrīptException(scrīptingEngineImpl.java:64)

        at com.meterware.httpunit.javascrīpt.scrīptingEngineImpl.runscrīpt(scrīptingEngineImpl.java:95)

     

     

    参考:http://lupingui.javaeye.com/blog/239738 在发送http 请求前增加选项:

    HttpUnitOptions.setExceptionsThrownOnscrīptError(false);

    即解决。

     

  • Apache MINA2异步连接框架编译,运行

    2008-12-27 19:10:00

    http://mina.apache.org/mina-v20-quick-start-guide.html

    样例代码有错误。IoAcceptor IdleStatus 路径有问题

     

    import java.io.IOException;

    import java.net.InetSocketAddress;

    import java.nio.charset.Charset;

     

    import org.apache.mina.core.service.IoAcceptor;

    import org.apache.mina.core.session.IdleStatus;

     

    import org.apache.mina.filter.codec.ProtocolCodecFilter;

    import org.apache.mina.filter.codec.textline.TextLineCodecFactory;

    import org.apache.mina.filter.logging.LoggingFilter;

    import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

     

    public class MinaTimeServer {

        private static final int PORT = 9123;

     

        public static void main(String[] args) throws IOException {

           IoAcceptor acceptor = new NioSocketAcceptor();

     

           acceptor.getFilterChain().addLast("logger", new LoggingFilter());

           acceptor.getFilterChain().addLast(

                  "codec",

                  new ProtocolCodecFilter(new TextLineCodecFactory(Charset

                         .forName("UTF-8"))));

     

           acceptor.setHandler(new TimeServerHandler());

           acceptor.getSessionConfig().setReadBufferSize(2048);

           acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);

           acceptor.bind(new InetSocketAddress(PORT));

        }

    }

     

     

     

    D:\eclipse-SDK-3.3.2-win32\project\mina-2.0.0-M4\src\mina-example>javac   -cp %cla

    sspath%;D:\eclipse-SDK-3.3.2-win32\project\mina-2.0.0-M4\dist\mina-core-2.0.0-M4

    .jar  MinaTimeServer.java

     

    运行时候,也费了很大周折,必须把log 实现类也加载。看来文档未经测试:)

    编译的时候需要把log4j.jar 以及slf4j 2个包放好。

     

    D:\eclipse-SDK-3.3.2-win32\project\mina-2.0.0-M4\src\mina-example>java  -cp %cla

    sspath%;D:\eclipse-SDK-3.3.2-win32\project\mina-2.0.0-M4\dist\mina-core-2.0.0-M4

    .jar;D:\eclipse-SDK-3.3.2-win32\project\mina-2.0.0-M4\lib\slf4j-api-1.5.6.jar;D:

    \eclipse-SDK-3.3.2-win32\project\mina-2.0.0-M4\lib\slf4j-log4j12-1.5.6.jar;D:\ec

    lipse-SDK-3.3.2-win32\project\mina-2.0.0-M4\lib\log4j.jar    MinaTimeServer

  • 阿里巴巴集团部分技术BLOG

    2008-12-07 17:28:49

      阿里人才济济,越来越多的技术专家在infoq上露面,也有很多的BLOG 生根发芽:)

    数据库与数据仓库

    http://rdc.taobao.com/blog/dw/

    http://rdc.taobao.com/blog/dba/

     http://www.dbanotes.net

    http://blue-prince.spaces.live.com/

    http://WWW.ALIDBA.NET/

    http://www.orawh.com/

    (biti_rainy)  http://space.itpub.net/3505/

     http://www.hellodba.net/

    http://www.jianzhaoyang.com/

     

    http://xujt82.spaces.live.com/

    http://www.ningoo.net/

    http://hutuworm.blogspot.com/

    前端研发

    http://ued.taobao.com/blog/

    http://www.aliued.cn/

    http://ued.alipay.com/

    http://www.alisoftued.com/

    http://ued.koubei.com/

    JAVA研发

    http://rdc.taobao.com/blog/arch/

    http://www.blogjava.net/BlueDavy/archive/2008/11.html


     http://blog.csdn.net/yzhz/category/24108.aspx

    http://blog.csdn.net/cenwenchu79

                  http://www.blogjava.net/cenwenchu/

    http://davyyew.blogbus.com

     http://www.esbzone.net/

     http://amoeba.meidusa.com/wordpress/?p=14

    http://www.alinotes.cn/

    http://www.blogkid.cn/

    安全

    http://blog.csdn.net/kj021320

    http://blog.ph4nt0m.org/

    Linux C

    QA

     http://fafeng.blogbus.com/

    http://rdc.taobao.com/blog/qa/

    http://nmtcolin.itpub.net/category/5135/31300

  • Windows下远程运行LINUX 上jmeter GUI解析监视器数据

    2008-12-05 22:51:38

    Windows 内存不足,JMeter解析大量监视器数据导致OutOfMemory异常,故利用8G内存的LINUX机器上JVM解析jmeter  监视器数据。 LINUX无显示器连接。

     

    所以需要Windows下远程运行Linux图形界面,工具有Xming或者Xmanager等。

    更多参考:http://www.cs.nctu.edu.tw/help/xming.html

    1.1    下载XMing 安装在Windows

    http://sourceforge.net/projects/xming

    安装XMing

    1.2    检查LINUX  图形包

    [aranda@dc_14 ~]$ rpm -qa |grep xorg
    xorg-x11-server-utils-7.1-4.fc6
    xorg-x11-server-Xnest-1.1.1-48.41.el5

    1.3    Windows下启动XMing launch

    XMingSSH 连接环境下选择no  access control,则不必做额外的动作。

    1.4    LINUX shell上设置DISPLAY输出到WINDOWS

     

    export DISPLAY=客户端IP:0

     

     

    1.5    LINUX 上测试GUI

    Xclock

    ./jmeter.sh 起动jmeter

  • 开源的质量控制工具 Sonar

    2008-11-23 17:14:55

    http://sonar.codehaus.org/documentation/

    http://www.javaread.com/article/show/195

     

    安装指南:http://docs.codehaus.org/display/SONAR/Installation+guide

    http://docs.codehaus.org/display/SONAR/Frequently+Asked+Questions

     

    下载

    http://sonar.codehaus.org/downloads/

     

    sonar 整合代码覆盖率/规则检查等数据WEB图形化展现。

    预先条件

    window xp 上环境变量PATH已经加入D:\apache-maven-2.0.9\bin

    D:\apache-maven-2.0.9\my-webapp>java -version

    java version "1.5.0_14"

    Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_14-b03)

    Java HotSpot(TM) Client VM (build 1.5.0_14-b03, mixed mode)

    D:\apache-maven-2.0.9\my-webapp>mvn -v

    Maven version: 2.0.9

    Java version: 1.5.0_14

    OS name: "windows xp" version: "5.1" arch: "x86" Family: "windows"

     

    安装

    安装在,D:\sonar-1.4.3\conf

    InstallNTService.bat 安装服务

    StartNTService.bat启动服务

    IEhttp://127.0.0.1:9000/ 初步测试。

     

    缺省用户名密码:admin/admin

    WEB 页面上创建DB 创建后可以看到D:\sonar-1.4.3\conf\ sonar.properties

    sonar.jdbc.url:                            jdbc:derby://localhost:1527/sonar;create=true

    sonar.jdbc.driverClassName:                org.apache.derby.jdbc.ClientDriver

     

    IE展现图如下:

     

     

    配置与maven2的关联

    $MAVEN_HOME/conf (如D:\apache-maven-2.0.9\conf)或者 ~/.m2 下的settings.xml 文件加入下面内容

     

    <profile>

                <id>sonar</id>

                <activation>

                    <activeByDefault>true</activeByDefault>

                </activation>

                <properties>

                                    

                     <sonar.jdbc.url>

                      jdbc:derby://localhost:1527/sonar

                    </sonar.jdbc.url>

                    <sonar.jdbc.driver>org.apache.derby.jdbc.ClientDriver</sonar.jdbc.driver>

                    <sonar.jdbc.username>sonar</sonar.jdbc.username>

                    <sonar.jdbc.password>sonar</sonar.jdbc.password>              

                    <sonar.host.url>http://127.0.0.1:9000/</sonar.host.url>

                   

                </properties>

            </profile>

     

    配置一个maven2 工程pom.xml

     

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

      <modelVersion>4.0.0</modelVersion>

      <groupId>com.mycompany.app</groupId>

      <artifactId>my-webapp</artifactId>

      <packaging>jar</packaging>

      <version>1.0-SNAPSHOT</version>

      <name>my-webapp</name>

      <url>http://maven.apache.org</url>

      <dependencies>

        <dependency>

          <groupId>junit</groupId>

          <artifactId>junit</artifactId>

          <version>3.8.1</version>

          <scope>test</scope>

        </dependency>

      </dependencies>

    </project>

     

     

    编译发布

     

     

    D:\apache-maven-2.0.9\my-webapp>mvn org.codehaus.sonar:sonar-maven-plugin:1.4.3:sonar -Dsonar.skipInstall=true

     

     

    重新刷新IE数据,漂亮的数据图表展现在面前。

  • JAVA持续集成解决方案

    2008-11-21 00:10:08

     敏捷方法倡导java持续集成,并输送很多有用的工具。当前比较流行的持续集成服务工具有


    1) apache continuum
    2) CruiseControl
     
       配套做持续集成的工具包有
       1) JUnit 单元测试
       2) JUnitPerft或者eclipse tptp 做单元性能测试
       3) 数据库DDL初始化语句
       4) EasyMock 等模拟工具
       5) PMD,checkStyle,FindBug分析工具
       6)httpUnit HTTP接口测试
       7) purify/Jprofile 动态分析
       8) EMMA/Clover度量代码覆盖率
       9) JAVANCSS度量代码复杂度
       10) JDepend 度量耦合度
       10) 构建工具ant,
       11) 部署脚本
       12)分布式分发框架staf/stax
      
       如上工具通过与持续集成工具粘合,将产生强大威力。
      
       当前阿里巴巴平台架构师采用continuum+maven+mylyn+trac,淘宝采用cruisecontrol做接口测试。
      

  • 阿里巴巴性能测试规划思路

    2008-11-14 00:14:37


    1)充分利用已有性能测试脚本,做性能测试回归对比,形成性能测试结果趋势分析库
    2)补充JMeter LINUX/ORACLE监控功能,补充报表统计分析功能,增强分布式脚本分发功能,规避OutOfMemory异常
    3)进一步挖掘前端性能测试工具,记录生产环境页面响应时间变化趋势,利用浏览器上等图形展现框架表达趋势。另外,参考HP BAC产品开发一些补充功能
    4)公司级别日志挖掘功能,以及服务器端性能监控颗粒细化,公司多个PC机器访问时间等信息充分利用,完善生产环境负载模型
    5)最最重要的是,提高模拟海量数据/高并发模拟压力能力,避免系统上线性能问题。还需要利用JMX等技术开发监控JAVA服务器/apache 细颗粒的性能,
    降低性能调优难度
    6)性能测试人才梯队建设以及培训交流增强
  • 阿里巴巴自动化测试发展思路

    2008-11-01 21:39:02

      自动化总体要求是 自动化覆盖率更高,维护成本更低,挖掘层次更深,运行速度更快,培训力度和知识分享覆盖面更大,运营管理更加规范, WATIR框架平稳取代QTP框架

             1)   代码更加灵活。 比如代码可以通过配置数据库检查开关

    2)   由于代码变更,各小组接口人定期(每2个月?)结合代码覆盖率数据,给出各个小组自动化下一步功能自动化用例建议

    3)   人员增长很快,所以培训力度、分级制度更完善。 各个小组接口人注意跟上。 另外,知识分享做好可以大幅度降低学习门槛

    4)   项目发布后预留一些自动化脚本编写时间,以便及时维护、完善脚本,从而减少自动化脚本重复执行次数

    5)   脚本运行速度进一步提升。 从另外一个角度,力争研发单位预留至少一个晚上运行时间以及前一天必要的准备运行时间

    6)   继续完善自动化运行管理平台,自动统计、分析QTP/WATIR框架、脚本运行状况,图形化展现覆盖率数据趋势―――――――――――――――――――――――这个需要额外增强现有框架

    7)   接口人定期跟进项目,挖掘可自动化的点,主要由测试组实施。

    8)   测试小组第一期自动化脚本由QA架构组主导搭建,后期的维护、增强由测试组实施。工作重心在优化框架,解决部门级别公共自动化问题  

    9)   深入接口测试,SOA测试等,不局限于页面级别自动化

  • 改写jQuery实现固定表头,滚动内容

    2008-10-26 00:57:04

    参考 http://blog.csdn.net/hu_zhenghui/archive/2007/12/02/1911733.aspx

     

     

    原来事件处理采用:

     

    <scrīpt src="scrīpts/jQuery.js"></scrīpt>

      <scrīpt>

          $(document).ready(function () {

           

              $("#tableContainer").scroll(function () {

                 // $("#divx").get(0).scrollLeft = this.scrollLeft;

                  $("#divy").get(0).scrollTop = this.scrollTop;

              });

             

             

          });

      </scrīpt>

     

    例子采用3个表,存在列宽/行高同步的问题。

     

    偶改写了事件,特别注意标红色的style 要素overflow

     

     

           <div id="tableContainer" style="width:1000px; height:600px; overflow:scroll">

    <table border="1" cellpadding="0" cellspacing="0" width="100%" class="scrollTable"  id="scrollTable" >

    <thead>

           <tr>

           <th>

                         <div> 标题</div>

    </th>

    <tr>

    </thead>

    <tbody id="tbSCMProject" class="tbSCMProject">

    </tbody> 

     

     

    <td valign="top"  >

                                       <div id="divy" style="width:300px; height:600px; overflow:hidden">  

    <table id="table_y" border="3">

                                                       

                        <tr><div style="height:51.5px">内容       </div>

                                </tr>

                                                                                                                                         </table>          

     

    </div>

     

     

    <scrīpt   language="javascrīpt">  

     

     var divScrollHander= function()

    {

                                       var thisContainer = document.getElementById('tableContainer');

                                       var ōbjdivy =    document.getElementById('divy');

                                       if (!thisContainer || !objdivy)

                                       {

                                                           

                                                      return;

                                       }    

                                      

                                       objdivy.scrollTop=thisContainer.scrollTop;

        }

       

       

      tableContainer.attachEvent('onscroll',divScrollHander);

       

    </scrīpt>

     

    </body>

     

     

    由于采用2个表,如何让2个表的行高度一致,不至于适配?下面的图看到,需要2个表的同一行移动需要同步。

     

     

     

  • Spring+ quartz 在jboss内实现定时任务

    2008-10-19 14:28:49

    参考

     

    http://www.cnblogs.com/phinecos/archive/2008/09/03/1282747.html

    http://www.blogjava.net/hwpok/archive/2008/08/19/223124.html

    http://www.cnblogs.com/phinecos/archive/2008/09/03/1283376.html

     

     

    com\ali\schedule\ quartz.xml内容

     

    <?xml version="1.0" encoding="UTF-8" ?>

    <beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

        <bean name="dataImportjobDetail"

            class="org.springframework.scheduling.quartz.JobDetailBean">

            <property name="jobClass"

                value="com.ali.schedule.DailyDataImportJob" />

            <property name="jobDataAsMap">

                <map>

                    <entry key="dataImportService" value-ref="dataImportService" />

                </map>

            </property>

            <property name="applicationContextJobDataKey"

                value="applicationContext" />

        </bean>

     

        <bean id="dataImportService" class="com.ali.schedule.ProjDataImportService" />

       

      

        <bean id="dataImportTrigger"

            class="org.springframework.scheduling.quartz.CronTriggerBean">

            <property name="jobDetail" ref="dataImportjobDetail" />

            <property name="cronExpression" value="*/5  * * * * ?" />

        </bean>

       

        <bean id="scheduler"

            class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

            <property name="triggers">

                <list>

                    <ref bean="dataImportTrigger" />

                </list>

            </property>

            <property name="schedulerContextAsMap">

                <map>

                    <entry key="timeout" value="30" />

                </map>

            </property>

            <property name="quartzProperties">

                <props>

                    <prop key="org.quartz.threadPool.class">

                        org.quartz.simpl.SimpleThreadPool

                    </prop>

                    <prop key="org.quartz.threadPool.threadCount">10</prop>

                </props>

            </property>

        </bean>

    </beans>

     

     

    值得注意的是:

    <!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序  -->
        
    <bean id="scheduler"   lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            
    <property name="triggers">
                
    <list>
                  
    </list>
            
    </property>
        
    </bean>
    </beans>

     

    调度程序:

     

    package com.ali.schedule;

    import org.quartz.JobExecutionContext;

    import org.quartz.JobExecutionException;

    import org.springframework.context.ApplicationContext;

    import org.springframework.context.support.ClassPathXmlApplicationContext;

    import org.springframework.scheduling.quartz.QuartzJobBean;

    public class DailyDataImportJob extends QuartzJobBean {

        public DailyDataImportJob()

        {

          

        }

        protected void executeInternal(JobExecutionContext jobcontext) throws JobExecutionException

        {

           service.importData();

        }

        private ProjDataImportService service;

        public void setDataImportService(ProjDataImportService service)

        {

           this.service=service;

        }

        public static void main(String[] args){

           //这里用于测试

           String configPath = "com/ali/schedule/quartz.xml";

           ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);

           ctx.getBean("scheduler");

        }

     

    }

     

     

    真正执行任务程序:

    package com.ali.schedule;

     

    import org.springframework.context.ApplicationContext;

     

    import org.springframework.context.support.ClassPathXmlApplicationContext;

    import org.springframework.context.support.FileSystemXmlApplicationContext;

     

    import com.ali.IIbatisDAOImpl;

     

    public class ProjDataImportService {

        public void importData() {

     

    //当前路径下

          

           String[] locations = {"com/ali/db/database.xml"};

     

       

        ApplicationContext context = //new FileSystemXmlApplicationContext(locations);

           new  ClassPathXmlApplicationContext(locations);

     

          

               IIbatisDAOImpl DAO = (IIbatisDAOImpl) context.getBean("IIbatisDAOImpl");

     

           DAO.importHisProjData();

     

        }

     

        public static void main(String[] args) {

     

            ProjDataImportService service = new ProjDataImportService();

           service.importData();

        }

     

    }

     

     

    依赖库:

    需要加入spring.jar  quartz.jar    log4j-1.2.14.jar   commons-collections.jar   jta.jar   commons-logging.jar这几个包

     

    如上都是在控制台应用下执行。由于spring工程、ibatis工程读取xml文件路径与JBOSS/TOMCAT web应用路径都不一样。控制台测试成功后,需要更改如上javaXML 路径依赖。

     

    WEB环境下使用调度程序,则需要在web.xml加载quartz.xml配置文件。

     

           <context-param>

                  <param-name>contextConfigLocation</param-name>

                  <param-value>

                         /WEB-INF/database.xml

                         /WEB-INF/applicationContext.xml

                         /WEB-INF/quartz.xml

                  </param-value>

           </context-param>

     

  • 子html 页面刷新父页面并关闭

    2008-10-15 23:19:25

    Child.html 关闭刷新父页面并关闭

     

     

    if (window.opener && !window.opener.closed) {

                                      

                                              var site=document.getElementById("hidden_currSite").value;

                                             

                                              var publishdate=document.getElementById("publishdate").value;

                                             

                                              var str_url="project.do?site="+site +"&publishdate="+publishdate;

                                                                                        window.opener.location.href=str_url;          

                                              //window.opener.location.reload();                         

             }

     

    window.close();

     

     

    html页面:

     

    window.open("child.htm ?projectid="+projectid+"&site="+site);

     

    同时为了保证取到更新的数据,应该禁止cache

    <Html>

    <head>

           <meta http-equiv="pragma" content="no-cache">

     <meta http-equiv="cache-control" content="no-cache, must-revalidate"> 

        <meta http-equiv="expires" content="0">

    </head>

     

     

    有朋友可能对不用window.opener.location.reload(); 存疑。

     

    当父页面之前是http post 请求,用window.opener.location.reload(); 会导致再次Post,这个可能不是我们期望的结果。

  • javascript 在Firefox 3.0与IE6 脚本下不同表现以及解决方法

    2008-10-09 23:24:10

    1.1       getElementById 区别

    <select name="month">  

    <option>Jan</option>  

    <opton>Feb</option>  

    </select>  

    <select name="month">

    <option>Jan</option>

    <opton>Feb</option>

    </select>

     

    IE中:

    document.getElementById("month") 正确

    document.getElementsByName("month") 正确

     

    Firefox:

    document.getElementById("month") 错误(必须加属性Id)

    document.getElementsByName("month") 正确 

     

    故通用方法编写标准html语法,然后用 document.getElementById.

     

    1.2       FireFox 不支持vbscrīpt

     

     

    1.3       Firefox 定位form

     

    Form 定义   <form name="userlist" id="userlist"  method="post" action="userlist.do">

     

    仅仅IE支持直接访问:

     

    userlist.pageSize.value="20";

            userlist.submit();

     

     

    通用函数

           function goto(p) {

            document.forms["userlist"].page.value=p;

            document.forms["userlist"].pageSize.value="20";

            document.forms["userlist"].submit();

    }

     

     

     

    1.4       事件函数

     

    仅仅 IE支持 document.onclick(){ 这种方式书写。

     

      function document.onclick(){

         with(window.event.srcElement){

        if (tagName != "INPUT" && getAttribute("Author") != "tiannet")

        tiannetHideControl();

         }

       }

    FireFox上提示: missing ( before formal parameters,javascrīpt error

     

     

    1.5       Console关键字

      <scrīpt   type='text/javascrīpt'>  

       

      var   http_request=null;

      alert(console); 

      var   console=null;  

     

    </scrīpt>

     

    firefoxconsole为一个对象

    setting a property that has only a getter

     

     

     

     

    IE 表现为未定义

     

     

    1.6       事件处理

     

    http://www.phpchina.com/12834/viewspace_29308.html

    http://www.javaeye.com/topic/47917

     

     

    如:

     

    function getEvent(){     //同时兼容ieff的写法

            if(document.all)    return window.event;        

            func=getEvent.caller;            

            while(func!=null){    

                var arg0=func.arguments[0];

                if(arg0){

                    if((arg0.constructor==Event || arg0.constructor ==MouseEvent)

                        || (typeof(arg0)=="object" && arg0.preventDefault && arg0.stopPropagation)){    

                        return arg0;

                    }

                }

                func=func.caller;

            }

            return null;

    }

     

     

        //任意点击时关闭该控件

       document.onclick=function(){  

         var ōbjevent= getEvent();   //window.event ;//getEvent();

        

        

          if( typeof(objevent.srcElement) == "undefined")

          {

                with(objevent.target)

                {

                             if (tagName != "INPUT" && getAttribute("Author") != "tiannet")

                             {

                                                  tiannetHideControl();

                             }

                }

              }

              else

         {   

               with(objevent.srcElement)

                {

                             if (tagName != "INPUT" && getAttribute("Author") != "tiannet")

                             {

                                                  tiannetHideControl();

                             }

                }      

         }

       }

     

     

     

    1.7       Document.all

    IE 特有:

    document.all.selTianMonth

     

    通用

    document.getElementById('selTianMonth')

     

    1.8       innerText

    http://www.cnlei.org/blog/article.asp?id=425

     

    Firefox下的DOM对象增加innerText属性:

    <scrīpt type="text/javascrīpt">

    var lBrowser = {};

    lBrowser.agt = navigator.userAgent.toLowerCase();

    lBrowser.isW3C = document.getElementById ? true:false;

    lBrowser.isIE = ((lBrowser.agt.indexOf("msie") != -1) && (lBrowser.agt.indexOf("opera") == -1) && (lBrowser.agt.indexOf("omniweb") == -1));

    lBrowser.isNS6 = lBrowser.isW3C && (navigator.appName=="Netscape") ;

    lBrowser.isOpera = lBrowser.agt.indexOf("opera") != -1;

    lBrowser.isGecko = lBrowser.agt.indexOf("gecko") != -1;

    lBrowser.ieTrueBody =function (){

      return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body;

    };

    //Firefox下的DOM对象增加innerText属性

    if(lBrowser.isNS6){ //firefox innerText define

      HTMLElement.prototype.__defineGetter__( "innerText",

      function(){

      return this.textContent;

      }

      );

      HTMLElement.prototype.__defineSetter__( "innerText",

      function(sText){

      this.textContent=sText;

      }

      );

    }

    alert(lBrowser.isNS6);

    </scrīpt>

     

    1.9       eval

    创建过程:

     

       for (var i=0;i<5;i++) {

        document.write (' <tr align=center id="trTiannetDay' + i + '" >');

        for (var j=0;j<7;j++){

         document.write('<td align="center" id="tdTiannetDay' + n + '" '+

        'onClick="tiannetDay=this.innerText;tiannetSetValue(true);" '

          +' style="' + s_tiannet_day + '">&nbsp;</td>');

         n ++;

        }

        document.write (' </tr>');

       }

     

     

    IE特有:

      for (var i = 0; i < 35; i++){

     eval("document.all.tdTiannetDay"+i);

          

     

    通用:

         var ōbjname="tdTiannetDay"+ i;

         var da =  eval( document.getElementById(objname)); 

     

           if (typeof(da) == undefined)

               {

                       alert("document.getElementById(tdTiannetDay"+i+"is null");

               }

               else

               {

                   alert(da.tagName);

                      //alert(typeof(da.constructor));

               }

     

    查找到一个区别:http://kongjian.baidu.com/freezesoul/blog/item/f6b7e5cd275752510eb34548.html

     

    javascrīptdom对象和普通对象可以通过判断tagName属性来区别,但是这不是非常好的办法,因为你很难禁止他人在普通对象中定义tagName属性。另外一个比较好的方法是dom对象的constructor属性一般为undefined(同时,显然地,instanceof Object将返回false,这是它们区别其他对象的一个明显特征

     

     

    1.10   execscrīpt

    如: window.execscrīpt("c = Asc(c)", "vbscrīpt");

    仅仅IE支持

     

  • Spring Velocity macro应用与调试

    2008-09-26 22:24:00

    默认情况下,velocity macro文件修改没有被应用服务器检测,必须重启才能生效。

     

     

    Spring  web.xml contextConfigLocation配置包含属性文件mvc-config.xml

     

    <servlet>

    <servlet-name>dispatcherServlet</servlet-name>     

    <servlet-class>  org.springframework.web.servlet.DispatcherServlet        </servlet-class>      

    <init-param>          

    <param-name>contextConfigLocation</param-name>         

    <param-value>

    /WEB-INF/mvc-config.xml

    /WEB-INF/alert-config.xml

    </param-value>   

    </init-param>  

    <load-on-startup>1</load-on-startup>  

     </servlet>

     

     

    mvc-config.xml 部分内容如下:

     

                  <bean id="velocityConfigurer"                           class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">

                  <property name="resourceLoaderPath">

                  <value>WEB-INF/velocity/</value>  

                  </property>

                  <property name="velocityProperties">

                         <props>

                         <prop key="input.encoding">gb2312</prop>

                         <prop key="output.encoding">gb2312</prop>

                         <prop key="contentType">text/html;charset=gb2312</prop>

                         <prop key="file.resource.loader.cache">false</prop>

                         <prop key="file.resource.loader.modificationCheckInterval">1</prop>

                         <prop key="velocimacro.library.autoreload">true</prop>

                         <prop key="velocimacro.library">templates.vm</prop>

                         <prop key="runtime.log.logsystem.class">org.apache.velocity.runtime.log.SimpleLog4JLogSystem</prop>

                         <prop key="runtime.log">com.ali</prop>

                         <prop key="runtime.log.error.stacktrace">true</prop>

                         <prop key="runtime.log.warn.stacktrace">true</prop>

                         <prop key="runtime.log.info.stacktrace">false</prop>

                         <prop key="runtime.log.invalid.reference">true</prop>

                  </props>

                  </property>

     

           </bean>

          

             <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">

               <property name="suffix"><value>.vm</value></property>

                         <property name="exposeSpringMacroHelpers"><value>true</value></property>

                         <property name="exposeRequestAttributes"><value>true</value></property>

                         <property name="exposeSessionAttributes"><value>true</value></property>

                         <property name="contentType" value="text/html;charset=gb2312" />

                         <property name="dateToolAttribute">

          <value>dateTool</value>

               </property>

            </bean>

     

     

     

    Velocity 文件包括库文件templates.vm都放在WEB-INF/velocity/

    确保velocity文件被修改都立即重新扫描,关键的参数:

    <prop key="file.resource.loader.cache">false</prop>

                         <prop key="file.resource.loader.modificationCheckInterval">1</prop>

                         <prop key="velocimacro.library.autoreload">true</prop>

     

     

    index.vm上通过:

    #parse("templates.vm") 引入velocity 模版。

  • Spring+mysql+velocity 中文问题解决方法

    2008-09-23 13:11:20

    碰到中文问题主要有几类:

    1)      confluencemysql数据库导出的 UTF-8数据

    2)      http get/post 请求中汉字

    3)      ajax xmlhttprequest传递的汉字

    4)      mysql 环境设置

    5)      spring /velocity /jboss环境的中文配置

     

    成功的文件配置关键内容如下:

    1.1       spring2应用Web.xml 配置

     

    <filter>

                  <filter-name>encodingFilter</filter-name>

                  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

                  <init-param>

                         <param-name>encoding</param-name>

                         <param-value>GB2312</param-value>

                  </init-param>

                 

                  <init-param>

                <param-name>forceEncoding</param-name>

                <param-value>true</param-value>

        </init-param>

     

           </filter>

     

     

    1.2       Ibatis  sqlmap-config.xml

     

    <?xml version="1.0"  encoding="UTF-8" ?>

     

     

    1.3       ibatis jdbc配置:

    jdbc.driverClassName=com.mysql.jdbc.Driver

    jdbc.url=jdbc:mysql://127.0.0.1:3306/scmproj?useUnicode=true&characterEncoding=UTF-8

     

     

     

     

    1.4       spring mvc:

     

           <bean id="velocityConfigurer"                           class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">

                  <property name="resourceLoaderPath">

                  <value>WEB-INF/velocity/</value>  

                  </property>

                  <property name="velocityProperties">

                         <props>

                         <prop key="input.encoding">GB2312</prop>

                         <prop key="output.encoding">GB2312</prop>

                         <prop key="contentType">text/html;charset=GB2312</prop>

                         <prop key="file.resource.loader.cache">false</prop>

                         <prop key="file.resource.loader.modificationCheckInterval">1</prop>

                         <prop key="velocimacro.library.autoreload">true</prop>

                         <prop key="velocimacro.library">templates.vm</prop>

                         <prop key="runtime.log.logsystem.class">org.apache.velocity.runtime.log.SimpleLog4JLogSystem</prop>

                         <prop key="runtime.log">com.ali</prop>

                         <prop key="runtime.log.error.stacktrace">true</prop>

                         <prop key="runtime.log.warn.stacktrace">true</prop>

                         <prop key="runtime.log.info.stacktrace">false</prop>

                         <prop key="runtime.log.invalid.reference">true</prop>                        

                  </props>

                  </property>

     

           </bean>

          

             <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">

               <property name="suffix"><value>.vm</value></property>

                         <property name="exposeSpringMacroHelpers"><value>true</value></property>

                         <property name="exposeRequestAttributes"><value>true</value></property>

                         <property name="exposeSessionAttributes"><value>true</value></property>

                         <property name="contentType" value="text/html;charset=UTF-8" />

                         <property name="dateToolAttribute">

          <value>dateTool</value>

               </property>

            </bean>

          

     

    由于页面上文字是汉字,但数据库为utf-8VelocityViewResolvercontentType必须为UTF-8 ,否则部分复杂汉字无法正常显示。如璟。

     

     

    1.5       Mysql5.0创建数据库:

    create database scmproj DEFAULT CHARACTER SET utf8;

     

    1.6       mysql 的配置文件my.ini

    [mysql]

     

    default-character-set=gb2312

    [mysqld]

    default-character-set=utf8

     

    1.7       velocity页面

     

     

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <%@page pageEncoding="gb2312"%>

    <html xmlns="http://www.w3.org/1999/xhtml">

    <head>

    <meta http-equiv="Content-Type" content="text/html;charset=gb2312" />

     

     

    1.8       velocity 表单提交前编码

     

    <scrīpt language="vbscrīpt">

     

    Function GetByteCode(ch)  

     

        code = Asc(ch)          ' -20001

     

        GetByteCode = Hex(code) ' "B1DF"

     

    End Function

     

    </scrīpt>

     

     

    <scrīpt language="javascrīpt">

     

    String.prototype.urlEncode = function() {

     

        var r = "";

     

        for (var i = 0; i < this.length; i++) {

     

            var code = "" + GetByteCode(this.charAt(i));

     

            if (code.length > 2) {

     

                var b1 = code.substr(0, code.length - 2);

     

                var b2 = code.substr(code.length - 2);

     

                if (i == 0) {

     

                    //alert("" + code + ", " + b1 + ", " + code.length + ", " + b2);

     

                }

     

                r += "%" + b1 + "%" + b2;

     

            } else {

     

                r += "%" + code;

            }

        }

        return r;

    }

     

    </scrīpt>

     

     

    Function checkform()

    {

     

    var ōldvalue= document.formtips.content.value;

                  if(oldvalue=="")

                  {

                         alert("请设置值");

                         return false;

                  }

                  var urlEncodeResult=oldvalue.urlEncode();

                 

                  document.formtips.content.value=urlEncodeResult;   

    }

     

    1.9       接收form表单的服务器端JAVA代码

     

    protected ModelAndView onSubmit(HttpServletRequest request,

                         HttpServletResponse response, Object command, BindException errors)

                         throws Exception {

     

                  try {

                         SCMTips tips = (SCMTips) command;

                        

                         if (logger.isInfoEnabled()) {

                                logger.info("before decode content:" + tips.getContent());

                                logger.info("requestEncode="+ request.getCharacterEncoding());

                         }

     

                         String decoderesult = java.net.URLDecoder.decode(tips.getContent(),

                                       "gb2312");

     

                         if (logger.isInfoEnabled()) {

                                logger.info("decode result:" + decoderesult);

                         }

     

    1.10  AJAX 发送端

     

    function  makeHttpReq()

      {

          var new_httpreq = null;

          if (window.XMLHttpRequest) {

                    new_httpreq = new XMLHttpRequest();

                    if (new_httpreq.overrideMimeType){

                     new_httpreq.overrideMimeType('text/xml');

                    }

                   } else if (window.ActiveXObject) {

                    try{

                     new_httpreq = new ActiveXObject("Msxml2.XMLHTTP");

                    } catch (e) {

                     try {

                      new_httpreq = new ActiveXObject("Microsoft.XMLHTTP");

                     } catch (e) {

                     }

                    }

                   }

                  return  new_httpreq;

      }

     

     

         if (httpReq)  {  
              httpReq.onreadystatechange  =  function(){
                if(httpReq.readyState == 4)
                {
                 //var console=document.getElementById('console'); 
                 //alert(httpReq.responseText);
                 //console.innerHtml = httpReq.responseText;
                 }
           };
              
              httpReq.open("GET",   url,   true);  
              httpReq.setRequestHeader("If-Modified-Since","0");
              httpReq.send(null);  
          }    
      

    从上面可以看到httqreq没有指定编码格式。默认就是ISO-8859-1。

    2.11 接收ajax处理的服务器端代码
    public ModelAndView handleRequestInternal(HttpServletRequest request,
       HttpServletResponse response) throws Exception {

      if (request.getMethod().equals("GET")) {
       String encodeProj = request.getParameter("projectname");
       if (logger.isInfoEnabled()) {
        logger.info("before decode:" + encodeProj);
       }
       //客户端经过编码后的汉字   
       String projectname= new String( encodeProj.getBytes( "8859_1" ) , "gb2312" );
       if (logger.isInfoEnabled()) {
        logger.info("after decode:" + projectname);
       }


    2.12 JBOSS4.2配置
    D:\jboss-4.2.2.GA\server\default\deploy\jboss-web.deployer \Server.xml 里面
        -->
        <Connector port="8080" address="${jboss.bind.address}"   
             maxThreads="250" maxHttpHeaderSize="8192"
             emptySessionPath="true" protocol="HTTP/1.1"
             enableLookups="false" redirectPort="8443" acceptCount="100"
             connectionTimeout="20000" disableUploadTimeout="true"  />

    没有修改URIEncoding

     

     

1614/9<123456789>
Open Toolbar