和风细雨

世上本无难事,心以为难,斯乃真难。苟不存一难之见于心,则运用之术自出。

#

C/S架构和B/S架构的概念和区别

C/S 架构

C/S 架构是一种典型的两层架构,其全程是Client/Server,即客户端服务器端架构,其客户端包含一个或多个在用户的电脑上运行的程序,而服务器端有两种,一种是数据库服务器端,客户端通过数据库连接访问服务器端的数据;另一种是Socket服务器端,服务器端的程序通过Socket与客户端的程序通信。
C/S 架构也可以看做是胖客户端架构。因为客户端需要实现绝大多数的业务逻辑和界面展示。这种架构中,作为客户端的部分需要承受很大的压力,因为显示逻辑和事务处理都包含在其中,通过与数据库的交互(通常是SQL或存储过程的实现)来达到持久化数据,以此满足实际项目的需要。

C/S 架构的优缺点

优点:
1.C/S架构的界面和操作可以很丰富。
2.安全性能可以很容易保证,实现多层认证也不难。
3.由于只有一层交互,因此响应速度较快。

缺点:
1.适用面窄,通常用于局域网中。
2.用户群固定。由于程序需要安装才可使用,因此不适合面向一些不可知的用户。
3.维护成本高,发生一次升级,则所有客户端的程序都需要改变。

B/S架构

B/S架构的全称为Browser/Server,即浏览器/服务器结构。Browser指的是Web浏览器,极少数事务逻辑在前端实现,但主要事务逻辑在服务器端实现,Browser客户端,WebApp服务器端和DB端构成所谓的三层架构。B/S架构的系统无须特别安装,只有Web浏览器即可。
B/S架构中,显示逻辑交给了Web浏览器,事务处理逻辑在放在了WebApp上,这样就避免了庞大的胖客户端,减少了客户端的压力。因为客户端包含的逻辑很少,因此也被成为瘦客户端。

B/S架构的优缺点

优点:
1)客户端无需安装,有Web浏览器即可。
2)BS架构可以直接放在广域网上,通过一定的权限控制实现多客户访问的目的,交互性较强。
3)BS架构无需升级多个客户端,升级服务器即可。

缺点:
1)在跨浏览器上,BS架构不尽如人意。
2)表现要达到CS程序的程度需要花费不少精力。
3)在速度和安全性上需要花费巨大的设计成本,这是BS架构的最大问题。
4)客户端服务器端的交互是请求-响应模式,通常需要刷新页面,这并不是客户乐意看到的。(在Ajax风行后此问题得到了一定程度的缓解)

posted @ 2008-04-29 15:13 和风细雨 阅读(96077) | 评论 (12)编辑 收藏

特殊的String

 

String的特殊之处

String是Java编程中很常见的一个类,这个类的实例是不可变的(immutable ).为了提高效率,JVM内部对其操作进行了一些特殊处理,本文就旨在于帮助大家辨析这些特殊的地方.
在进入正文之前,你需要澄清这些概念:
1) 堆与栈
2) 相同与相等,==与equals
3) =的真实意义.

栈与堆

1. 栈(stack)与堆(heap)都是Java用来在内存中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。每个函数都有自己的栈,而一个程序只有一个堆.
2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,详见第3点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。 3. Java中的数据类型有两种。   一种是基本类型(primitive types), 共有8种,即int, short, long, byte, float, double, boolean, char(注意,并没有string的基本类型)。这种类型的定义是通过诸如int a = 3; long b = 255L;的形式来定义的,称为自动变量。值得注意的是,自动变量存的是字面值,不是类的实例,即不是类的引用,这里并没有类的存在。如int a = 3; 这里的a是一个指向int类型的引用,指向3这个字面值。这些字面值的数据,由于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了),出于追求速度的原因,就存在于栈中。   另外,栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义   int a = 3;    int b = 3;   编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。   特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完a与 b的值后,再令a=4;那么,b不会等于4,还是等于3。在编译器内部,遇到a=4;时,它就会重新搜索栈中是否有4的字面值,如果没有,重新开辟地址存放4的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。   另一种是包装类数据,如Integer, String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中,Java用new()语句来显示地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间。

相同与相等,==与equals

在Java中,相同指的是两个变量指向的地址相同,地址相同的变量自然值相同;而相等是指两个变量值相等,地址可以不同.
相同的比较使用==,而相等的比较使用equals.
对于字符串变量的值比较来说,我们一定要使用equals而不是==.

=的真实意义

=即赋值操作,这里没有问题,关键是这个值有时是真正的值,有的是地址,具体来说会根据等号右边的部分而变化.
如果是基本类型(八种),则赋值传递的是确定的值,即把右边变量的值传递给左边的变量.
如果是类类型,则赋值传递的是变量的地址,即把等号左边的变量地址指向等号右边的变量地址.

指出下列代码的输出

String andy="andy";
String bill="andy";

if(andy==bill){
  System.out.println("andy和bill地址相同");
}
else{
  System.out.println("andy和bill地址不同");
}

String str=“andy”的机制分析

上页代码的输出是andy和bill地址相同.
当通过String str=“andy”;的方式定义一个字符串时,JVM先在栈中寻找是否有值为“andy”的字符串,如果有则将str指向栈中原有字符串的地址;如果没有则创建一个,再将str的地址指向它. String andy=“andy”这句代码走的是第二步,而String bill=“andy”走的是第一步,因此andy和bill指向了同一地址,故而andy==bill,andy和bill地址相等,所以输出是andy和bill地址相同.
这样做能节省空间—少创建一个字符串;也能节省时间—定向总比创建要省时.

指出下列代码的输出

String andy="andy";
String bill="andy";
bill="bill";

if(andy==bill){
  System.out.println("andy和bill地址相同");
}
else{
  System.out.println("andy和bill地址不同");
}

输出及解释

