存档

文章标签 ‘java’

jQuery work with CKEditor

2011年9月29日 没有评论

最近忙于搞一个后台,开始只使用jQuery的ThickBox 组件,结果后台一工作发现杂七杂八的特殊符号得一一过滤,要不然就会影响界面的显示。一怒之下,引入富文本编辑器,直接使用了工程中原来就有的ckeditor,关于ckeditor的种种配置就不再讲述了,简单的很,手册可以参考这儿。
获取textarea对象
<textarea id=”content” style=”width: 512px; height: 40px;” name=”content” rows=”5″ cols=”50″>cftea</textarea>

对textarea操作的时候,直接使用jQuery的$(“#editorid”).val(“设置新的值”)不起作用,最后用下面的语句搞定

CKEDITOR.instances.content.setData("秘密小黑屋"); // content 就是前面 CKEDITOR.replace 的第一个参数值

或者使用

var editor = CKEDITOR.replace("content");
editor.setData("秘密小黑屋");

获取值,可以使用

alert(CKEDITOR.instances.content.getData()); // content 就是前面 CKEDITOR.replace 的第一个参数值

或者

var editor = CKEDITOR.replace("content");
alert(editor.getData());

直接使用jQuery的模式也起作用

alert($("#content").val());

另外,jQuery的表单清空,多个不同项目的时候可以使用下面的组合:

           $(':input','#myform')                    //所有input,传入form表单的id
                 .not(':button, :submit, :reset, :hidden')   //除去这些按钮的操作
		 .val('')                                    //值清空
		 .removeAttr('checked')             //去掉checkbox的选择
		 .removeAttr('selected');           //去掉select box的选择

org.springframework.dao.IncorrectResultSizeDataAccessException

2011年9月6日 没有评论

今天在写一个游戏接口的时候,以为数据库中就一条记录,想当然的写下了

select appid, code, name, url from hall_games where code=:code

测试机上一运行就出现这个异常。
org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 0 or 1, actual 8: com.xiaonei.in.dao.LoginUserDAO#getHallGameInfo

于是查看文档。
Data access exception thrown when a result was not of the expected size, for example when expecting a single row but getting 0 or more than 1 rows。
当期望返回的结果记录是1时,如果返回值为0或者>1会抛此异常。于是修改sql,当需要一条数据的时候,还是老实加上limit 1比较好。

select appid, code, name, url from hall_games where code=:code limit 1

HttpClient模拟操作https网站

2011年8月5日 没有评论

在日常工作中,我们常常需要抓取一些网站的信息为自己所用,比如自动抓取天气预报啊,抓取sina的股票数据,某些图片网站的美图等等,这就需要spider出场了,其实每种语言都有自己的写法,比如在Linux下,第一眼想到的就是wget,这是个强大的工具,可以递归地抓取网站,有windows下的版本,在本文章中还是说下Java的方式,那就是著名的开源软件HttpClient,在使用HttpClient的时候,我们需要知道网站的运行方式,可能在中间跳转了好几次,为了看到这些信息,我们还需要一点工具,Firefox的话直接中Httpfox就可以了,在IE下可以使用Httpwatch,官方下载地址是这个http://www.httpwatch.com,具体的使用很简单,不会的可以参考这个:http://www.cnblogs.com/mayingbao/archive/2007/11/30/978530.html
完事具备了,我们来看看怎么使用Httpclient

public static HttpMethod loginXN() throws IOException {
                PostMethod post = new PostMethod("http://passport.renren.com/PLogin.do");
		NameValuePair user = new NameValuePair("email",
				"zhangsan@hotmail.com");
		NameValuePair pwd = new NameValuePair("password", "12345");
		NameValuePair domain = new NameValuePair("domain", "renren.com");
		post.setRequestBody(new NameValuePair[] { user, pwd, domain});
		return post;
}

如果是https的请求,略微麻烦一点,需要使用SSLProtocolSocketFactory,在new HttpClient实例的时候,需要指定一下。

public static String httpGet(String url,Header header) {
        Protocol myhttps = new Protocol("https", new SSLProtocolSocketFactory(), 443);
        String result = "";
        HttpClient httpClient = new HttpClient();
        GetMethod getMethod = new GetMethod(url);
        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                new DefaultHttpMethodRetryHandler());
        int statusCode = 1000;//默认代码Connection refused
        try {
            httpClient.getHostConfiguration().setHost("passport.dudusp.com",443,myhttps);
            getMethod.addRequestHeader(header);            
            statusCode = httpClient.executeMethod(getMethod);//执行getMethod
            if (statusCode == HttpStatus.SC_OK) {
                result = getMethod.getResponseBodyAsString();
            }
        } catch (Exception e) {
            log.info(e.getMessage(), e);
        } finally {
            getMethod.releaseConnection(); //释放连接
        }
        return result;
    }

