Archive for category develop

Date: 八月 30th, 2010
Cate: develop

Opera下多选select控件bug一枚

1: 首先用以下代码从多选的select控件中删除多个选项

for(var i=from.options.length-1;i>=0;i—) {
    var tempOption=from.options[i];
    if(tempOption.selected){
        from.removeChild(tempOption);
    }
}

2: 选中多个选项,执行上面的代码,除opera的其他浏览器都能够正确删除选中的多个选项,只有opera只能删除序号最大那个选中的选项,测试版本为opera 10.61

3: 经过仔细观察得知,删除一个选项以后,整个select控件失去焦点,于是所有选项的selected属性都变成false,所以以上代码的if语句除第一次外都跳过了,所以只成功删除序号最大的选中的那项

4: 基本解决思路: 先把选中选项的index用一个数组记录下来,然后根据选项序号从大到小删除对应选项. 或者放弃支持opera这么小众的浏览器,况且这还是个bug,不一定非要处理这种情况

5: 已经把bug提交给opera开发

Date: 四月 12th, 2010
Cate: develop

JavaScript中将unicode代码字符转为真实字符

<script type="text/javascript">
    function UnicodeToStr(str){
        var re = /&#[\da-fA-F]{1,5};/ig;
        var arr = str.match(re);
        if(arr == null) {
            return str;
        }
        var temp;
        for(var i = 0;i < arr.length; i++){
            str = str.replace(arr[i], String.fromCharCode(arr[i].replace(/[&#;]/g,"")));
        }
        return str; 
    }
    alert(UnicodeToStr("&#37;"));
</script>

Date: 三月 5th, 2010
Cate: develop

不同浏览器对iframe与主页面dom树的不同理解

悄悄的IE8/firefox/opera与IE6/7/chrome对iframe与主页面dom结构的理解产生了分歧.
在IE6/7/chrome中iframe的dom树与主页面是独立的, 因此将iframe中的节点移动到主页面中会报错.
而在IE8/firefox/opera中iframe的dom树与主页面是相关的, 因此将iframe中的节点移动到主页面中会成功.
测试代码如下

iframe.html:

<div id="testdiv">inside a iframe</div>

主页面:

<iframe id="testiframe" src="iframe.html"></iframe><br />
<div>here is main content</div>
<script type="text/javascript">
    var iframe = document.getElementById("testiframe");
    setTimeout(function(){
        var testdiv = iframe.contentWindow.document.getElementById("testdiv");
        alert(testdiv.innerHTML);
        document.body.appendChild(testdiv);
        document.body.innerHTML += testdiv.outerHTML;
    }, 200);
</script>

首先等待200毫秒让iframe加载进来, 再验证的确取到了iframe中的内容, 然后将节点append到主页面, 然后就观察到了上面所描述的现象.
以上的分歧影响到了其他的JS库, 如JQuery, $("body").append()一样会有问题.
弥补方法则是判断浏览器类型, 然后用innerHTML绕过这个限制.
有趣的是,注释掉appendChild语句后发现, 在所有浏览器中只有firefox不支持outerHTML这个事实标准了.

Date: 十月 13th, 2009
Cate: develop

IBM Portal中从portal向portlet传参数的方法

虽然不是portlet规范中所定义的方法,但有的时候hack真的无法避免.以下方法在IBM Portal 6.1中测试通过.

先在portal(比如theme)中设置

request.setAttribute("testKey","testValue");

然后在portlet中使用

//用内部方法取得portal的http request

HttpServletRequest httpReq = com.ibm.wps.pe.pc.std.core.PortletUtils.getInternalRequest(portletRequest).getHttpServletRequest();

httpReq.getAttribute("testKey");

其实portletRequest.getAttribute(…)本身就包含很多好东西,甚至包含portal的session,只是取的方法很麻烦.

Date: 五月 25th, 2009
Cate: develop

在portlet里成功使用sendRedirect的条件

在spring portlet的过程总发现使用actionResponse.sendRedirect(String url)有时成功有时不成功, 甚是蹊跷.
查阅portlet api后得知sendRedirect不能与一些方法同用, 相信如同在servlet里不能先out.print再sendRedirect一样, 因为outputstream不能打开两遍.
不能一同使用的方法是

  • setPortletMode
  • setWindowState
  • setRenderParameter
  • setRenderParameters
  • removePublicRenderParamter
  • 由此引发的问题是, sendRedirect不能与很多类或者方法一起使用. 如

    spring中的parameterMappingInterceptor, 因为这个handler里主动调用setRenderParameter设置返回render方法的action参数.

    这种例子会有很多, 只能使用过程中密切注意.
    这里另一篇类似问题的文章, http://forum.springsource.org/showthread.php?t=55857, 是它使我获得灵感.

    Date: 七月 2nd, 2008
    Cate: develop

    JAVA中使用HTTP 1.1提高基于AXIS 1.4的web service的性能

    HTTP 1.1会在第一次连接的时候进行认证, 而在一定时间内保持连接而不用重新验证. 一般情形下,每个web service请求都会在web service服务端验证, 而验证会消耗很多时间, 因此改进或减少验证的次数, 并且使用HTTP 1.1来保持长时间连接能够极大的提高web service性能.

    JAVA中使用Axis 1.4时,默认使用HTTP 1.0来传输web service请求.因此需要配置其使用HTTP 1.1.

    以下是配置Axis 1.4使用HTTP 1.1的方法:

    1. 配置Axis使用CommonsHTTPSender代替默认的HTTPSender.
    方法可查看apache的wiki: http://wiki.apache.org/ws/FrontPage/Axis/AxisCommonsHTTP

    如果缺乏配置client-config.wsdd的条件(比如没权限碰环境,或者是某个共享环境), 可以换个方式在代码里强制调用:

         EngineConfiguration defaultConfig = EngineConfigurationFactoryFinder.newFactory().getClientEngineConfig(); 
         SimpleProvider config = new SimpleProvider(defaultConfig); 
         config.deployTransport(HTTPTransport.DEFAULT_TRANSPORT_NAME,new CommonsHTTPSender()); 
         ServiceLocator locator = new ServiceLocator(config);

    2. 使locator静态化:
             ServiceLocator必须只实例化一次. 然后在所有stub中共用. 之所以如此是因为ServiceLocator管理着http connection的连接池, 它通过CommonsHTTPSender的引用管理着MultiThreadedHttpConnectionManager.

    3. 在每个请求(stub)中都发送web service的用户名和密码. 默认情况下axis不会在每个请求初始的时候发送用户名密码, 此时服务器会返回401标志(unauthorized error), 而401标志会要求提供用户名密码然后重做登陆验证, 因此为了拒绝出现401登陆的情形, 每次都应该主动提供用户名和密码.在代码中可以这么写:

         Hashtable headers = new Hashtable(); 
         headers.put(HTTPConstants.HEADER_AUTHORIZATION, "Basic " + Base64.encode(username + ":" + password).getBytes()));
         stub._setProperty(HTTPConstants.REQUEST_HEADERS, headers);

    或者:

         System.setProperty("httpclient.authentication.preemptive", "true"); 
         然后 
         stubServicePort._setProperty(Call.USERNAME_PROPERTY, username); 
         stubServicePort._setProperty(Call.PASSWORD_PROPERTY, password);

    本质上是一样的, 后者只是通过调节asix中包含的httpclient包来达到目的而已.

    以上代码表示在每次都在SOAP头部中包含Basic验证的Base64加密的用户名:密码的字符串.也因此推荐对web service使用https连接(如果是内网就不必了), 当然这个本来也是要在网络中传递的, 与是否使用了这个方案无关.

    实际的效果表明这个方案很有效, 我的案例是从每次6-7秒(大部分是登陆验证时间, 而这个验证的方法是别人维护的)降到了0.5秒.