上页代码的输出是:andy和bill地址不同
当执行bill=“bill”一句时,外界看来好像是给bill变换了一个新值bill,但JVM的内部操作是把栈变量bill的地址重新指向了栈中一块值为bill的新地址,这是因为字符串的值是不可变的,要换值(赋值操作)只有将变量地址重新转向. 这样andy和bill的地址在执行bill=“bill”一句后就不一样了,因此输出是andy和bill地址不同.

指出下列代码的输出

String andy=new String("andy");
String bill=new String("andy");

// 地址比较
if(andy==bill){
  System.out.println("andy和bill地址相同");
}
else{
  System.out.println("andy和bill地址不同");
}

// 值比较
if(andy.equals(bill)){
  System.out.println("andy和bill值相等");
}
else{
  System.out.println("andy和bill值不等");
}

输出及机制分析

andy和bill地址不同
andy和bill值相等
我们知道new操作新建出来的变量一定处于堆中,字符串也是一样.
只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即每个字符串都有自己的值,自然地址就不会相同.因此输出了andy和bill地址不同.
equals操作比较的是值而不是地址,地址不同的变量值可能相同,因此输出了andy和bill值相等.

指出下列代码的输出

String andy=new String("andy");
String bill=new String(andy);

// 地址比较
if(andy==bill){
  System.out.println("andy和bill地址相同");
}
else{
  System.out.println("andy和bill地址不同");
}

// 值比较
if(andy.equals(bill)){
  System.out.println("andy和bill值相等");
}
else{
  System.out.println("andy和bill值不等");
}


输出

andy和bill地址不同
andy和bill值相等

道理仍和第八页相同.只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即每个字符串都有自己的值,自然地址就不会相同.

指出下列代码的输出