公司的passport验证原理

2011年8月4日 没有评论

最近为了安全考虑,出了套验证机制。passport处理未登录用户的过程大致为:
1.用户访问应用服务器A
2.如果用户未登录A,自动重定向到passport服务器
3.passport验证登录成功后,返回验证票
4.应用服务器A使用验证票到passport服务器进行二次验证
5.passport二次验证成功后,返回用户名

根据上述处理过程,passport的使用方法为:
1.passport的请求地址为:passport.no.xxxx.com;
2.应用服务器请求passport页面时,需提供forward跳转参数;
3.passport接收请求,验证正确的情况下,返回验证票(ticket参数);
4.应用服务器二次验证的过程为:
1)构造HTTP REFERER请求头;
2)携带HTTP REFERER请求头,远程读取passport.no.xxxx.com/verify.php?t=$ticket(该$ticket为 passport返回的ticket)地址的内容;
3)如果passport验证成功,返回用户名,否则返回空串。

passport的使用示例如下(以MM系统为例http://mm.renren.com/index.php):
1.MM请求访问passport的地址:https://passport.no.xxxx.com/login.php?forward=http://mm.renren.com/index.php
2.passport验证成功后,将地址重定向到http://mm.renren.com/index.php/index.php?ticket=nscr3omh80rn367h5pu0dq76u0
3.MM系统处理passport验证票($ticket参数)的过程为:

   function auth_check_valid($ticket){
       if($ticket == "")
           return false;
 
       $opts=array(
           'http'=>array(
               'header'=>"Referer :".$_SERVER['REQUEST_URI']
           )
       );
 
       $context = stream_context_create($opts);//构造HTTP REFERER头   
       $url = "https://passport.no.xxxx.com/verify.php?t=".$ticket;
       $user_id = file_get_contents($url,false,$context);//二次验证,远程请求用户名       
       return $user_id;//返回登录用户名,需进行后续判断是否为空串
   }

在接下来的文章中,我们会进一步讲解如果使用程序模拟登录验证系统,该怎么处理。

Use jpype in python scripts

2011年7月20日 没有评论

JPype is an effort to allow python programs full access to java class libraries. This is achieved not through re-implementing Python, as Jython/JPython has done, but rather through interfacing at the native level in both Virtual Machines.
JPype是一个高效的python库,它允许python程序和java类互通。它并非是一个重新实现的Python,就像Jython和JPython那样,而是通过在虚拟机native层面上实现。
Eventually, it should be possible to replace Java with python in many, though not all, situations. JSP, Servlets, RMI servers and IDE plugins are all good candidates.
实际上,它应该可以在许多的场景下使用python来替换Java,当然了并非所有的都能替换。像 JSP, Servlets, RMI servers and IDE plugins都是很好的替换对象。
—————————————–强行分割一下吧—————————————-
最近学习写一些用来处理日志log的python脚本,但是到连接到线上数据库的时候出现了点小小的麻烦,因为众所周知,renren的代码是java的,连接数据库都被java做了封装,不能显示的看到具体那台数据库【实际上开发者也无需关心,我们只需要一个配置文件,具体指向什么地方,后面是一台机器还是多台,都不在操心。】就想找到一个python能直接访问java程序的解决方案,翻来翻去就找到JPype了,它的源码好久没更新,不过最近更新了一下,最新的版本是0.5.4.1,可以通过这个链接下载
安装很简单,直接直接python setup.py install就可以了(安装过程中显示的warning可以不必理会)。用于测试是否安装成功的Hello World代码如下:

from jpype import *
startJVM(getDefaultJVMPath())
java.lang.System.out.println("hello world")
shutdownJVM()

运行结果如下:

[root@SJSWT45-26 wei]# python testp2j.py
hello world
JVM activity report     :
        classes loaded       : 30
JVM has been shutdown

2.  启动JVM

依靠startJVM这个函数来完成,一个使用的例子是这样的:

vmPath = jpype.getDefaultJVMPath()
jpype.startJVM(vmPath, "-Xms32m", "-Xmx256m", "-mx256m", "-Djava.class.path=/home/some-lib.jar:")

startJVM的第一个参数是JVM库所在的路径(和JAVA_HOME不是一回事儿),通常可以用jpype.getDefaultJVMPath()来自动获取系统默认JVM的路径。如果系统中安装了多个JDK,希望从中选择一个,则可以手动注明这个路径。比如Mac OSX下可以写成“/System/Library/Frameworks/JavaVM.framework/Libraries/libjvm_compat.dylib”

剩下的都是发送给JVM的启动参数,每个逗号见是一个参数。因为这里是不支持带空格的参数写法的,所以例子里特意把classpath参数写成了-Djava.class.path=…的形式。注意这里需要手工保证参数的正确性,jpype是不会对错误的参数给出提示的,它的反应很简单,就是在后面用到这个JVM的时候报一些怎么也想不明白的错误……所以,使用jpype遇到任何问题,首先检查传给startJVM的各参数正确性。

3.  如何调用一个Java函数

主要靠JPackage语句来实现,比如

Document = jpype.JPackage('org').w3c.dom.Document

可以把Java里面的org.w3c.dom.Document映射给Python里面的Document变量。
java和javax两个包不需要以这种方式来调用,直接类似jpype.java.lang.System.out.println()这样就可以了。

有时候我们会遇到类似TypeError: Package org.w3c.dom.Document is not Callable”这样的错误。通常这时用到的Java指令在jar里面,而这个jar没有被正确导入,所以JVM找不到它。也就是说,遇到这种错误时,要去检查startJVM函数中的-Djava.class.path=参数的设置,通常都是因为这里的路径写错了造成的。

4.  如果捕捉Java异常

可以在Python里使用 jpype.JavaException指代所有的Java异常,比如像下面这样:

import jpype
jpype.startJVM(jpype.getDefaultJVMPath())
try:
    jpype.java.lang.Integer("x1")
except jpype.JavaException, ex:
    print ex.javaClass(), ex.message()
    print ex.stacktrace()    
jpype.shutdownJVM()

如果要捕获特定的Java异常呢,则需要用到jpype.JException,比如像下面这样捕获的就是java.lang.NumberFormatException

import jpype
jpype.startJVM(jpype.getDefaultJVMPath())
try:
    jpype.java.lang.Integer("x1")
except jpype.JException(jpype.java.lang.NumberFormatException), ex:
    print ex.javaClass(), ex.message()
    print ex.stacktrace()    
jpype.shutdownJVM()

5.  如何处理Java的函数多态

Java里面是允许参数格式不同的多个同名函数的,Python里面则不允许。这样在通过jpype调用Java api里面的函数时,有时会因为参数的类型乱掉而报错。那么怎么能调用到Java里面的特定函数呢?没办法,做强制类型转换吧。

比如jpype.java.lang.System.out.println(1)实际会调用println(int),那么如果我们想调用println(byte)%,则可以写成jpype.java.lang.System.out.println(JByte(1))这样。。

6.  如何重启JVM

jpype提供的shutdownJVM()方法实际调用的是JNI接口的unload实现,但是Sun对unload的实现有点问题,造成的结果就是jpype调用shutdownJVM()以后就没法再startJVM()了(会报错)。什么?您问关掉JVM干嘛还要重新开启它,这个折腾个什么劲?答案很简单:因为有时在未知的黑暗角落隐藏着邪恶的源头——内存泄露。。

既然jpype没法重启JVM,那么只好把jpype放到processing里面来用,需要重启时,就杀掉当前进 程,重新启动一个新进程好了。。(processing安装很简单,Python 2.6官方发行版已经带了,之前的版本则可以easy_install processing)

下面给出一个processing下用jpype的例子:

import jpype
import processing
 
def java_loop(pipe, id):
    jpype.startJVM(jpype.getDefaultJVMPath())
    while True:
        jpype.java.lang.System.out.println(pipe.recv() + ' ' + id)
        pipe.send(None)
 
head1, head2 = processing.Pipe()
p = processing.Process(target = java_loop, args = [head2, '(JVM 1)'])
p.setDaemon(True)
p.start()
head1.send("Hello message from")
head1.recv()
p.terminate()
 
head1, head2 = processing.Pipe()
p = processing.Process(target = java_loop, args = [head2, '(JVM 2)'])
p.setDaemon(True)
p.start()
head1.send("Hello message from")
head1.recv()

这里用到的pipe.recv()要小心,一旦阻塞可能会与twisted之类的框架产生冲突。一个可能的解决办法是在recv()之前用pipe.poll()函数检测一下管道里面是否有待接收数据,如果没有就等一会重新poll()就是了。[poll()自称是非阻塞的,因为它只阻塞当前线程;而recv()则会阻塞当前进程,于是twisted就不干了]

很茫然也很兴奋

2010年10月29日 没有评论

写代码时间久了,总是感觉接触面越来越窄,到现在估计只剩下Java还能写点东西了,PHP算作业余时间搞的,好在是弱语言类型的,每次都是现学现卖。一口气写下来,在本地debug也快,出现错误就地改正就是了,尝试过用框架,结果都是半途而废了,估计水平也就这样子了,自己搞点小玩意儿还是可以的,帮朋友做几个个人网站也行。
近半年来,总算是有点目标,学习还是马马虎虎的,最近公司的事情好多啊,只能见缝插针的学习点,感觉提高的也不快,任何事情总得动手才行。
淘宝客的一堆东西基本上快研究透彻了,想到了几个点子,准备抽时间给实现了。
剩下的学习任务很很重,搞下PHPRPC,丢掉的C++想尽可能的给捡回来,搞好英语。

分类: 技术收集 标签: , , ,

学习memcached的安装和java通讯

2010年9月30日 1 条评论

memcache需要libevent进行网络的通讯才能正常工作,所以安装memcache之前需要首先安装libevent. libevent可以从这儿下载,memcache需要从google code下载。
现在万事具备,开始安装的基本过程,如下所示:

#yum install gcc  //确认gcc已经安装,可以gcc -v确认

#wget http://monkey.org/~provos/libevent-1.4.5-stable.tar.gz  //下载最新的稳定版本
#tar xvzf libevent-1.4.4-stable.tar.gz  //解压缩
#cd libevent-1.4.4-stable 
#./configure -prefix=/usr/local/libevent //开始编译
#make
#make install

接着安装memcache.

#cd /home/mysoft/
#tar -zxvf  memcached-1.4.5.tar.gz
#cd  memcached-1.5.0
#./configure --prefix=/usr/local/memcached --with-libevent=/usr/
#make #make install
#ls -al /usr/local/memcached/bin //验证安装

如果没有问题,现在就可以正常启动memcached了,命令如下:

/usr/local/memcached/bin/memcached -d -m 100 -u root -l 192.168.1.101 -p 11211 -c 256 -P /tmp/memcached.pid

-d选项是启动一个守护进程,
-m是分配给Memcache使用的内存数量,单位是MB,我这里是100MB,
-u是运行Memcache的用户,我这里是root,
-l是监听的服务器IP地址,如果有多个地址的话,我这里指定了服务器的IP地址192.168.1.100,
-p是设置Memcache监听的端口,我这里设置了11211,最好是1024以上的端口,我们这里统一使用11211-c选项是最大运行的并发连接数,默认是1024,我这里设置了256,按照自己服务器的负载量来设定。
-P是设置保存Memcache的pid文件,我这里是保存在/tmp/memcached.pid
常见的启动失败信息有:
AA.启动时找不到libevent库
memcached: error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory

解决办法1:将libevent库所在路径加入LIBRARY_PATH,在/etc/profile中加入
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/libevent/lib

解决办法2:
ln -s /libevent安装路径/libevent/lib/libevent-1.3b.so.1 /usr/lib/libevent-1.3c.so.1
详细的处理过程如下:
>locate libevent-1.4.so.2
libevent-1.4.so: /usr/local/lib/libevent-1.4.so.2

> ldd /usr/local/bin/memcached
linux-gate.so.1 => (0xb7fa4000)
libevent-1.4.so.2 => not found
libpthread.so.0 => /lib/libpthread.so.0 (0x0086e000)
libc.so.6 => /lib/libc.so.6 (0x006f7000)
/lib/ld-linux.so.2 (0x006d9000)

> LD_DEBUG=libs ./memcached -v
找到默认路径 /usr/lib/
>ln -s /usr/local/lib/libevent-1.4.so.2 /usr/lib/libevent-1.4.so.2

>ldd /usr/local/bin/memcached
linux-gate.so.1 => (0xb7ffd000)
libevent-1.4.so.2 => /usr/lib/libevent-1.4.so.2 (0xb7fdc000)
libpthread.so.0 => /lib/libpthread.so.0 (0x0086e000)
libc.so.6 => /lib/libc.so.6 (0x006f7000)
libnsl.so.1 => /lib/libnsl.so.1 (0x009f8000)
librt.so.1 => /lib/librt.so.1 (0×00887000)
libresolv.so.2 => /lib/libresolv.so.2 (0x00b29000)
/lib/ld-linux.so.2 (0x006d9000)
收工
AB.第二个可能的问题是编译memcache期间出现的,解决方案可以参考这儿
或者 在./configure 时加入参数–build=i686-pc-linux-gnu
AC.如果客户端连接不上,可能是服务器防火墙的原因,选择关闭或者增加相应的iptables文件如下:
#永久性生效,重启后不会复原
开启: chkconfig iptables on
关闭: chkconfig iptables off
#即时生效,重启后复原
开启: service iptables start
关闭: service iptables stop
#修改/etc/sysconfig/iptables文件,
添加-A RH-Firewall-1-INPUT -m state –state NEW -m tcp -p tcp –dport 11211 -j ACCEPT

使用的方式可以有很多种,常见的语言api通过官方网站都能找到,比如php的参考这儿,需要memcached插件
Java的可以选择这个spymemcached或者java memcached,其他语言的可以从这个列表中查找。

commons lang组件之自动生成toString()内容

2009年10月30日 5 条评论

问题

希望能自动生成toString()方法

解决方案

使用Commons Lang的ReflectionToStringBuilder或ToStringBuiler,配合ToStringBuilder可生成toString()方法
.下面的代码显示了如何使用反射生成器(reflection builder)生成toString()方法.

import org.apache.commons.lang.builder.ReflectionToStringBuilder;

public String toString(){
return ReflectionToStringBuilder.toString(this);
}

让toString()的内容与不断变化的类保持一致,是一项让人心烦又容易遗忘的工作.Commons Lang带有一个非常易用的工具类,
通过反射自动完成这件麻烦事.ToStringBuilder类及其派生类ReflectionToStringBuilder能把原本臃肿的toString()方法
浓缩成一行.更重要的是ReflectionToStringBuilder反映了对象模型未来的变化趋势.

在有限的时间和预算条件下,面对含有上百个实体的对象模型,要保证toString()方法能实时更新几乎就是天方夜谭.如果你的类
拥有含义明确的toString()方法,在诊断程序时将会受益非浅.通过使用ReflectionToStringBuilder类,能确保输出是正确的.
依靠开发者手动维护toString()方法会很不可靠.

分类: 杂七杂八 标签: ,

native2ascii工具使用

2009年10月14日 1 条评论

在做Java开发的时候,常常会出现一些乱码,或者无法正确识别或读取的文件,比如常见的validator验证用的消息资源(properties)文件就需要进行Unicode重新编码。原因是java默认的编码方式为Unicode,而我们的计算机系统编码常常是GBK等编码。需要将系统的编码转换为 java正确识别的编码问题就解决了。

1、native2ascii简介:
native2ascii是sun java sdk提供的一个工具。用来将别的文本类文件(比如*.txt,*.ini,*.properties,*.java等等)编码转为Unicode编码。为什么要进行转码,原因在于程序的国际化。Unicode编码的定义:Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。随着计算机工作能力的增强,Unicode也在面世以来的十多年里得到普及。
2、获取native2ascii:
安装了jdk后,假如你是在windows上安装,那么在jdk的安装目录下,会有一个bin目录,其中native2ascii.exe正是。

3、native2ascii的命令行的命名格式:
native2ascii -[options] [inputfile [outputfile]]

说明:
-[options]:表示命令开关,有两个选项可供选择
-reverse:将Unicode编码转为本地或者指定编码,不指定编码情况下,将转为本地编码。
-encoding encoding_name:转换为指定编码,encoding_name为编码名称。

[inputfile [outputfile]]
inputfile:表示输入文件全名。
outputfile:输出文件名。如果缺少此参数,将输出到控制台。

4、最佳实践: 阅读全文…

分类: 技术收集 标签: ,

漫谈一下网站的转化率与注册

2008年8月5日 没有评论

用户转化率,可以说是任何一个信息填写类网站的灵魂,这儿的信息可以是用户由访客变成真实用户,也可以是一些增值类业务用户手机号码验证码确认码的输入,等等的。面对同一个产品,一个精心设计的网站,1000个IP可能会带来10个有效的转换,而不注重转换率的页面,1000个IP可能产生不了一个有效用户。

1、做到真正以客户为中心的网站设计,产品、美工、技术等不能代表客户,当一个站点页面,一个业务流程设计好以后,有条件的话,最好的方法,是选择针对性的客户进行试用并提出意见:自己的观点,只代表你自己的认识,并不能代表客户的感受。如果做不到这点,就要用数据来说话,通过把不同风格,甚至文字提示信息的修改,都要测试一段时间,用数据来做对比,然后慢慢调优,这种改动不易过大,整版风格的改变,一般情况下对用户的转化率没有多大的帮助,而且数据的返回结果往往会对业务人员产生错误的指导方向。一个不错的创意,可能就因为一点的瑕疵,而被抛弃,这种应该尽可能的避免。

2、用户的体验。个人感觉用户的体验是最最重要的,在没有十足把握的情况下,不要修改网站既有的体验流程。要考虑到老用户的使用感受。一个很明显的例子,就是本来很早的时候我是用msn来写日记的,但是自从某次改版之后,变得十分的“恶心”,偌大的广告,巨慢无比的页面载入速度,结果可想而之,就是我另寻它山了。这种情况下,建议搞一种新版和旧版可以来回切换的功能比较好,习惯了老格局,老模式的用户可以继续使用。新用户可以引导着使用新的流程。对于内容提供方来说,最起码的就要保证页面在主流浏览器,主流分辨率下页面布局效果都要保持一致。实际上,就是IE(70%+) 和 Firefox(20%),其中ie中主要是ie7(45%)和ie6(25%),这部分主要由切页面的美工来保证效果,技术人员一般是不会去顾及的,笔者有两台机器,恰好一个是ie7,一个是用ie6,在做的几个页面中发现或多或少的都会有表格,文本域对不齐的情况发生。

3、现在来看下用户注册过程中的三个困扰:

a, 用户不知道给了你他们的个人信息,换回来什么好处 [注册后,输入邮箱密码导入用户]
b, 信息受挑战,要求填写太少,太多或不正确的信息
c,用户还没有建立信任,更不知道注册后会有什么的预期效果

个人之见,在需要用户转化的着陆页中,减少用户可选择点击的选项,减少用户对内容选择作决定,尽量减化流程。如果确实需要提供第二个选项,可将它放在网页的下端位置,防止用户从注册界面中分散注意力,因此通过减少干扰选项来提高网站的转化率。 但是,光秃秃的业务转化流程,显然效果也好不到哪儿去。用户在注册时,应该能看到我注册能干嘛,我为啥要输入详细的个人资料。这是一个冲突,这中间的,文字图片,应该摆放多少,摆放在哪儿?应该还是靠上面1的数据来说了算比较好,呵呵。