The NoteBook of EricKong

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

#

package www.puyufanyi.com;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import www.puyufanyi.com.test.Word;

import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import android.widget.TextView;

public class UIActivity extends ListActivity {

    
private ArrayList<Word> words = new ArrayList<Word>();

    @Override
    
public void onCreate(Bundle savedInstanceState) {
        
super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Word word1 
= new Word("index1""result1");
        Word word2 
= new Word("index2""result2");
        Word word3 
= new Word("index3""result3");
        Word word4 
= new Word("index4""result4");
        Word word5 
= new Word("index5""result5");
        
this.words.add(word1);
        
this.words.add(word2);
        
this.words.add(word3);
        
this.words.add(word4);
        
this.words.add(word5);

        List
<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>();

        
for (int i = 0; i < words.size(); i++) {
            Map
<String, Object> listItem = new HashMap<String, Object>();
            listItem.put(
"Index", words.get(i).getIndex());
            listItem.put(
"Result", words.get(i).getResult());
            listItems.add(listItem);
        }
        SimpleAdapter simpleAdapter 
= new SimpleAdapter(
                
this
                listItems, 
                R.layout.main,
                
new String[]{"Index","Result"},
                
new int[]{R.id.index,R.id.result}
        );
                setListAdapter(simpleAdapter);
                ListView lv 
= getListView(); 
                lv.setTextFilterEnabled(
true);
                lv.setOnItemClickListener(
new OnItemClickListener() {
                    
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
                         String  indexValue 
= ((TextView)view.findViewById(R.id.index)).getText().toString();
                         Toast.makeText(getApplicationContext(), indexValue, Toast.LENGTH_SHORT).show();    
                    }  
                });
                
     }
}
posted @ 2012-02-29 15:36 Eric_jiang 阅读(233) | 评论 (0)编辑 收藏

首先写一个定义Button样式的XML文件:
新建Android XML文件,类型选Drawable,根结点选selector,文件名就buton_style吧。
程序自动给我们刚刚建的文件里加了selector结点,我们只需要在selector结点里写上三种状态时显示的背景图片(按下、获取焦点,正常)。
代码如下:

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
	<item android:state_pressed="true" android:drawable="@drawable/play_press" />
	<item android:state_focused="true" android:drawable="@drawable/play_press" />
	<item android:drawable="@drawable/play" />
</selector>

我这里获取焦点跟点击时显示的是同一张图片,必须严格照上面的顺序写,不可倒。
接下来只要在布局时写Button控件时应用到Button的Background属性即可。

1
2
3
4
<Button android:id="@+id/button1"
	android:layout_width="wrap_content" android:layout_height="wrap_content"
	android:background="@drawable/button_style"
></Button>

最终效果图:

点击时会变。
源代码下载:
Button_style (313)
再加上一种自定义样式方法,上面的是用图片,其实我们可以直接通过定义xml文件来实现不同的样式:
在上面的源代码基础上,只需要修改button_style文件,同样三种状态分开定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
	<item android:state_pressed="true">
		<shape>
			<gradient android:startColor="#0d76e1" android:endColor="#0d76e1"
				android:angle="270" />
			<stroke android:width="1dip" android:color="#f403c9" />
			<corners android:radius="2dp" />
			<padding android:left="10dp" android:top="10dp"
				android:right="10dp" android:bottom="10dp" />
		</shape>
	</item>
 
	<item android:state_focused="true">
		<shape>
			<gradient android:startColor="#ffc2b7" android:endColor="#ffc2b7"
				android:angle="270" />
			<stroke android:width="1dip" android:color="#f403c9" />
			<corners android:radius="2dp" />
			<padding android:left="10dp" android:top="10dp"
				android:right="10dp" android:bottom="10dp" />
		</shape>
	</item>
 
	<item>
		<shape>
			<gradient android:startColor="#000000" android:endColor="#ffffff"
				android:angle="180" />
			<stroke android:width="1dip" android:color="#f403c9" />
			<corners android:radius="5dip" />
			<padding android:left="10dp" android:top="10dp"
				android:right="10dp" android:bottom="10dp" />
		</shape>
	</item>
</selector>

gradient 主体渐变 startColor开始颜色,endColor结束颜色 ,angle开始渐变的角度(值只能为90的倍数,0时为左到右渐变,90时为下到上渐变,依次逆时针类推)
stroke 边框 width 边框宽度,color 边框颜色
corners 圆角 radius 半径,0为直角
padding text值的相对位置

posted @ 2012-02-27 18:04 Eric_jiang 阅读(22257) | 评论 (0)编辑 收藏

     摘要:   Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->1.做一个DTO类Studentpackage com.wepull.student.model; public class Student&nbs...  阅读全文