String andy="andy";
String bill=new String(“Bill");
bill=andy;

// 地址比较
if(andy==bill){
  System.out.println("andy和bill地址相同");
}
else{
  System.out.println("andy和bill地址不同");
}

// 值比较
if(andy.equals(bill)){
  System.out.println("andy和bill值相等");
}
else{
  System.out.println("andy和bill值不等");
}


输出及解析

andy和bill地址相同
andy和bill值相等
String bill=new String(“Bill”)一句在栈中创建变量bill,指向堆中创建的”Bill”,这时andy和bill地址和值都不相同;而执行bill=andy;一句后,栈中变量bill的地址就指向了andy,这时bill和andy的地址和值都相同了.而堆中的”Bill”则没有指向它的指针,此后这块内存将等待被垃圾收集.


指出下列代码的输出

String andy="andy";
String bill=new String("bill");
andy=bill;

// 地址比较
if(andy==bill){
  System.out.println("andy和bill地址相同");
}
else{
  System.out.println("andy和bill地址不同");
}

// 值比较
if(andy.equals(bill)){
  System.out.println("andy和bill值相等");
}
else{
  System.out.println("andy和bill值不等");
}

输出

andy和bill地址相同
andy和bill值相等

道理同第十二页

结论

使用诸如String str = “abc”;的语句在栈中创建字符串时时,str指向的字符串不一定会被创建!唯一可以肯定的是,引用str本身被创建了。至于这个引用到底是否指向了一个新的对象,必须根据上下文来考虑,如果栈中已有这个字符串则str指向它,否则创建一个再指向新创建出来的字符串. 清醒地认识到这一点对排除程序中难以发现的bug是很有帮助的。
使用String str = “abc”;的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String(“abc”);的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。
如果使用new()来新建字符串的,都会在堆中创建字符串,而且其字符串是单独存值的,即每个字符串都有自己的值,且其地址绝不会相同
当比较包装类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==。
由于String类的immutable性质,当String变量需要经常变换其值如SQL语句拼接,HTML文本输出时,应该考虑使用StringBuffer类,以提高程序效率。

posted @ 2008-04-29 15:10 和风细雨 阅读(390) | 评论 (0)编辑 收藏

[转载]Web2.0-个人品牌打造指南

     摘要: 序言:本指南旨在帮助你建立全面的个人品牌战略。个人品牌的建立是你销售自己从而在商业上取得成功的重要一环。个人品牌的建立是一个持续的过程正如你不断认识自己的过程。你自己强大了,品牌也亦然。在全球化导致工作竞争加剧的今天,个人品牌的提升也显得尤为重要。正如像金子那样发光,你能在人群中崭露自己,就能步入精英的行列。如今这场角力将比你的预想更为激烈和艰难。

或许是David Samuel这个家伙把我带进个人品牌研究这一行的,几年前我看了他的报告。他在报告中说了我们为什么需要个人品牌。当时他的听众来自一个电信大公司:

“如果我们根据人的智力把他们划分三六九等,那么他们就是一群A,一群B,一群C和一群D。因为全球化趋势,C群和D群的工作已经被外包了。一切已经过去了。至于留下的你们,现在就要为跻身A群和B群而开始竞争。或许在这个人才济济的群体中,你会想用大声嚷嚷来取得关注了。如何才能让自己受到关注?你该如何让自己发光以证明自己可以获得额外的工作机会?你该如何从身边每个人都像你一样能干甚至更甚于你的环境中胜出?如果你身边的每个人都是很能干的A群B群,你又该如何与他  阅读全文

posted @ 2008-03-31 11:55 和风细雨 阅读(198) | 评论 (0)编辑 收藏

全排列算法示例

package com.sitinspring;

/**
 * 全排列算法示例
如果用P表示n个元素的排列,而Pi表示不包含元素i的排列,(i)Pi表示在排列Pi前加上前缀i的排列,那么,n个元素的排列可递归定义为:
如果n=1,则排列P只有一个元素i
如果n>1,则排列P由排列(i)Pi构成(i=1、2、.、n-1)。
根据定义,容易看出如果已经生成了k-1个元素的排列,那么,k个元素的排列可以在每个k-1个元素的排列Pi前添加元素i而生成。
例如2个元素的排列是1  2和2   1,对3个元素而言,p1是2  3和3  2,在每个排列前加上1即生成1 2 3和1 3 2两个新排列,
p2和p3则是1  3、3  1和1  2、2  1,
按同样方法可生成新排列2 1 3、2 3 1和3 1 2、3 2 1。
 * 
@author: sitinspring(junglesong@gmail.com)
 * @date: 2008-3-25
 
*/

public class Permutation<T>{
    
public static void main(String[] args){
        String[] arr
={"1","2","3"};
        
        Permutation
<String> a=new Permutation<String>();
        a.permutation(arr,
0,arr.length);
    }

    
    
public void permutation(T[] arr,int start,int end){
        
if(start<end+1){
            permutation(arr,start
+1,end);
            
            
for(int i=start+1;i<end;i++){
                T temp;
                
                temp
=arr[start];
                arr[start]
=arr[i];
                arr[i]
=temp;
                
                permutation(arr,start
+1,end);
                
                temp
=arr[i];
                arr[i]
=arr[start];
                arr[start]
=temp;
            }

        }

        
else{
            
for(int i=0;i<end;i++){
                System.out.print(arr[i]);
            }

            System.out.print(
"\n");
        }

    }

}

posted @ 2008-03-25 05:33 和风细雨 阅读(298) | 评论 (0)编辑 收藏

JNDI概述

JNDI(Java Naming and Directory Interface)的中文意思是Java命名和目录接口。
借助于JNDI ,开发者能够通过名字定位用户,机器,网络,对象,服务。 JNDI的常见功能有定位资源,如定位到内网中一台打印机,定位Java对象或RDBMS(关系型数据库管理系统)等
在EJB,RMI,JDBC等JavaEE(J2EE)API技术中JNDI得到了广泛应用。JNDI为J2EE平台提供了标准的机制,并借助于名字来查找网络中的一切对象。

理解“命名和目录服务”

在掌握JNDI之前,开发者必须理解命名和目录服务。
名字类似于引用,即能标识某实体如对象,人等。在企业应用中,经常需要借助于名字实现对各种对象的引用,如借助于名字引用电话号码,IP地址,远程对象等。
命名服务类似于话务员,如果需要打电话给某人,但又不知道他的电话号码,于是将电话打到查询台,以便能够询问到用户的电话号码,打电话者需要提供人名给他。随后,话务员就能查到那人的电话号码。



命名服务的功能

将名字与对象绑定在一起,这类似于电话公司提供的服务,比如将人名绑定到被叫端的电话。
提供根据名字查找对象的机制。这称为查找对象或者解析名字。这同电话公司提供的服务类似,比如根据人名查找到电话号码。

在现实的计算机环境中,命名服务很常见,如需要定位网络中的某台机器,则借助于域名系统(Domain Name System,DNS)能够将机器名转化成IP地址。

目录对象和目录服务

在命名服务中,借助名字能够找到任何对象,其中有一类对象比较特殊,它能在对象中存储属性,它们被称之为目录对象或称之为目录入口项(Directory Entry)。将目录对象连接在一起便构成了目录(Directory),它是一个树状结构的构成,用户可以通过节点和分支查找到每个目录对象。
目录服务是对命名服务的扩展,它能够依据目录对象的属性而提供目录对象操作。

JNDI的概念和主要用途

为实现命名和目录服务,基于java的客户端需要借助于JNDI系统,它为命名和目录服务架起了通信的桥梁。JNDI的主要用途有:
开发者使用JNDI,能够实现目录和Java对象之间的交互。
使用JNDI,开发者能获得对JAVA事务API中UserTransaction接口的引用。
借助于JNDI,开发者能连接到各种资源工厂,如JDBC数据源,Java消息服务等。
客户和EJB组件能够借助于JNDI查找到其他EJB组件。

名字,绑定和上下文的概念

JNDI中存在多种名字,一种是原子名,如src/com/sitinspring中的src,com和sitinspring;一种是复合名,它由0个或多个原子名构成,如src/com/sitinspring。
绑定就是将名字和对象关联起来的操作。如system.ini绑定到硬盘中的文件, src/com/sitinspring/.classpath分别绑定到三个目录和一个文件。
上下文(Context)由0个或多个绑定构成,每个绑定存在不同的原子名。如WEB-INF文件夹下分别含有.cvsignore和web.xml的文件名。在JNDI中, WEB-INF是上下文,它含有原子名.cvsignore和web.xml的绑定,它们分别绑定到硬盘中的文件。
上下文中也允许存在上下文,它们被成为子上下文(subcontext),子上下文和上下文类似,它也能含有多个名字到对象的绑定。这类似于文件夹下含有子文件夹。

命名系统和初始上下文

命名系统由一套连在一起的上下文构成,而且这些上下文使用了相同的命名语法。可以用目录树来类比这个概念。
浏览命名空间的起点称之为初始上下文(Initial Context),初始上下文类似于目录树中的根节点概念。

借助于初始上下文,能够开始命名和目录服务。

JNDI查找资源示例

try {
  Context initCtx = new InitialContext();
  // java:comp/env是命名空间,相当于是本机JNDI资源引用根目录
  Context envCtx = (Context) initCtx.lookup("java:comp/env");
  Member bean = (Member) envCtx.lookup("Member");

  System.out.print("member name=" + bean.getMemberName() + " age="
      + bean.getAge());
} catch (NamingException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

JNDI有关API

list():用于获得当前上下文的绑定列表
lookup():用于解析上下文中名字绑定,该操作将返回绑定到给定名字的对象。
rename():重新命名
createSubContext():从当前上下文创建子上下文。
destroySubContext():从当前上下文销毁子上下文。
bind()。从当前上下文中创建名字到对象的绑定。
rebind():再次绑定,如果已经存在同名绑定则覆盖之。

posted @ 2008-03-20 12:55 和风细雨 阅读(655) | 评论 (0)编辑 收藏

如何配置filter解决Struts的中文问题

1.制作一filter类如下:
package com.sitinspring.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class SetCharacterEncodingFilter implements Filter {
    
protected String encoding = null;

    
protected FilterConfig filterConfig = null;

    
protected boolean ignore = true;

    
public void destroy() {
        
this.encoding = null;
        
this.filterConfig = null;
    }


    
public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) 
throws IOException, ServletException {

        
// Conditionally select and set the character encoding to be used
        if (ignore || (request.getCharacterEncoding() == null)) {
            String encoding 
= selectEncoding(request);
            
if (encoding != null)
                request.setCharacterEncoding(encoding);
        }


        
// Pass control on to the next filter
        chain.doFilter(request, response);

    }


    
public void init(FilterConfig filterConfig) throws ServletException {

        
this.filterConfig = filterConfig;
        
this.encoding = filterConfig.getInitParameter("encoding");
        String value 
= filterConfig.getInitParameter("ignore");
        
if (value == null)
            
this.ignore = true;
        
else if (value.equalsIgnoreCase("true"))
            
this.ignore = true;
        
else if (value.equalsIgnoreCase("yes"))
            
this.ignore = true;
        
else
            
this.ignore = false;

    }


    
protected String selectEncoding(ServletRequest request) {
        
return (this.encoding);
    }


}


2.在Web.xml中配置这个filter。
    <!-- filter -->
    
<filter>
        
<filter-name>Set Character Encoding</filter-name>
        
<filter-class>com.sitinspring.filter.SetCharacterEncodingFilter</filter-class>
        
<init-param>
            
<param-name>encoding</param-name>
            
<param-value>UTF-8</param-value>
        
</init-param>
    
</filter>
    
<filter-mapping>
        
<filter-name>Set Character Encoding</filter-name>
        
<url-pattern>/*</url-pattern>
    
</filter-mapping>

3.Action调用示例:
package com.sitinspring.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

/**
 * Action定义处
 * 
@author sitinspring
 *
 * @date 2008-3-20
 
*/

public final class HelloAction extends Action {
    
public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            
throws Exception {
        request.setCharacterEncoding(
"UTF-8");

        
// 取Form中参数name
        String name = (String) PropertyUtils.getSimpleProperty(form, "name");
        
        request.setAttribute(
"msg""欢迎你!"+name);

        
return (mapping.findForward("SayHello"));
    }

}


以上。

posted @ 2008-03-20 12:46 和风细雨 阅读(791) | 评论 (0)编辑 收藏

使用正则表达式解析SQL语句

本文详细代码请见:
http://www.blogjava.net/sitinspring/archive/2008/03/14/186372.html

 

问题:将左边的SQL语句解析成右边的形式

Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group  by g1,g2,g3 order  by g2,g3

select
     c1,
    c2,
    c3
from
     t1,
    t2,
    t3
where
     condi1=5 and
     condi6=6 or
     condi7=7
group by
     g1,
    g2,
    g3
order by
     g2,
    g3

按关键字找出SQL语句中各部分

我们阅读SQL语句会把整句分来成列,表,条件,分组字段,排序字段来理解,解析SQL的目的也是这样.
分解SQL语句有规律可循,以列为例,它必定包含在select和from之间,我们只要能找到SQL语句中的关键字select和from,就能找到查询的列.
怎么找到select和from之间的文字呢?其实一个正则表达式就能解决:(select)(.+)(from),其中第二组(.+)代表的文字就是select和from之间的文字.
程序见右边.

/**
 * 从文本text中找到regex首次匹配的字符串,不区分大小写
 * @param regex: 正则表达式
 * @param text:欲查找的字符串
 * @return regex首次匹配的字符串,如未匹配返回空
 */
private static String getMatchedString(String regex,String text){
  Pattern pattern=Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
   
    Matcher matcher=pattern.matcher(text);

    while(matcher.find()){
      return matcher.group(2);
    }
   
    return null;
}

解析函数分析

private static String getMatchedString(String regex,String text){
  Pattern pattern=Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
   
    Matcher matcher=pattern.matcher(text);

    while(matcher.find()){
      return matcher.group(2);
    }
   
    return null;
}

左边的这个函数,第一个参数是拟定的正则表达式,第二个是整个SQL语句.
当正则表达式为(select)(.+)(from)时,程序将在SQL中查找第一次匹配的地方(有Pattern.CASE_INSENSITIVE的设置,查找不区分大小写),如果找到了则返回模式中的第二组代表的文字.
如果sql是select a,b from tc,则返回的文字是a,b.

选择的表对应的查找正则表达式

选择的表比较特殊,它不想选择的列一样固定处于select和from之间,当没有查找条件存在时,它处于from和结束之间;当有查找条件存在时,它处于from和where之间.
因此查询函数写为右边的形式:

/**
 * 解析选择的表
 *
 */
private void parseTables(){
    String regex="";  
   
    if(isContains(sql,"\\s+where\\s+")){
      regex="(from)(.+)(where)";  
    }
    else{
      regex="(from)(.+)($)";  
    }
   
    tables=getMatchedString(regex,sql);
}


isContains函数

isContains函数用于在lineText中查找word,其中不区分大小些,只要找到了即返回真.

/**
 * 看word是否在lineText中存在,支持正则表达式
 * @param lineText
 * @param word
 * @return
 */
private static boolean isContains(String lineText,String word){
  Pattern pattern=Pattern.compile(word,Pattern.CASE_INSENSITIVE);
  Matcher matcher=pattern.matcher(lineText);
  return matcher.find();
}

解析查找条件的函数

private void parseConditions(){
    String regex="";  
   
    if(isContains(sql,"\\s+where\\s+")){
      // 包括Where,有条件
     
      if(isContains(sql,"group\\s+by")){
        // 条件在where和group by之间
        regex="(where)(.+)(group\\s+by)"; 
      }
      else if(isContains(sql,"order\\s+by")){
        // 条件在where和order by之间
        regex="(where)(.+)(order\\s+by)"; 
      }
      else{
        // 条件在where到字符串末尾
        regex="(where)(.+)($)"; 
      }       
    }
    else{
      // 不包括where则条件无从谈起,返回即可
      return;
    }
   
    conditions=getMatchedString(regex,sql);
}

解析GroupBy的字段

private void parseGroupCols(){
    String regex="";  
   
    if(isContains(sql,"group\\s+by")){
      // 包括GroupBy,有分组字段

      if(isContains(sql,"order\\s+by")){
        // group by 后有order by
        regex="(group\\s+by)(.+)(order\\s+by)"; 
      }
      else{
        // group by 后无order by
        regex="(group\\s+by)(.+)($)"; 
      }     
    }
    else{
      // 不包括GroupBy则分组字段无从谈起,返回即可
      return;
    }
   
    groupCols=getMatchedString(regex,sql);
}


解析OrderBy的字段

private void parseOrderCols(){
    String regex="";  
   
    if(isContains(sql,"order\\s+by")){
      // 包括order by,有分组字段
      regex="(order\\s+by)(.+)($)";                 
    }
    else{
      // 不包括GroupBy则分组字段无从谈起,返回即可
      return;
    }
     
    orderCols=getMatchedString(regex,sql);
}

得到解析后的各部分

按以上解析方法获得了列,表,条件,分组条件,排序条件各部分之后,它们会存储到各个成员变量中.
注意这些成员变量的原值都是null,如果在SQL语句中能够找到对应的部分的话它们将借助getMatchedString获得值,否则还是null.我们通过判断这些成员变量是否为空就能知道它对应的部分是否被解析出来.

 /**
   * 待解析的SQL语句
   */
  private String sql;
 
  /**
   * SQL中选择的列
   */
  private String cols;
 
  /**
   * SQL中查找的表
   */
  private String tables;
 
  /**
   * 查找条件
   */
  private String conditions;
 
  /**
   * Group By的字段
   */
  private String groupCols;
 
  /**
   * Order by的字段
   */
  private String orderCols;

取得不需要单行显示时的SQL语句

进展到这一步,SQL语句中列,表,条件,分组条件,排序条件各部分都被获取了出来,这时把它们重新组合一下就能得到整理后的SQL语句.
如下面的SQL语句将变成右边的部分(先使静态成员isSingleLine=false):
Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group  by g1,g2,g3 order  by g2,g3

select
     c1,c2,c3
from
     t1,t2,t3
where
     condi1=5 and condi6=6 or condi7=7
group by
     g1,g2,g3
order by
     g2,g3


进一步解析

有时我们需要把列,表,条件,分组条件,排序条件单行显示以方便查看或加上注释,这就要求我们对列,表,条件,分组条件,排序条件等进行进一步解析.
初看解析很方便,以固定的分隔符劈分即可,但需要注意的是查询条件中分隔符有and和or两种,如果贸然分隔会使重新组合时使SQL失真.
推荐一种做法,我们可以在分隔符后加上一个标志如空行,然后再以这个标志来劈分.这样就不会使SQL失真了.
请见下页的getSplitedParagraph函数.

getSplitedParagraph函数

private static List<String> getSplitedParagraph(String paragraph,String splitStr){
  List<String> ls=new ArrayList<String>();   
 
  // 先在分隔符后加空格
  Pattern p = Pattern.compile(splitStr,Pattern.CASE_INSENSITIVE);

  Matcher m = p.matcher(paragraph);
  StringBuffer sb = new StringBuffer();

  boolean result = m.find();
  while (result) {
    m.appendReplacement(sb, m.group(0) + Crlf);
    result = m.find();
  }
  m.appendTail(sb);
 
  // 再按空格断行
  String[] arr=sb.toString().split("[\n]+");
  for(String temp:arr){
    ls.add(FourSpace+temp+Crlf);
  }
 
  return ls;
}

处理结果

把静态成员变量isSingleLine=true后我们来看看执行结果:
select
     c1,
    c2,
    c3
from
     t1,
    t2,
    t3
where
     condi1=5 and
     condi6=6 or
     condi7=7
group by
     g1,
    g2,
    g3
order by
     g2,
    g3

小结

从这个例子中我们体会了分治的思想:分治是把一个大问题分解成小问题,然后分别解决小问题,再组合起来大问题的解决方法就差不多了.这种思想在工程领域解决问题时很普遍,我们要学会使用这种思想来看待,分析和解决问题,不要贪多求大,结果导致在大问题面前一筹莫展.
其次我们可以从这个例子中学习找规律,然后借助规律的过程,现实世界千变万化,但都有规律可循,只要我们找到了规律,就等于找到了事物之门的钥匙.
接下了我们复习了正则表达式用于查找的方法,以前的正则表达式学习多用于验证匹配,其实这只是正则表达式的一部分功能.
最后从解析条件成单行的过程中,我们可以学习到一种解决问题的技巧,即当现实中的规律存在变数时加入人为设置的规律,这有时能使我们更好更快的解决问题.

posted @ 2008-03-19 22:00 和风细雨 阅读(9635) | 评论 (4)编辑 收藏

Blogjava的CSS实现

效果:


CSS页面设置代码:
body{
    margin
:0 auto;
    text-align
:center;
    min-width
:760px;
    background
:#e6e6e6;
}


#bodyDiv
{
    width
:924px;
    margin
:0 auto;
    text-align
:left;
    background
:#eefaec;
}


#header
{
    width
:924px;
    height
:132px;
    background
:#ffffff;
}


#sidebar
{
    margin
:2px;
    width
:170px;
    height
:560px;
    float
:right;
    background
:#ffffff;
    border-style
:dashed;
    border-color
:#b9ecae;
    border-width
:1px;
    padding-top
:20px;
    padding-bottom
:20px;
}


#sidebar li
{
    padding-left
:20px;
    padding-right
:20px;
}


#content
{
    margin
:2px;
    width
:740px;
    height
:560px;
    float
:left;
    border-style
:dashed;
    border-color
:#b9ecae;
    border-width
:1px;
    background
:#f8f8f8;
    padding-top
:20px;
}


#footer
{
    clear
:both;
    background
:#eefaec;
}


ul
{
    margin
:0;
    padding
:0;
    list-style-type
:none;
}


a:link 
{
    color
: #6fbc4c;
    text-decoration
: none;
}

a:active 
{
    color
: #6fbc4c;
}

a:visited 
{
    color
: #6fbc4c;
}

a:hover 
{
    color
: #646464;
}


h1 
{
    font-size
: 18px; 
    margin
: 10px 0px 5px; 
    color
: #666666; 
    text-align
: center;
}

h2 
{
    font-size
: 16px; 
    margin
: 10px 0px 5px; 
    color
: #666666; 
    text-align
: center;
}

h3 
{
    font-size
: 14px; 
    margin
: 10px 0px 5px; 
    color
: #666666; 
    text-align
: center;
}

页面代码:
<%@ page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Bug管理布局示例</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" rev="stylesheet" href="web/css/bugmngLayout.css"
    type
="text/css" />
</head>

<body>
<div id="bodyDiv">
<div id="header">
    
<jsp:include page="/web/page/branch/header2.jsp"/>
</div>
<div id="sidebar">
    
<jsp:include page="/web/page/branch/sidebar.jsp"/>
</div>
<div id="content">
    
<jsp:include page="/web/page/branch/content.jsp"/>
</div>
<div id="footer">
    
<jsp:include page="/web/page/branch/footer.jsp"/>
</div>
</div>
</body>
</html>





posted @ 2008-03-17 22:06 和风细雨 阅读(346) | 评论 (0)编辑 收藏

使用CSS设置网页元素样式

在XHTML中CSS的意义

传统的HTML能够并已经创建了大量优秀美观使用的网页,但随着时代的发展和客户要求的逐步提高,传统HTML网页将网页的数据,表现和行为混杂的方式妨碍了自身可维护性和精确性的提高。
在XHTML中,CSS能把网页的数据和表现(主要是格式和样式规则)分隔开来,使人对网页能有更精确细致的控制,同时可维护性也变得更好,更方便。
在本文中,我们将学习CSS的相关知识。

框模型

在CSS处理网页时,它认为网页包含的每一个元素都包含在一个不可见的框中,这个框由内容(Content),内容外的内边距(padding),内边距的外边框(border)和外边框的不可见空间-外边距(margin)组成。


块级元素和行内元素

在XHTML中,元素可能是块级(block)的,也可能是行级(inline)的。
块级元素会产生一个新行(段落),而行级元素是行内的,不会产生新行(段落)。
常见的块级元素有div,p等,常见的行级元素有a,span等。
在默认情况下,元素按照在XHTML中从上到下的次序显示,并且在每个块级元素的框的开头和结尾换行。

注意:块级元素和行级元素不是绝对的,我们可以通过样式设置来改变元素的这个属性。

元素的基本属性

内边距:padding
边框:border
外边距:margin
大小:width,height
对齐:text-align
颜色:color
背景:background
使元素浮动:float

下面将讲述如何对这些元素属性进行设置。

改变元素背景

Background有以下子属性:
background-color:背景颜色,默认值transparent,输入#rrggbb即可。
background-image:背景图像,默认值none
background-repeat:背景图像的重复显示,默认值repeat(纵横重复),repeat-x(水平重复),repeat-y(垂直重复),no-repeat(使图像不并排显示)
background-attachment:默认值scroll,表示随页面滚动,如果是fixed则不随页面滚动。
background-posistion:默认值top left。

这些属性也可以统一设置,如:background:#ccc url(theadbg.gif) repeat-x left center;
例:
TABLE.Listing TH {
    FONT-WEIGHT: bold;
    background:#ccc url(theadbg.gif) repeat-x left center;
    BORDER-BOTTOM: #6b86b3 1px solid
}

设定元素的大小

设置width和height即可,如:
width:180px;
height:50%;
注意这里可以设置绝对大小如180px也可以设置相对大小50%,其中百分数是相对与父元素的比例,父元素即容纳本元素的元素。
此外设置元素大小还可以使用min-width,max-width,max-height,min-height等,但在部分浏览器中不支持这些属性。
例:
#content{
width:640px;
height:500px;
float:right;
background:#f8f8f8;
}

