Archive for the 'Java' Category

算法:关于二进制

Jul 08 2010 Published by Tony under Java,Other

package test;
 
public class BitAdd {
 
	/**
	 * 算法,给定一个二进制数n中1所在的位置,求3*n的二进制表达式中1的所在位置
	 * 例如 50 的二进制位110010 那么这个二进制数1的位置为{1,4,5},50*3=150 求150的二进制数的1所在位置 
	 * 先利用2*n等于n左移以为,计算出2*n,再2*n+n 得出解,解最终打印出来了。关键步骤就是二进制加法。
 
	 */
	public static void main(String[] args) {
		int[] A={1,4,5};
		int[] B={2,3,4,5};
		Bit3Times(A);
		System.out.println("");
		Bit3Times(B);
 
	}
	public static void Bit3Times(int[] A){
		int[] B=new int[A.length];
		int[] C=new int[A.length+1];
		for(int i=0;i<A.length;i++){
			B[i]=A[i]+1;
			C[i]=A[i];
		}
 
		for(int i=0;i<C.length;i++){
			if(i<B.length){
				for(int j=0;j<B.length;j++){
					if(C[i]==B[j]){
						C[i]=C[i]+1;
						break;
					}else if(B[j]<C[i+1]&&B[j]>C[i]){
						C[B.length+i]=B[j];
					}
				}
			}
		}
		if(C[B.length-1]==B[B.length-1]){
			C[B.length-1]++;
		}
		int num=0;
		for(int i=0;i<C.length;i++){
			if(C[i]>0) num++;
			System.out.printf("%s,", C[i]);
		}
	}
 
}

No responses yet

Hibernte 1:n 最佳抓取策略

Mar 10 2010 Published by Tony under Java

Hibernte 1:n 最佳抓取策略
在orm中实体1:n关联时,要考虑两个问题,分别是经典的n+1问题,和笛卡尔积问题。所以要避免使用默认抓取策略,同时尽量减少结果。hibernate作为最主流的java orm。一般的的优化原则是使用batchsize减少子查询的sql数量,同时在one一端使用懒加载,并且用subselect或者join来代替默认的关联加载。
上代码:

@Entity
@BatchSize(size=10)//因为一般要获得post,都会调用creator,所以使用预抓(EAGER)策略,同事设置预抓持为10
public class User extends BaseEntity{
@Id @GeneratedValue
@Column(name="id")
private long id;
@OneToMany(mappedBy="creator",fetch=FetchType.LAZY)//懒加载
@Fetch(FetchMode.SUBSELECT)//使用JOIN会产生笛卡尔积的问题,subselect策略是Hibernate.org推荐的解决N+1问题策略
private Set posts=new HashSet();
......
}
@Entity
public class Post extends BaseEntity {
@Id @GeneratedValue
@Column(name="id")
private long id;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(nullable=false)
private User creator;
....
}

No responses yet

用perl脚本解决ant…非法字符:\65279…的问题

Feb 21 2010 Published by Tony under Java,Perl

用perl脚本解决ant…非法字符:\65279…的问题


用ant管理项目,编译时发现有些utf8编码的java文件无法编译,
报错是…非法字符:\65279…。

在网上查N多与ant有关的文章,但是大多数的解决方案都不是很理想。因为文件比较多,而且我的
机器上也没有装editplus。
索性自己用perl写了一个脚本
如下:

#remove the utf-8  BOM for Ant
sub remove_bom {
	#open( my $in, "+<", "src/com/umpay/wap20/mobileProxy/MobileProxy.java" );
	foreach my $filename (@_) {
		print $filename,"\n";
		open( my $in, "+<", $filename );
		@lines = <$in>;
		$line1 = $lines[0];
		$t_chk1 = substr( $line1, 0, 1 );    #0xef -> 239
		$t_chk2 = substr( $line1, 1, 1 );    #0xbb -> 187
		$t_chk3 = substr( $line1, 2, 1 );    #0xbf ->191
		if ( ord($t_chk1) == 239 && ord($t_chk2) == 187 && ord($t_chk3) == 191 )
		{
			$line1 = substr( $line1, 3 );
			seek( $in, 0, 0 );
			print $in $line1;
		}
		close $in;
	}
}
&remove_bom("src/com/umpay/wap20/mobileProxy/MobileProxy.java"
,"src/com/umpay/wap20/security/GeneralKeyPairs.java"
,"src/com/umpay/wap20/security/RSAUtil.java"
,"src/com/umpay/wap/pages/WML.java");