posted @ 2012-02-23 17:57 Eric_jiang 阅读(419) | 评论 (0)编辑 收藏

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class TestXML {

 
    
public static void objectXmlEncoder(Object obj, String fileName)
            
throws FileNotFoundException, IOException, Exception {
        
// 创建输出文件
        File fo = new File(fileName);
        
// 文件不存在,就创建该文件
        if (!fo.exists()) {
            
// 先创建文件的目录
            String path = fileName.substring(0, fileName.lastIndexOf('.'));
            File pFile 
= new File(path);
            pFile.mkdirs();
        }

        
// 创建文件输出流
        FileOutputStream fos = new FileOutputStream(fo);
        
// 创建XML文件对象输出类实例
        XMLEncoder encoder = new XMLEncoder(fos);
        
// 对象序列化输出到XML文件
        encoder.writeObject(obj);
        encoder.flush();
        
// 关闭序列化工具
        encoder.close();
        
// 关闭输出流
        fos.close();
    }


 
    
public static List objectXmlDecoder(String objSource) throws FileNotFoundException, IOException, Exception {
        List objList 
= new ArrayList();
        File fin 
= new File(objSource);
        FileInputStream fis 
= new FileInputStream(fin);
        XMLDecoder decoder 
= new XMLDecoder(fis);
        Object obj 
= null;
        
try {
            
while ((obj = decoder.readObject()) != null{
                objList.add(obj);
            }

        }
 catch (Exception e) {
             
        }

        fis.close();
        decoder.close();
        
return objList;
    }


}
posted @ 2012-02-23 16:28 Eric_jiang 阅读(396) | 评论 (0)编辑 收藏

     摘要:   Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->import java.io.File;  import java.io.FileNotFoundException;  imp...  阅读全文
posted @ 2012-02-23 15:14 Eric_jiang 阅读(303) | 评论 (0)编辑 收藏

1、 查看当前DNS地址。
运行破解过的锐捷客户端,正常情况下,和平时一样,能够连接。Win+R呼出运行命令窗口,cmd,然后ipconfig /all,查看当前的DNS地址(“网络”,即“网上邻居”里,连接外网的网卡的IP地址和DNS都是自动获取,所以那里看不到)。注意,win7进入cmd后,默认不是system 32文件夹,所以要先cd c:/windows/system32,进入该文件夹,才能运行ipconfig命令。此时要记下当前IPV4的DNS地址(一会儿要往路由器里填),如下图中红框所示:


2、  连接路由器
此时电脑的一块网卡正常地连接校园网的插口,不用管它。将无线路由器和第二块网卡用平常用的网线(即交叉线,两端的线序不同)连接起来。注意此时连接的是无线路由器的LAN口,一般的路由器有4到5个LAN口,任意一个都行。

3、  设置无线路由器

输入无线路由器的ip地址,一般是192.168.1.1,进入设置页面。下面给出的是我的路由器设置页面,其他的也应该都差不多。

可以直接点击“网络参数”里的“Wan口设置”,设置Wan口的固定IP,网关、DNS,也可以如下面所示,利用向导一步一步来,这里图说地很明白,就不多说了,直接上图。


下一步->使用固定IP
 
下一步->

这里之所以用这个IP地址,是因为在win7中开启共享后,另一块网卡的地址会自动变成192.168.137.1(下面的设置中会看到),路由器里的IP地址要和该地址在同一个网段内,所以用192.168.137.2——192.168.137.254之间的地址都可以。当然,也可以手工设定另一块网卡的地址为其他地址,只要路由器中的地址和第二块网卡的地址在同一个网段就行了。子网掩码就用255.255.255.0。网关、DNS服务器不可留空(虽然写着“可选”)。网关要写上主机第二块网卡的地址,即192.168.137.1,如果手工改的话,就填手工改过的地址,反正这里要做的,就是给路由器一个固定的IP,网关就是内网主机的地址。DNS服务器,就填入刚才在1中查到的DNS服务器地址。这个框里只有两个,所以填前两个就行了(如果哪天这么设置不能连接了,有可能就是校园网的DNS服务器变更了,此时再重复步骤1,重新设置这里的DNS即可,其实就我们学校来说,DNS基本没变过,所以这样还是比较方便的。其他的DNS没有试过,有兴趣的话各位可以试试)。下一步->

这里是设置无线wifi的相关地方,按一般的无线路由器设置就行了。下一步->

好,无线路由器的设置完成。(当然还没有完,主机还没设置共享。虽然上面已经说了“恭喜”)
4、  设置主机共享。注意此时要在锐捷客户端已经运行的时候操作。因为有些破解过的客户端,在启动的时候,也会检测是否开启了共享,所以我们要先让它运行,再设置共享。

打开win7的网络和共享中心(“网络”里面)--适配器设置。此时可以看到两块网卡。



为了记忆方便,我们将连接外网的网卡重命名为“out”,将用于连接无线路由器的网卡重命名为“inner”。右击out,属性,会看到右边有一个“共享”选项卡,点击该选项卡:
 
然后出现下面的对话框:
 

按图操作,把“允许其他网络用户通过该计算机的网络连接”选上,第二个选不选都行,不用管。

此时,右击inner,属性,查看其ipv4的属性,应该已经自动变成192.168.137.1了。当然也可以自己手动设置一个,前面路由器的设置也要相应地更改。
 

上面两个图是用于确认第二块网卡(内网网卡)的连接状态的,不需要设置。

5        至此,无线路由器和主机的设置都已完成。把连接路由器的网线从LAN拔掉,插到Wan口上(见上面路由器的端口图),此时路由器就可以被看做一台客户机,共享主机的网络。路由器发出的无线信号可以被手机、笔记本等检测到,输入刚才设置的SSID名称和密码,应该就可以使用wifi了。当然其他的电脑也可以连接至路由器的LAN口,共享该网络。

    以后每次使用wifi时,要先关闭out(连接外网的网卡)的共享,再运行锐捷客户端,然后再开启共享(注意顺序!)。第二块网卡就可以共享第一块的网络了,并且主机的正常上网也没有任何影响。

 

缺点:主机必须一直开着....这一点没办法,路由器无法像拨ADSL一样“拨”校园网(晚上睡觉时,可以设置一个时间,让电脑自动关机,这时就可以躺在床上用手机连wifi上网了。我也尝试过用手机控制软件连接电脑,试图用手机控制电脑关机,理论上同一个网段的手机和电脑是可以通过wifi通信的,但这里毕竟是一台主机和“客户机”通过wan口连接的,所以可能无法通信。在我的M8上的控制软件也并没有与电脑连接成功)。并且这一行为是锐捷本身就不允许的,以前实验室就因为用一台主机做代理服务,让N台机器上网,经常被锐捷检测出来强制下线。但目前我使用的这个破解版本没有这个问题,并且我只共享了一个wifi,供我的手机使用,流量不大,经过几天的测试,一直都很稳定。

 

 

posted @ 2012-02-14 10:20 Eric_jiang 阅读(3954) | 评论 (2)编辑 收藏

 

风寒性感冒,例如:突然淋雨或受到冷风刺激,鼻黏膜或呼吸道分泌过多水份,导致阻塞甚至气喘。常见症状有鼻塞、流清鼻水、痰稀白、咳嗽、口不乾、身体寒冷或发热、不会流汗、头痛、全身痠痛,甚至发烧。

上述症状产生是因为风寒的寒气包覆于体表外,阳气被抑制住了,所以身体感到寒冷,但其实身体外在发热,且不易排汗。所以,此时常有人以闷棉被等方式,促使发汗,或使用发散药物治疗,例如:十味败毒散、荆防败毒散,目前市面上已有感冒冲剂,以热水冲泡后即可服用,热热喝效果好。有时候参加户外活动,比较贴心的主办单位会准备薑母茶给大家保暖,以预防风寒感冒。

风热性感冒,是指流感病毒或病毒所引起的急性上呼吸道传染疾病。常见症状有鼻塞、鼻涕黄浊、痰黏黄、咳嗽、喉咙肿痛、口渴、身体寒冷或发高热、有汗但不畅。

罹患风热性感冒时,应该多喝水,水份是组成身体重要物质,也是身体代谢废物的辅助,成人一天需要摄取的水份约2,500c.c.至3,000c.c.,但大多数人通常不足,因此风热感冒时应多喝水,摄取充足的水份,才能促使废物代谢,缓解感冒症状,使身体机能早日复原。且建议喝凉水,凉水可以帮助散热,还有滋润咽部的效果。

风寒性感冒不用多喝水,避免呼吸道水份过多反造成气喘,若要喝水,要喝温开水,也可以加些薑母;若风热性感冒,则需多喝水,且要喝凉水,也可以将运动饮料加水稀释饮用,补充身体的电解质加速身体的循环。

 

 

posted @ 2012-02-06 10:31 Eric_jiang 阅读(251) | 评论 (1)编辑 收藏

本文目标

30分钟内让你明白正则表达式是什么,并对它有一些基本的了解,让你可以在自己的程序或网页里使用它。一旦入门后,你可以从网上找到更多更详细的资料来继续学习。

别被下面那些复杂的表达式吓倒,只要跟着我一步一步来,你会发现正则表达式其实并不像你想像中的那么困难。当然,如果你看完了这篇教程之后发现自己明白了很多,却又几乎什么都记不得,那也是很正常的--其实我认为没接触过正则表达式的人在看完这篇教程后能把提到过的语法记住80%以上的可能性为零。这里只是让你明白基本道理,以后你还需要多练习,多查资料,才能熟练掌握正则表达式。

说明

正则表达式是用于进行文本匹配的工具,所以本文里多次提到了在字符串里搜索/查找,这种说法的意思是在给定的字符串中,查找与给定的正则表达式相匹配的部分。有可能字符串里有不止一个部分满足给定的正则表达式,这时每一个这样的部分被称为一个匹配。匹配在本文里可能会有三种意思:一种是形容词性的,比如说一个字符串匹配一个表达式;一种是动词性的,比如说在字符串里匹配正则表达式;还有一种是名词性的,就是刚刚说到的“字符串中满足给定的正则表达式的一部分”。

文本格式约定:专业术语 特殊代码/语法格式 正则表达式 正则表达式中的一部分(用于分析) 用于在其中搜索的字符串 对正则表达式或其中一部分的说明

什么是正则表达式?

很可能你使用过Windows/Dos下用于文件查找的通配符,也就是*?。如果你想查找某个目录下的所有的Word文档的话,你会搜索*.doc。在这里,*会被解释成任意的字符串。和通配符类似,正则表达式也是用来进行文本匹配的工具,只不过比通配符更能精确地描述你的需求--当然,代价就是更复杂。比如你可以编写一个正则表达式来查找所有以0开头,后面跟着2-3个数字,然后是一个连字号“-”,最后是7或8位数字的字符串(像010-123456780376-7654321)。

入门

在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。例如,\d+就是一个简洁的代码,代表着规则1位或更多位数字2008就符合这个规则,而A3则不符合(它包含了不是数字的字符)。

学习正则表达式的最好方法是从例子开始,理解例子之后再自己对例子进行修改,实验。下面给出了不少简单的例子,并对它们作了详细的说明。

假设你在一篇英文小说里查找hi,你可以使用正则正则表达式hi

这是最简单的正则表达式了,它可以精确匹配这样的字符串:由两个字符组成,前一个字符是h,后一个是i。通常,处理正则表达式的工具会提供一个忽略大小写的选项,如果选中了这个选项,它可以匹配hi,HI,Hi,hI

不幸的是,很多单词里包含hi这两个连续的字符,比如him,history,high等等。用hi来查找的话,这里边的hi也会被找出来。如果要精确地查找hi这个单词的话,我们应该使用\bhi\b

\b是正则表达式规定的一个特殊代码,代表着单词的开头或结尾。虽然通常英文的单词是由空格或标点符号或换行为分隔的,但是\b并不代表这些单词分隔符中的任何一个,只代表一个位置

假如你要找的是hi后面不远处跟着一个Lucy,你应该用\bhi\b.*\bLucy\b

这里,.是另一个特殊代码,代表除了换行符以外的任意字符*同样是特殊的代码,不过它代表的不是字符,也不是位置,而是数量--它指定*前边的内容可以重复任意次以使整个表达式得到匹配。因此,.*连在一起就意味着任意数量的不包含换行的字符。现在\bhi\b.*\bLucy\b的意思就很明显了:先是一个单词hi,然后是任意个任意字符(但不能是换行),最后是Lucy这个单词

如果同时使用其它的一些特殊代码,我们就能构造出功能更强大的正则表达式。比如下面这个例子:

0\d\d-\d\d\d\d\d\d\d\d代表着这样的字符串:以0开头,然后是两个数字,然后是一个连字号“-”,最后是8个数字(也就是中国的电话号码,当然,这个例子只能匹配区号为3位的情形,想同时匹配区号为4位的话,请在教程的下面寻找答案)。

这里的\d是一个新的特殊代码,代表任意的数字(0,或1,或2,或。。。)-不是特殊代码,只代表它本身--连字号。

为了避免那么多烦人的重复,我们也可以这样写这个表达式:0\d{2}-\d{8}

这里\d后面的{2}({8})指定的是前面\d必须连续重复出现2次(8次)

测试正则表达式

如果你不觉得正则表达式很难读写的话,要么你是一个天才,要么,你不是地球人。正则表达式的语法很令人头疼,即使对经常使用它的人来说也是如此。由于难于读写,容易出错,所以很有必要创建一种工具来测试正则表达式。

由于在不同的环境下正则表达式的一些细节是不相同的,本教程介绍的是Microsoft .net下正则表达式的行为,所以,我向你介绍一个.net下的工具The Regulator。首先你确保已经安装了.net Framework1.1,然后下载The Regulator,下载完后打开压缩包,运行setup.exe安装。

下面是the Regulator运行时的截图:

the Regulator运行时的截图

特殊代码

现在你已经知道几个具有特殊意义的代码了,如\b,.,*,还有\d.事实上还有更多的特殊代码,比如\s代表任意的空白符,包括空格,制表符(Tab),换行符\w代表着字母或数字

下面来试试更多的例子:

\ba\w*\b匹配以字母a开头的单词-先是某个单词开始处(\b),然后是字母a,然后是任意数量的字母或数字(\w*),最后是单词结束处(\b)

\d+匹配1个或更多连续的数字。这里的+是和*类似的特殊代码,不同的是*代表重复任意次(可能是0次),而+则代表重复1次或更多次

\b\w{6}\b 匹配刚好6个字母/数字的单词

表1.常用的特殊代码
代码/语法 说明
. 匹配除换行符以外的任意字符
\w 匹配字母或数字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束

特殊代码^以及$\b有点类似,都匹配一个位置。^匹配你要用来查找的字符串的开头,$匹配结尾。这两个代码在验证输入的内容时非常有用,比如一个网站如果要求你填写的QQ号必须为5位到12位数字时,可以使用:^\d{5,12}$

这里的{5,12}和前面介绍过的{2}是类似的,只不过{2}代表只能不多不少重复2次{5,12}则是必须重复最少5次,最多12次,否则都不匹配。

因为使用了^$,所以输入的整个字符串都要用来和\d{5,12}来匹配,也就是说整个输入必须是5到12个数字,因此如果输入的QQ号能匹配这个正则表达式的话,那就符合要求了。

和忽略大小写的选项类似,有些正则表达式处理工具还有一个处理多行的选项。如果选中了这个选项,^$的意义就变成了匹配行的开始处和结束处

字符转义

如果你想查找特殊代码本身的话,比如你查找.,或者*,就出现了问题:你没法指定它们,因为它们会被解释成其它的意思。这时你就必须使用\来取消这些字符的特殊意义。因此,你应该使用\.\*。当然,要查找\本身,你也得用\\.

例如:deerchao\.net匹配deerchao.netc:\\windows匹配c:\windows,2\^8匹配2^8(通常这是2的8次方的书写方式)。

重复

你已经看过了前面的*,+,{2},{5,12}这几个代表重复的方式了。下面是正则表达式中所有指定重复的方式:

表2.常用的量词
代码/语法 说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

下面是一些使用重复的例子:

Windows\d+匹配Windows后面跟1个或更多数字

13\d{9}匹配以13后面跟9个数字(中国的手机号)

^\w+匹配一行的第一个单词(或整个字符串的第一个单词,具体代表哪个意思得看选项设置)

字符类

要想查找数字,字母或数字,空白是很简单的,因为已经有了对应这些字符集的特殊代码,但是如果你想匹配没有预定义特殊代码的字符集比如元音字母(a,e,i,o,u),怎么办?

很简单,你只需要在中括号里列出它们就行了,像[aeiou]就匹配任何一个元音字母[.?!]匹配标点符号(.或?或!)(英文语句通常只以这三个标点结束)。要注意的是,在中括号中,特殊代码不会被解释成其它意义,所以我们不需要写成[\.\?!](事实上这样写会出错,因为出现了两次\)。

我们也可以轻松地指定一个字符范围,像[0-9]代表的含意与\d就是完全一致的:一位数字,同理[a-z0-9A-Z]也完全等同于\w。

下面是一个更复杂的表达式:\(?0\d{2}[) -]?\d{8}

这个表达式可以匹配几种格式的电话号码,像(010)88886666,或022-22334455,或02912345678等。我们对它进行一些分析吧:首先是一个转义字符\(,它能出现0次或1次(?),然后是一个0,后面跟着2个数字({2}),然后是)-空格中的一个,它出现1次或不出现(?),最后是8个数字(\d{8})。不幸的是,它也能匹配010)12345678(022-87654321这样的“不正确”的格式。要解决这个问题,请在本教程的下面查找答案。

反义

有时需要查找不属于某个简单定义的字符类的字符。比如想查找除了数字以外,其它任意字符都行的情况,这时需要用到反义

表3.常用的反义代码
代码/语法 说明
\W 匹配任意不是字母和数字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符

例子:\S+代表不包含空白符的字符串

<a[^>]+>代表用尖括号括起来的以a开头的字符串

替换

好了,现在终于到了解决3位或4位区号问题的时间了。正则表达式里的替换指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。听不明白?没关系,看例子:

0\d{2}-\d{8}|0\d{3}-\d{7}这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)