Px和em的区别

px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。(引自CSS2.0手册)
em是相对长度单位。相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸。(引自CSS2.0手册) 任意浏览器的默认字体高都是16px。所有未经调整的浏览器都符合: 1em=16px。那么12px=0.75em, 10px=0.625em。为了简化font-size的换算,需要在css中的body选择器中声明Font-size=62.5%,这就使em值变为 16px*62.5%=10px, 这样12px=1.2em, 10px=1em, 也就是说只需要将你的原来的px数值除以10,然后换上em作为单位就行了。

设置元素的外边距

外边距是一个元素与下一个元素之间的透明空间量,位于元素的边框外边。
设置外边距设置margin的值即可,如margin:1;它将应用与四个边。
如果要为元素的上右下左四个边设置不同的外边距,可以设置margin-top,margin-right,margin-bottom,margin-left四个属性。
例:
fieldset{
margin:1em 0;
padding:1em;
border:1px solid #ccc;
background:#f8f8f8;
}

添加元素的内边距

内边距是边框到内容的中间空间。使用它我们可以把内容和边界拉开一些距离。
设置内边距如右:padding:1px;
如果要为元素的上右下左四个边设置不同的内边距,可以设置padding-top,padding-right,padding-bottom,padding-left四个属性。
例:
li{
padding-left:10px;
}