其中remove_bom方法就是处理有问题的文件的方法。
把你的项目中出现问题的文件名称一个一个的放到remove_bom的参数列表中就可以了。ant,BOM,ant,BOM
最后运行这个perl文件。之后再运行ant就可以了。

No responses yet

SIP Servlet入门教程及例子

Feb 19 2010 Published by Tony under Java

作为一个SIP Servlet Tutorial,这个文档主要描述了在JavaEE平台下如何开发基于SIP协议的应用服务。当然这个教程也包含了如何将JavaEE技术与SIP应用程序集成。
这个教程主要涉及到的软件有:
1. JavaSE 5.0
2. Glassfish and Sailfin(这是目前为止,我知道的唯一的一个开源的java sip servlet 容器)
3. Netbeans IDE(主要是在sailfin的安装包中有Netbeans的插件,所以使用NB)
4. X-Lite Soft Phone 或者MyFreesipphone
5. Apache Ant
这里就不多介绍SIP协议了,直接进入主题。
熟悉web开发的人基本都知道Http request 和 http Response 两个对象。
对应的,SIP也有对应的对象。
SIP Request
常见SIP Request Action

  • INVITE 请求初始化一个session
  • ACK 回应INVITE请求,是(acknowledges的简写)
  • BYE 请求关闭连接
  • CANCEL 取消所有未处理的action,但是不释放连接
  • REGISTER 向服务器注册一个地址,或者说,客户端向服务器发送一个注册请求


  • 什么是SIP Servlets?
    SIP Servlet 是一个 基于Java 语言的 server-side 组件,就类似于Java Servlet 一样,只不过SIP Servlet 需要运行在 SIP Servlet 容器中。
    而且SIP Servlet主要用来处理SIP请求,而Servlet用来处理HTTP请求。
    HTTP Servlet 与 SIP Servlet的不同之处:
    1. HTTP Servlet 都会有一个context对象,也就是每个Servlet都有一个上下文的概念。而SIP Servlet没有。
    2. HTTP Servlet 通常会返回一个HTML 页面或者某种形式的字符串(比如JSON),而SIP请求通常只是起到连接服务器与客户端的作用。
    3. SIP 是一个P2P的协议,所以服务器端同样可以向客户端发送SIP请求。
    4. SIP Servlet通常只是扮演一个代理的角色,最终的请求(客户端的请求)会发送到另一个已注册的SIP客户端。而HTTP Servlet会返回给客户端一个HTTP response。
    5. SIP协议类似于长连接,但是一个无状态的链接,所以它可以返回个客户端多个相互独立的response,而HTTP是一个无状态的协议,一个Request对一个Response。
    6. SIP 请求可以是一个异步的请求。这一点取决于上一个特性。
    关于SIP Servlet的annotation。
    Annotation 描述
    @SipServlet 标示这是一个SIP Servlet
    @SipListener 标示这个一个Sip Listener
    @SipApplication 用来定义一组SIP Servlets
    @SipApplicationKey 为一个SIP请求或者一个SIP session分配一个SipApplicationSession
    比如:

    @SipServlet
    public class MyServlet extends SipServlet{}

    @SipApplication 这个注释一般都用在包上。
    比如

    @SipApplication(name=”MySipApp”)
    Package com.example.sip;

    而@SipApplicationKey这个注释需要使用在方法上,而且这个方法需要满足以下条件:
    1. Public method
    2. Static method
    3. Return a String
    4. 方法的参数必须是SipServletRequest 类型
    5. 传入的参数不可变
    例如:

    @SipApplication(name=”MySipApp”)
    Package com.example.sip;
     public class MySipApp{
    	@SipApplicationKey
    	public static String sessionKey(SipServletRequest request){
    		Return hash(request.getRequestURI()+getDomain(request.getForm()));
           }
    }

    在一个Sip application中只能有一个SipApplicationKey。
    SIP Factory
    SIP Factory 是一个Servlet Factory,也就是说所有的SIP请求进入SIP容器后,都要通过SIP Factory来创建一个Servlet实例。所以SIP Factory是整个SIP容器的入口。如果想调用容器中的其他资源,可以通过SIP Factory来调用。而调用的方法包括依赖注入和”查找”两种方式。
    看例子:

    //通过注释来调用
    @Resource
    SipFactory sf;
    //通过查找的方式
    SipFactory sf=(SipFactory)getServletContext().getAttribute(“javax.servlet.sip.SipFactory);

    SIP Session
    SIP协议是一个无状态协议,所以一个response只能对应一个request(虽然一个request可以对应多个response)。也就是说多个request之间无法共享数据。
    但是SIP Session提供了一种比较便捷的方式,用来存储request之间的共享数据。而这种方式非常类似于HTTP servlet中的Session对象。
    但是与HTTP Session不同的是,在SIP应用中还有一个SIP ApplicationSession对象,这个东西很强大,它可以关于整个应用的session信息。
    除此之外,还有个SipSessionUtil可以使用。使用方法和SIP Factory类似:

    @Resource
    SipSessionUtil sessionUtil;
    //或者
    SipSessionUtil sessionUtil=(SipSessionUtil)getServletContext().getAttribute(“javax.servlet.sip.SipSessionUtil);

    SIP Listeners
    SIP application Listeners 就是用来监听SIP相关事件的Java Servlet listeners。它需要实现SIPServletListener接口。同时在其类上标注上Annotation用于简化部署。
    比如:

    @SipListener
    Public class MyListener implements SipServletListener{
    …..
    }

    Back-to-Back User Agent Applications
    一个back-to-back user agent(B2BUA)本身就是一个应用程序,同时它还是一个工具,很类似于代理。用于将一个客户端请求,转发给另一个客户端。而javax.servlet.sip.B2buaHelper就是一个实现这种功能的帮助类。

    以上内容翻译自SUN的SIP Servlet Tutorial文档。
    下面是我自己写的一个简单的sip程序。

    package com.ohacker.sip.proxy;
    import java.io.IOException;
    import java.util.ArrayList;
    import javax.servlet.ServletException;
    import javax.servlet.sip.*;
    import javax.servlet.sip.Address;
    /**
     *
     * @author O!Hacker
     */
    @javax.servlet.sip.annotation.SipServlet
    public class RegistratorServlet extends javax.servlet.sip.SipServlet {
       public static ArrayList<Address> CLIENT_LIST=new ArrayList<Address>();
     
        @Override
        protected void doInvite(SipServletRequest req) throws ServletException, IOException {
            System.err.println("doInvite action: "+ req.getCallId());
            Proxy proxy=req.getProxy();
            System.err.println(req.getTo().getURI().toString());
            proxy.proxyTo(req.getTo().getURI());
        }
     
        @Override
        protected void doRegister(SipServletRequest req) throws ServletException, IOException {
            System.err.println("doRegister action: "+ req.getCallId());
            System.err.println("doRegister action: "+ req.getRequestURI());
            SipServletResponse resp=null;
            Address address=req.getTo();
            if(!RegistratorServlet.CLIENT_LIST.contains(address)){
                CLIENT_LIST.add(address);
            }
            System.err.println(CLIENT_LIST.size());
            resp=req.createResponse(SipServletResponse.SC_OK);
            resp.send();
        }
    }

    No responses yet

    Ant 小记

    Feb 19 2010 Published by Tony under Java

    Ant 小记
    传统的ant 打包的项目需要处理文件和路径。特别是烦人的classpath。Ant内置了很多处理文件和路径的数据类型。比如fileset和path
    Fileset可以枚举文件。
    比如:

    <fileset id=”source.fileset” dir=”src” includes=”**/*.java”/>

    其中id是一个引用。其他的操作,可以通过id引用的方式调用它。比如:

    <copy todir=”backup”>
    	<fileset refid=”source.fileset”/>
    </copy>

    javac
    Debugging info
    Javac中常用到的选项
    Debug=”true” or debug=”false” debu=”true” debuglevel=”lines,vars,source”
    Nowarn=”true” verbose=”true” verbose是一个有意思的选项,它会在编译的时候打印出一些编译信息。当然还有classpath。
    比如:

    <javac destdir="${build.classes.dir}" debug="true" verbose="true" srcdir="src">
    			<classpath refid="compile.classpath"/>
    </javac>

    Src也可以用子元素来表示
    比如:

    <javac destdir="${build.classes.dir}" debug="true" verbose="true">
    	<classpath refid="compile.classpath"/>
    	<src path=”src”/>
    </javac>

    如果源文件分散在多个目录中可以使用引用的方式
    比如:

           <path id="src.dir">
    		<pathelement path="src:conf"/>
    	</path>
    	<target name="mkdir">
    		<mkdir dir="${build.classes.dir}"/>
    	</target>
    	<target name="compile" depends="mkdir">
    		<javac destdir="${build.classes.dir}">
    			<classpath refid="compile.classpath"/>
    			<src refid="src.dir"/>
    		</javac>
    	</target>

    还有一种方法,比较土
    例子:

    <javac destdir="${build.classes.dir}">
    			<classpath refid="compile.classpath"/>
    			<src refid="src.dir"/>
    			<src path=”test”/>
    		</javac>

    但是需要注意的是src指的是一个目录。

    在path或者fileset这类标签中常常会遇到类似以”**/*.jsp”这样的匹配模式。下面就讲讲在如何匹配。这种匹配方式好像应该叫做wildcard路径匹配方式。是目前比较常见的3中路径匹配风格之一,(题外话,另两种是mod_rewrite风格和perl 正则风格的路径匹配)

  • “*”表示一个或多个字符
  • “?”表示一个字符
  • “**”表示零个或者多个目录
  • 如果以”/”or”\”结尾,那么就相当于”**”
  • 常见例子:
    **/*~ linux 下的备份文件
    **/CVS/ cvs元文件
    **/.cvsignore cvs文件
    **/.svn/ SVN元文件目录
    比如在javac中的使用

    <javac srcdir=”src” destdir=”build/classes”>
    	<include name=”org/mama/**/*.java”/>
    	<exclude name=”org/mama/papa/*.java”/>
    </javac>

    下面是一个完整的java 项目的build文件

    <?xml version="1.0"?>
    <project name="java_project" default="archive">
    	<property file="build.properties"/>
     
    	<path id="compile.classpath">
    		<pathelement location="lib/*.jar"/>
    	</path>
    	<path id="src.dir">
    		<pathelement path="src/java"/>
    		<pathelement path="src/conf"/>
    	</path>
    	<target name="init">
    		<mkdir dir="${build.classes.dir}"/>
    		<mkdir dir="dist"/>
    	</target>
    	<target name="compile" depends="init">
     
    		<javac destdir="${build.classes.dir}">
    			<classpath refid="compile.classpath"/>
    			<src refid="src.dir"/>
    		</javac>
    	</target>
    	<target name="archive" depends="compile">
    		<jar destfile="dist/${project.name}.jar" basedir="build/classes"/>
    	</target>
    	<target name="clear" depends="init">
    		<delete dir="build"/>
    		<delete dir="dist"/>
    	</target>
    </project>

    对应的build.properties文件也很简单
    project.name=default
    build.classes.dir=build/classes

    No responses yet

    Glassfish sip server(sailfin) install 安装glassfish sip server

    Feb 09 2010 Published by Tony under Java

    Glassfish sip server(sailfin) install 安装glassfish sip server
    第一步:安装JDK,Ant

    第二步:下载sailfin:下载地址

    第三步:如果你的机器上正跑着glassfish,先关掉。在你的下载目录下运行:

    >java -Xmx256m -jar filename.jar

    等解压完后,再运行

    >cd sailfin
    >ant -f setup.xml

    第四步:之后将生成的目录加进环境变量中的Path下。

    第五步:在环境变量中加入AS_ADMIN_USER 值为admin

    第六步:从新开一个cmd console,运行

    asadmin start-domain domain1



    第六步:在浏览器中打开http://localhost:4848/

    第七步:输入admin/adminadmin
    大功告成

    No responses yet

    Next »