\(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}这个表达式匹配3位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号间可以用连字号或空格间隔,也可以没有间隔。你可以试试用替换|把这个表达式扩展成也支持4位区号的。

\d{5}-\d{4}|\d{5}这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字,或者用连字号间隔的9位数字。之所以要给出这个例子是因为它能说明一个问题:使用替换时,顺序是很重要的。如果你把它改成\d{5}|\d{5}-\d{4}的话,那么就只会匹配5位的邮编(以及9位邮编的前5位)。原因是匹配替换时,将会从左到右地测试每个条件,如果满足了某个条件的话,就不会去管其它的替换条件了。

Windows98|Windows2000|WindosXP这个例子是为了告诉你替换不仅仅能用于两种规则,也能用于更多种规则。

分组

我们已经提到了怎么重复单个字符;但如果想要重复一个字符串又该怎么办?你可以用小括号来指定子表达式(也叫做分组),然后你就可以指定这个子表达式的重复次数了,你也可以对子表达式进行其它一些操作(教程后面会有介绍)。

(\d{1,3}\.){3}\d{1,3}是一个简单的IP地址匹配表达式。要理解这个表达式,请按下列顺序分析它:\d{1,3}代表1到3位的数字(\d{1,3}\.}{3}代表三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字(\d{1,3})。