控制元素浮动

float属性可以使元素浮动在文本或其它元素中,这种技术的最大用途是创建多栏布局(layout)
float可以取两个值:left,浮动到左边,right:浮动到右边
例:
#sidebar{
width:180px;
height:500px;
float:left;
background:#f8f8f8;
padding-top:20px;
padding-bottom:20px;
}

#content{
width:640px;
height:500px;
float:right;
background:#f8f8f8;
}

设置边框

边框位于外边距和内边距中间,在应用中常用来标示特定的区域。它的子属性有:
border-style:可以设定边框的样式,常见的有solid,dotted,dashed等。
border-width:边框的宽度。
border-color:边框颜色
border-top,border-right,border-bottom,border-left可以把边框限制在一条或几条边上。
例:
ul a{
display:block;
padding:2px;
text-align:center;
text-decoration:none;
width:130px;
margin:2px;
color:#8d4f10;
}

ul a:link{
background:#efb57c;
border:2px outset #efb57c;
}

控制元素内容的对齐

text-align属性可以让我们设置元素内容的对齐,它可以取的值有left,center,right等。
例:
body{
margin:0 auto;
text-align:center;
min-width:760px;
background:#e6e6e6;
}

#bodyDiv{
width:822px;
margin:0 auto;
text-align:left;
background:#f8f8f8;
border:1px solid #FFFFFf;
}

控制元素在父元素的垂直对齐

设置vertical-align可以控制元素在父元素的垂直对齐位置,它可以取的值有:
middle:垂直居中
text-top:在父元素中顶对齐
text-bottom:是元素的底线和父元素的底线对齐。

在网页中引入样式表

<title>"記賬系统"单项收支记录浏览页面</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="web/js/ajax.js" type="text/javascript"></script>
<link rel="stylesheet" rev="stylesheet" href="web/css/style.css"
type="text/css" />

</head>

样式表示例

body{
  margin:0 auto;
  text-align:center;
  min-width:760px;
  background:#e6e6e6;
}

#bodyDiv{
  width:822px;
  margin:0 auto;
  text-align:left;
  background:#f8f8f8;
  border:1px solid #FFFFFf;
}


TABLE.Listing {
    MARGIN: 0px 0px 8px;
    WIDTH: 92%;
    BORDER-BOTTOM: #6b86b3 3px solid
}

#content{
  width:640px;
  height:500px;
  float:right;
  background:#f8f8f8;
}

#content h1,#content h2,#content p{
  padding-left:20px;
}

#footer{
  clear:both;
}

fieldset{
  margin:1em 0;
  padding:1em;
  border:1px solid #ccc;
  background:#f8f8f8;
}


如何知道页面元素对应样式表的那部分?