不幸的是,它也将匹配256.300.888.999这种不可能存在的IP地址(IP地址中每个数字都不能大于255)。如果能使用算术比较的话,或许能简单地解决这个问题,但是正则表达式中并不提供关于数学的任何功能,所以只能使用冗长的分组,选择,字符类来描述一个正确的IP地址:((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

理解这个表达式的关键是理解2[0-4]\d|25[0-5]|[01]?\d\d?,这里我就不细说了,你自己应该能分析得出来它的意义。

后向引用

使用小括号指定一个子表达式后,匹配这个子表达式的文本可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:以分组的左括号为标志,从左向右,第一个分组的组号为1,第二个为2,以此类推。

后向引用用于重复搜索前面某个分组匹配的文本。例如,\1代表分组1匹配的文本。难以理解?请看示例:

\b(\w+)\b\s+\1\b可以用来匹配重复的单词,像go go, kitty kitty。首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字(\b(\w+)\b),然后是1个或几个空白符(\s+,最后是前面匹配的那个单词(\1)。

你也可以自己指定子表达式的组号或组名。要指定一个子表达式的组名,请使用这样的语法:(?<Word>\w+),这样就把\w+的组名指定为Word了。要反向引用这个分组捕获的内容,你可以使用\k<Word>,所以上一个例子也可以写成这样:\b(?<Word>\w+)\b\s*\k<Word>\b

使用小括号的时候,还有很多特定用途的语法。下面列出了最常用的一些:

表4.分组语法
捕获
(exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配exp,并捕获文本到名称为name的组里
(?:exp) 匹配exp,不捕获匹配的文本
位置指定
(?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
注释
(?#comment) 这种类型的组不对正则表达式的处理产生任何影响,只是为了提供让人阅读注释

我们已经讨论了前两种语法。第三个(?:exp)不会改变正则表达式的处理方式,只是这样的组匹配的内容不会像前两种那样被捕获到某个组里面

位置指定

接下来的四个用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们用于指定一个位置,就像\b,^,$那样,因此它们也被称为零宽断言。最好还是拿例子来说明吧:

(?=exp)也叫零宽先行断言,它匹配文本中的某些位置,这些位置的后面能匹配给定的后缀exp。比如\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如果在查找I'm singing while you're dancing.时,它会匹配singdanc

(?<=exp)也叫零宽后行断言,它匹配文本中的某些位置,这些位置的前面能给定的前缀匹配exp。比如(?<=\bre)\w+\b会匹配以re开头的单词的后半部分(除了re以外的部分),例如在查找reading a book时,它匹配ading

假如你想要给一个很长的数字中每三位间加一个逗号(当然是从右边加起了),你可以这样查找需要在前面和里面添加逗号的部分:((?<=\d)\d{3})*\b。请仔细分析这个表达式,它可能不像你第一眼看出来的那么简单。

下面这个例子同时使用了前缀和后缀:(?<=\s)\d+(?=\s)匹配以空白符间隔的数字(再次强调,不包括这些空白符)

负向位置指定

前面我们提到过怎么查找不是某个字符或不在某个字符类里的字符的方法(反义)。但是如果我们只是想要确保某个字符没有出现,但并不想去匹配它时怎么办?例如,如果我们想查找这样的单词--它里面出现了字母q,但是q后面跟的不是字母u,我们可以尝试这样:

\b\w*q[^u]\w*\b匹配包含后面不是字母u的字母q的单词。但是如果多做测试(或者你思维足够敏锐,直接就观察出来了),你会发现,如果q出现在单词的结尾的话,像Iraq,Benq,这个表达式就会出错。这是因为[^u]总是匹配一个字符,所以如果q是单词的最后一个字符的话,后面的[^u]将会匹配q后面的单词分隔符(可能是空格,或者是句号或其它的什么),后面的\w+\b将会匹配下一个单词,于是\b\w*q[^u]\w*\b就能匹配整个Iraq fighting负向位置指定能解决这样的问题,因为它只匹配一个位置,并不消费任何字符。现在,我们可以这样来解决这个问题:\b\w*q(?!u)\w*\b

零宽负向先行断言(?!exp),只会匹配后缀exp不存在的位置\d{3}(?!\d)匹配三位数字,而且这三位数字的后面不能是数字

同理,我们可以用(?<!exp),零宽负向后行断言来查找前缀exp不存在的位置(?<![a-z])\d{7}匹配前面不是小写字母的七位数字(实验时发现错误?注意你的“区分大小写”先项是否选中)。

一个更复杂的例子:(?<=<(\w+)>).*(?=<\/\1>)匹配不包含属性的简单HTML标签内里的内容(<?(\w+)>)指定了这样的前缀:被尖括号括起来的单词(比如可能是<b>),然后是.*(任意的字符串),最后是一个后缀(?=<\/\1>)。注意后缀里的\/,它用到了前面提过的字符转义;\1则是一个反向引用,引用的正是捕获的第一组,前面的(\w+)匹配的内容,这样如果前缀实际上是<b>的话,后缀就是</b>了。整个表达式匹配的是<b>和</b>之间的内容(再次提醒,不包括前缀和后缀本身)。

注释

小括号的另一种用途是能过语法(?#comment)来包含注释。要包含注释的话,最好是启用“忽略模式里的空白符”选项,这样在编写表达式时能任意的添加空格,Tab,换行,而实际使用时这些都将被忽略。启用这个选项后,在#后面到这一行结束的所有文本都将被当成注释忽略掉。例如,我们可以把上一个表达式写成这样:

      (?<=    # 查找前缀,但不包含它
      <(\w+)> # 查找尖括号括起来的字母或数字(标签)
      )       # 前缀结束
      .*      # 匹配任意文本
      (?=     # 查找后缀,但不包含它
      <\/\1>  # 查找尖括号括起来的内容:前面是一个"/",后面是先前捕获的标签
      )       # 后缀结束
    

贪婪与懒惰

当正则表达式中包含能接受重复的量词(指定数量的代码,例如*,{5,12}等)时,通常的行为是匹配尽可能多的字符。考虑这个表达式:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。

有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的量词都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:

a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aabab

表5.懒惰量词
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复

还有些什么东西没提到

我已经描述了构造正则表达式的大量元素,还有一些我没有提到的东西。下面是未提到的元素的列表,包含语法和简单的说明。你可以在网上找到更详细的参考资料来学习它们--当你需要用到它们的时候。如果你安装了MSDN Library,你也可以在里面找到关于.net下正则表达式详细的文档。

表6.尚未讨论的语法
\a 报警字符(打印它的效果是电脑嘀一声)
\b 通常是单词分界位置,但如果在字符类里使用代表退格
\t 制表符,Tab
\r 回车
\v 竖向制表符
\f 换页符
\n 换行符
\e Escape
\0nn ASCII代码中八进制代码为nn的字符
\xnn ASCII代码中十六进制代码为nn的字符
\unnnn Unicode代码中十六进制代码为nnnn的字符
\cN ASCII控制字符。比如\cC代表Ctrl+C
\A 字符串开头(类似^,但不受处理多行选项的影响)
\Z 字符串结尾或行尾(不受处理多行选项的影响)
\z 字符串结尾(类似$,但不受处理多行选项的影响)
\G 当前搜索的开头
\p{name} Unicode中命名为name的字符类,例如\p{IsGreek}
(?>exp) 贪婪子表达式
(?<x>-<y>exp) 平衡组
(?-<y>exp) 平衡组
(?im-nsx:exp) 在子表达式exp中改变处理选项
(?im-nsx) 为表达式后面的部分改变处理选项
(?(exp)yes|no) 把exp当作零宽正向先行断言,如果在这个位置能匹配,使用yes作为此组的表达式;否则使用no
(?(exp)yes) 同上,只是使用空表达式作为no
(?(name)yes|no) 如果命名为name的组捕获到了内容,使用yes作为表达式;否则使用no
(?(name)yes) 同上,只是使用空表达式作为no

 

posted @ 2012-01-04 16:25 Eric_jiang 阅读(320) | 评论 (0)编辑 收藏

1、缘由:我们在做项目中肯定都会遇到自定义业务异常 ,然后将业务异常信息跳转的统一的信息提示页面的情况,比如我们在struts的时候我们会用到struts的异常处理机制,我们在业务层会跑出我们遇到业务处理异常 ,然后交由struts处理将提示信息到一个页面进行显示,来提示用户的相关操作,这里我们会根据以上情景设计一下怎么来显示该功能。

2、解决方法:我们的业务异常通常都是抛出的,就是unchecked exception,所以最后总会到达调用该方法的最外层进行捕获,一般我们都会在action中调用我们的业务方法 ,而业务方法可能会跑出异常,此时我们就可以在此时做些文章了, 我们可以利用filter,来捕获我们抛出的异常,然后跳转到一个统一页面,进行信息提示了。

3、具体代码:

①自定义异常类,我想这个就不用多说了 ,大家都是会的:

BsException.java

 

 package com.ajun.exception; 
 
 
/**
 * 业务异常类
 * @author ajun
 * @http://blog.csdn.net/ajun_studio
 */ 
public class BsException extends RuntimeException { 
 
    //异常代码  
    private String key; 
     
    private Object[] values;//一些其他信息  
     
    public BsException() { 
        super(); 
    } 
 
    public BsException(String message, Throwable throwable) { 
        super(message, throwable); 
    } 
 
    public BsException(String message) { 
        super(message); 
    } 
 
    public BsException(Throwable throwable) { 
        super(throwable); 
    } 
     
    public BsException(String message,String key){ 
        super(message); 
        this.key = key; 
    } 
     
    public BsException(String message,String key,Object value){ 
        super(message); 
        this.key = key; 
        this.values = new Object[]{value}; 
    } 
     
    public BsException(String message,String key,Object[] values){ 
        super(message); 
        this.key = key; 
        this.values = values; 
    } 
 
    public String getKey() { 
        return key; 
    } 
 
    public Object[] getValues() { 
        return values; 
    } 

package com.ajun.exception;


/**
 * 业务异常类
 * @author ajun
 * @http://blog.csdn.net/ajun_studio
 */
public class BsException extends RuntimeException {

 //异常代码
 private String key;
 
 private Object[] values;//一些其他信息
 
 public BsException() {
  super();
 }

 public BsException(String message, Throwable throwable) {
  super(message, throwable);
 }

 public BsException(String message) {
  super(message);
 }

 public BsException(Throwable throwable) {
  super(throwable);
 }
 
 public BsException(String message,String key){
  super(message);
  this.key = key;
 }
 
 public BsException(String message,String key,Object value){
  super(message);
  this.key = key;
  this.values = new Object[]{value};
 }
 
 public BsException(String message,String key,Object[] values){
  super(message);
  this.key = key;
  this.values = values;
 }

 public String getKey() {
  return key;
 }

 public Object[] getValues() {
  return values;
 }
}
既然要用到filter ,自然少不了实现Filter接口,拦截你想要的请求,然后,就可以捕获异常了,此时你可以对你的chain.doFilter进行try catch,然后判断你想捕获的异常,很简单 ,请看代码:


 package com.ajun.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; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
import com.ajun.exception.BsException; 
 
/**
 * 业务异常过滤器
 * @author ajun
 * @http://blog.csdn.net/ajun_studio
 */ 
public class ExceptionFiler implements Filter { 
 
    private String errorPage;//跳转的错误信息页面  
     
     
    public void destroy() { 
         
    } 
 
    public void doFilter(ServletRequest req, ServletResponse res, 
            FilterChain chain) throws IOException, ServletException { 
 
         HttpServletResponse response = (HttpServletResponse) res; 
         HttpServletRequest request = (HttpServletRequest) req; 
         //捕获你抛出的业务异常  
         try { 
            chain.doFilter(req, res); 
        } catch (RuntimeException e) { 
            if(e instanceof BsException){//如果是你定义的业务异常  
                request.setAttribute("BsException", e);//存储业务异常信息类  
                request.getRequestDispatcher(errorPage).forward(request, response);//跳转到信息提示页面!!  
            } 
            e.printStackTrace(); 
        } 
    } 
       //初始化读取你配置的提示页面路径  
    public void init(FilterConfig config) throws ServletException { 
        //读取错误信息提示页面路径  
        errorPage = config.getInitParameter("errorPage"); 
        if(null==errorPage || "".equals(errorPage)){ 
            throw new RuntimeException("没有配置错误信息跳转页面,请再web.xml中进行配置\n<init-param>\n<param-name>errorPage</param-name>\n<param-value>/error.jsp</param-value>\n </init-param>\n路径可以是你自己设定的任何有效路径页面!!"); 
            //System.out.println("没有配置错误信息跳转页面");  
        } 
    } 
 

package com.ajun.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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ajun.exception.BsException;

/**
 * 业务异常过滤器
 * @author ajun
 * @http://blog.csdn.net/ajun_studio
 */
public class ExceptionFiler implements Filter {

 private String errorPage;//跳转的错误信息页面
 
 
 public void destroy() {
  
 }

 public void doFilter(ServletRequest req, ServletResponse res,
   FilterChain chain) throws IOException, ServletException {

   HttpServletResponse response = (HttpServletResponse) res;
      HttpServletRequest request = (HttpServletRequest) req;
      //捕获你抛出的业务异常
      try {
   chain.doFilter(req, res);
  } catch (RuntimeException e) {
   if(e instanceof BsException){//如果是你定义的业务异常
    request.setAttribute("BsException", e);//存储业务异常信息类
    request.getRequestDispatcher(errorPage).forward(request, response);//跳转到信息提示页面!!
   }
   e.printStackTrace();
  }
 }
       //初始化读取你配置的提示页面路径
 public void init(FilterConfig config) throws ServletException {
  //读取错误信息提示页面路径
  errorPage = config.getInitParameter("errorPage");
  if(null==errorPage || "".equals(errorPage)){
   throw new RuntimeException("没有配置错误信息跳转页面,请再web.xml中进行配置\n<init-param>\n<param-name>errorPage</param-name>\n<param-value>/error.jsp</param-value>\n </init-param>\n路径可以是你自己设定的任何有效路径页面!!");
   //System.out.println("没有配置错误信息跳转页面");
  }
 }

}

Filter在web.xml中的配置如下:


view plaincopy to clipboardprint?
<filter> 
    <filter-name>ExceptionFilter</filter-name> 
    <filter-class>com.ajun.filter.ExceptionFiler</filter-class> 
    <init-param> 
        <param-name>errorPage</param-name> 
        <param-value>/error.jsp</param-value> 
    </init-param> 
</filter> 
<filter-mapping> 
    <filter-name>ExceptionFilter</filter-name> 
    <url-pattern>*.do</url-pattern> 
</filter-mapping> 
 <filter>
  <filter-name>ExceptionFilter</filter-name>
  <filter-class>com.ajun.filter.ExceptionFiler</filter-class>
  <init-param>
      <param-name>errorPage</param-name>
      <param-value>/error.jsp</param-value>
     </init-param>
 </filter>
 <filter-mapping>
  <filter-name>ExceptionFilter</filter-name>
  <url-pattern>*.do</url-pattern>
 </filter-mapping>
下面写个servlet ,在请求的时候抛出你定义业务异常来试验一下吧


 package com.ajun.servlet; 
 
import java.io.IOException; 
import java.io.PrintWriter; 
 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
public class ExServlet extends HttpServlet { 
 
     
    public void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException { 
 
        this.doPost(request, response); 
         
    } 
 
     
    public void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException { 
 
        TestService t = new TestService(); 
        t.add();//模拟调用业务层方法,在此方法内抛出异常,此异常会在filter中进行捕获。  
         
    } 
 

package com.ajun.servlet;

import java.io.IOException;
import java.io.PrintWriter;

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

public class ExServlet extends HttpServlet {

 
 public void doGet(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {

  this.doPost(request, response);
  
 }

 
 public void doPost(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {

  TestService t = new TestService();
  t.add();//模拟调用业务层方法,在此方法内抛出异常,此异常会在filter中进行捕获。
  
 }

}
web.xml配置上述servlet


view plaincopy to clipboardprint?
<servlet> 
  <servlet-name>ExServlet</servlet-name> 
  <servlet-class>com.ajun.servlet.ExServlet</servlet-class> 
</servlet> 
 
<servlet-mapping> 
  <servlet-name>ExServlet</servlet-name> 
  <url-pattern>*.do</url-pattern> 
</servlet-mapping> 
  <servlet>
    <servlet-name>ExServlet</servlet-name>
    <servlet-class>com.ajun.servlet.ExServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ExServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
测试时在servlet中被调用的业务类

TestService.java


view plaincopy to clipboardprint?
package com.ajun.servlet; 
 
import com.ajun.exception.BsException; 
 
public class TestService { 
 
    public void add(){ 
         
        System.out.println("add () was called!!"); 
        if(true){ 
            throw new BsException("in add() throws exception!!");//抛出异常,根据你的业务逻辑  
        } 
    } 

package com.ajun.servlet;

import com.ajun.exception.BsException;

public class TestService {

 public void add(){
  
  System.out.println("add () was called!!");
  if(true){
   throw new BsException("in add() throws exception!!");//抛出异常,根据你的业务逻辑
  }
 }
}

现在部署项目,在你的浏览器内输入:http://localhost:8080/BsException/ajun.do

成功跳转到error.jsp:显示:in add() throws exception!!

在后台得到:


 com.ajun.exception.BsException: in add() throws exception!! 
    at com.ajun.servlet.TestService.add(TestService.java:11) 
    at com.ajun.servlet.ExServlet.doPost(ExServlet.java:26) 
    at com.ajun.servlet.ExServlet.doGet(ExServlet

posted @ 2011-12-29 18:20 Eric_jiang 阅读(4777) | 评论 (0)编辑 收藏

问题起因:
   今天遇到一个乱码问题,以前已经配置好了的呀。而且是普遍现象,看来是公共的变更引起的问题。
   
分析过程:

    于是开始进行调试,因为是公共问题,所以就对web.xml最近的变更进行增删调试,发现如果使用SecurityFilter就报错,去掉久正常了。
  仔细检查,发现如下现象:
   1、在设置字符集之前, 提前调用了request.getParameter()方法,就会出现问题。即使后来再设置字符集,随后的action接收的数据也会乱码。
    2、对于同一个url,如:*.do,filter-mapping 是有顺序的,按照web.xml中的配置顺序。

    从网上查到的结论:
   根据servlet2.3规范filter执行是按照web.xml配置的filter-mapping先后顺序进行执行,所以上面的配置会导致遇见*.do的url请求,先进行SecurityFilter的过滤器处理,这时候没有做编码处理,已经是乱码,到下面的filter处理时已经时乱码,再做编码处理已经没有用处。

解决办法:   
 错误的顺序:
    
     <filter-mapping>
         <filter-name>SecurityFilter</filter-name>
         <url-pattern>*.do</url-pattern>
     </filter-mapping>
 
     <filter-mapping>
         <filter-name>CharacterEncoding</filter-name>
         <url-pattern>*.do</url-pattern>
     </filter-mapping>
 
     <filter-mapping>
         <filter-name>CharacterEncoding</filter-name>
         <url-pattern>*.jsp</url-pattern>
     </filter-mapping>
 
 正确的顺序:
 
     <filter-mapping>
         <filter-name>CharacterEncoding</filter-name>
         <url-pattern>*.do</url-pattern>
     </filter-mapping>
 
     <filter-mapping>
         <filter-name>CharacterEncoding</filter-name>
         <url-pattern>*.jsp</url-pattern>
     </filter-mapping>
 
     <filter-mapping>
         <filter-name>SecurityFilter</filter-name>
         <url-pattern>*.do</url-pattern>
     </filter-mapping>

posted @ 2011-12-29 16:42 Eric_jiang 阅读(3172) | 评论 (2)编辑 收藏

仅列出标题
共57页: First 上一页 32 33 34 35 36 37 38 39 40 下一页 Last