如果页面元素设置了id,则它对应的样式表部分是#id,如#bodyDiv。
如果页面元素设定了class,则它在样式表中寻找”元素类型.class”对应的部分,如TABLE.Listing。
如果没有写明,则元素会找和自己类型对应的样式设置,如fieldset。

注意CSS中没有大小写的区别。

例:
<div id="content">

<table id="TbSort" class="Listing" width=100% align=center>

<fieldset><legend>添加账目</legend>

posted @ 2008-03-14 12:59 和风细雨 阅读(1325) | 评论 (0)编辑 收藏

JavaScript基本语法

JavaScript的运行环境和代码位置

编写JavaScript脚本不需要任何特殊的软件,一个文本编辑器和一个Web浏览器就足够了,JavaScript代码就是运行在Web浏览器中。
用JavaScript编写的代码必须嵌在一份html文档才能得到执行,这可以通过两种方法得到,第一种是将JavaScript代码直接写在html文件中,这多用于仅适用于一个页面的JS程序;另一种是把JavaScript代码存入一个独立的文件中(.js作为扩展名),在利用<Script>标签的src属性指向该文件.

将JavaScript直接嵌入页面文件中

<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>欢迎进入"我的事务备忘录"</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="web/js/strUtil.js" type="text/javascript"></script>
</head>

<body>
<div>这个页面应该很快消失,如果它停止说明Web容器已经停止运作了,或JavaScript功能未开启
<form method=post action="ShowPage?page=login">
</form>
<div>
</body>
</html>

<script LANGUAGE="JavaScript">
<!--
document.body.onload=function(){
 document.forms[0].submit();

//-->
</script>


将JavaScript存入单独的文件中(页面文件)

<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>"我的事务备忘录"用户登录页面</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="web/js/ajax.js" type="text/javascript"></script>
<link rel="stylesheet" rev="stylesheet" href="web/css/style.css"
 type="text/css" />
</head>

<body>
<div id="branding">欢迎进入"个人事务备忘录",请输入您的用户名和密码,再按登录键登录
<form method=post action="ShowPage?page=loginCheck">
 <table  bgcolor="#ffffff" id="TbSort" class="Listing" width="200" align=center>
  <tbody id="loginTable">
   <tr><th align="center" colspan=3>用户登录.</th></tr>
   <tr>
    <td width=50>用户名:</td>
    <td width=150><input type="text" name="userName" value=""
      style="width: 300px; height: 20px" /></td>
   </tr>
   <tr>
    <td width=50>密码:</td>
    <td width=150><input type="text" name="userPswd" value=""
      style="width: 300px; height: 20px" /></td>
   </tr>
   <tr>
    <td width=50></td>
    <td width=150><input type="submit" value="登录"
      style="width: 100px; height: 20px" /></td>
   </tr>
  </tbody>
 </table>
</form>
<div>
</body>
</html>

将JavaScript存入单独的文件中(ajax.js)

var prjName="/MyTodoes/";
var ajaxObj;

function createAjaxObject(){
 try{return new ActiveXObject("Msxml2.XMLHTTP");}catch(e){};
 try{return new ActiveXObject("Microsoft.XMLHTTP");}catch(e){};
 try{return new XMLHttpRequest();}catch(e){};
 alert("XmlHttpRequest not supported!");
 return null;
}

function $(id){
     return document.getElementById(id);
}

JavaScript中的语句和注释

JavaScript中的语句和Java中一样,也是一行书写一条语句,末尾加上分号’;’,虽然js中也可以把多条语句写在一行,但推荐不要这样做.
JavaScript中注释也和Java中一样,以// 来注释单行,/*….*/来注释多行,虽然HTML风格的注释<!-- *****  --> 在JS中也有效,但建议不要这样做.


JavaScript中的变量

在js中,变量允许字母,数字,美元符号和下划线字符.变量定义使用var关键字,如
var age;
age=23;
var name=“andy”;
虽然js允许程序员可以直接对变量进行赋值而无需提前对它们做出声明,但我们强烈建议不要这样做.
Js中变量和其它语法元素都是区分字母大小写的,如变量age,Age,AGE没有任何关系,它们都不是同一个变量.

JavaScript是一种弱类型语言

和强制要求程序员对数据类型做出声明的强类型(Strongly typed)程序设计语言如java,C#等不一样,js不要求程序员进行类型说明,这就是所谓的弱类型”weakly typed”语言.这意味着程序员可以随意改变某个变量的数据类型.
以下写法在Java中是绝对不允许的,但在js中完全没有问题:
var age=23;
age=“Twenty three”
Js并不关心age的值是字符串还是变量.

JavaScript中的数据类型-字符串

字符串必须放在单引号或双引号中.如
var name=“Andy”;
var name=‘Bill’;
一般情况下宜使用双引号,但如果字符串中有双引号则应该把字符串放在单引号中,反之则应该把字符串放在双引号中.

JavaScript中的数据类型-数值

Js中并没有int,float,double,long的区别,它允许程序员使用任意位数的小数和整数,实际上js中的数值应该被称为浮点数.
如:
var salary=10000;
var price=10.1;
var temperature=-6;

JavaScript中的数据类型-布尔值

Js中的布尔值和Java中的一致,true表示真,false表示假,如:
var isMale=true;
var isFemale=false;

注意布尔值true和false不要写成了字符串”true”和’false’.

JS中的函数

如果需要多次使用同一组语句,可以把这些语句打包成一个函数。所谓函数就是一组允许人们在代码中随时调用的语句。从效果上看,每个函数都相当于一个短小的脚本。
和Java中每个函数都在类中不一样,JS中函数不必属于一个类,在使用上它类似于Java中的静态公有函数,只要引入这个函数所在的文件就可以使用它。

JS中函数的语法

JS中,一个函数的大致语法如下:
function fname(args){
      statements;
}
Function是函数的固定标志;fname是函数名;args是函数参数,它可以有很多个,只要你把它们用逗号分割开来即可;statements是其中的语句,每句结尾都和java中一样用“;”表示结束。

在定义了这个函数的脚本(页面)中,你可以从任意位置去调用这个函数;引入这个页面后,你还可以从其它页面访问它。

一般来说,对于共通性强,适用面广,会在多个页面中调用的函数,我们一般把它们放在一个JS页面中,然后由需要使用这些函数的页面引入它们;而对于只适用于一个页面的函数,还是把它放在单个页面中较好。

JS函数的返回值

在JS中,函数不仅能够以参数的形式接受数据,运行代码,它和其它编程语言中的函数一样,可以返回数据。
让JS函数返回数据,你不需要也不能在函数签名上动任何手脚,只需要用return语句返回你想返回的数字即可,举例如下:
function substract(op1,op2){
     return op1-op2; }
}

JS中变量的作用域

在JS中,我们提倡用var来定义一个变量,凡是变量就会有作用域的问题,根据定义方式和位置的不同,它既可能是全局的,也有可能是局部的。
用var定义在脚本文件中,不属于任何一个函数的变量,它的作用域就是全局性的,它可以在脚本中的任何位置被引用,包括有关函数的内部。全局变量的作用域是整个脚本。
用var定义在函数中的变量,它的作用域就是局部性的,它的作用域仅限于这个函数,在函数的外部是无法使用它的。
不用var定义在函数中的变量,它的作用域是全局的,如果你的脚本里已经存在一个与之同名的变量,这个函数将覆盖那个现有变量的值。
定义函数时,我们必须明确的把它内部的变量都明确的声明为局部变量,如果从来没有忘记在函数中使用var关键字,就可以避免任何形式的二义性隐患。

JS中的数组

在JS中,我们使用Array关键字声明数组,在声明时对数组长度进行限定,如:
var arr=Array(3);
有时运行起来才知道数组长度,JS中我们也可以这样定义数组:
var arr=Array();
向数组中添加元素时你需要给出新元素的值,还需要在数组中为新元素制定存放位置,这个位置由下标给出,如arr[1]=4。

在JS中定义数组的例子

定义方式一:
var arr=Array(3);
arr[0]=“刘备”; arr[1]=“关于”; arr[2]=“张飞”;
定义方式二:
var arr=Array();
arr[0]=3; arr[1]=4;arr[2]=5;
定义方式三:
Var arr=Array(“1”,2,true);
定义方式四:
var arr=[“征东”,”平西”,”镇南”,”扫北”];

posted @ 2008-03-14 12:49 和风细雨 阅读(1983) | 评论 (0)编辑 收藏

仅列出标题
共10页: 上一页 1 2 3 4 5 6 7 8 9 下一页 Last