2008年10月31日星期五

JSON解析之JSONObject对象---js对象转换成java对象

以前用过一段时间的JSON,非常简单,而且觉得2期的学员在学习了jsp的基础之后,都能应用自如.所以觉得有必要说一说它的使用方法.整个json框架以及其工具库的内容还是教多的,饭要一口一口吃,我们先从简单的基础讲起,让大家明白json究竟是什么,为什么要学习使用它,以及掌握它以后在开发过程中都能获得哪些便利.下面,我们即将开始.

要求基础:《使用jsp开发Web应用系统》(s2学期 / y2学期)

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它是大家熟悉的javascript客户端脚本的一个子集。JSON采用完全独立于语言的文本格式,它是一款非常理想的数据交换语言。其中文网站是http://www.json.org/json-zh.html,详细阐述了JSON的概念和数据格式等等,大家如果感兴趣的话可以去浏览一下。

在简要的概述了JSON是什么之后,相信大家也有了一个初步的印象。那么我们下面以一个简单的示例来了解一下JSON如何使用。今天我们示例的主角是JSON基于java的库包-json-lib.jar中的JSONObject对象,我们今天的例子也就是把javascript对象内的数据透明的绑定到简单的java值对象上。

我们还是依旧以实例为导向,这样理解起来非常容易。我们今天就以一个简单的注册页面(不带数据库,大家可以自己在练习中使用数据库)来贯穿我们今天的内容。(要准备的jar包为json-lib-2.2.2-jdk15.jar,commons-beanutils-1.8.0.jar,commons-collections-3.2.1.jar,commons-lang-2.4.jar,commons-logging-1.1.1.jar,可以去网上下载,也可以找我索取)

首先我们建立一个简单的jsp注册页面,代码片断如下:


<form name="frm" action="convertJava.jsp" method="post">
请输入姓名:<input name="username"><br>
请输入密码:<input type="password" name="password" ><br>
请选择你的性别: <input type="radio" name="sex" value="男" >男

<input type="radio" name="sex" value="女"> 女

请选择爱好:<input type="checkbox" name="love" value="java"> java
<input type="checkbox" name="love" value=".net">.net
<input type="checkbox" name="love" value="php">php
<input type="checkbox" name="love" value="vb">vb<br>
<input type="hidden" name="str" value="" />
<input type="button" value="注册" onclick="run()"/>
</form>

这是我们最常见的表单了,但是这里要注意的是大家在设置表单元素的name属性的时候,要确保和以后你新建的java值对象的属性名相同。

也许大家注意到了,最后注册的按钮控件上有个点击事件--run,run这个函数比较重要,我们主要是用这个函数来把这个表单描述为JSON格式的文本。那么下面我们就来看看run函数的代码片段:

function run()
{

var str="{'username':'"+document.frm.username.value+"','password':'"+document.frm.password.value+"','sex':'";
var radios=document.getElementsByName("sex");
var radiovalue="";
for(i=0;i<radios.length;i++)
{
if(radios[i].checked==true)
radiovalue=radios[i].value;
}
str+=radiovalue+"','love':[";
var arraytemp=document.getElementsByName("love");
for(i=0;i {
if(arraytemp[i].checked==false)
continue;
if(arraytemp[i].value=="")
continue;
if(i+1==arraytemp.length&&arraytemp[i].checked==true)
{
str+="'"+arraytemp[i].value+"']";
break;
}
str+="'"+arraytemp[i].value+"',";
}
if(str.substring(str.length-1,str.length)==",")
{
str=str.substring(0,str.length-1)+"]";

}
str+="}";
document.frm.str.value=str;
document.frm.submit();
}


这里卖个关子,具体JSON文本格式是怎样的,请大家把以上的代码片段拼起来,在run方法里加上alert(str),就可以在执行run后弹出的对话框中看到JSON文本的格式了。很简单的,如果想完美点,还可以写一个js方法做一下验证。

我们这段run方法的目的也就是为了把表单元素的name属性以及内部包含的值以key=value的键值对的形式描述为一段JSON文本。

紧接着,我们来创建一个简单的java值对象,代码示例为:

package entity;

public class formBean {
private String username;
private String password;
private String sex;
private String[] love;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String[] getLove() {
return love;
}
public void setLove(String[] love) {
this.love = love;
}
}




有了JSON文本和需要绑定的java值对象后,那么我们下一步就是要编写另一个jsp页面convertJava.jsp(当然,你也可以使用servlet),用来把这段文本转换成java对象了。

另一页面,如: 代码片段如下:

request.setCharacterEncoding("GBK");
String jsobject = request.getParameter("str");// 这个是jsp页面传过来的对象字符串
JSONObject js = JSONObject.fromObject(jsobject);// 根据字符串转换对象
formBean bean = (formBean) js.toBean(js, formBean.class); // 把值绑定成相应的值对象
// 下面输出bean的值
response.setCharacterEncoding("GBK");
response.setContentType("text/html;charset=gbk");
out.println(bean.getUsername());
out.println(bean.getPassword());
out.println(bean.getSex());
out.println("bean的love属性为一个数组:");
for (String s : bean.getLove()) {
out.println("bean的数组元素:" + s );
}


通过上面的代码片段,可以了解到JSONObject有用的方法是fromObject(JSON文本)[用于讲JSON文本创建一个JSONObject实例]和toBean(带有JSON文本的JSONObject对象,你要绑定的java值对象类型.class)[用于把JSON文本转换成java对象]

至此,你就可以利用这个简单的java值对象了,不再用request的getParameter方法一一获取参数值,然后再使用java值对象的setter方法一一设置属性值这么麻烦了。也许刚开始构造JSON对象文本的时候有一些麻烦,但是这些麻烦对于你来说不过是小菜一碟,对吗?要记住,JSON框架的用法不仅仅于次,这只是冰山一角而已,我们陆续会窥探到其内部。希望大家看完此篇文章后回去做练习,掌握今天的内容,我们下一次再继续学习它的其他部分。

2008年10月30日星期四

使用struts动态验证框架详细步骤分解(理论部分)


上次课讲解了struts的动态验证框架,并给同学们做了演示,今天正好有时间把它在这里再次讲解一遍,加深同学们的印象。对此还不太熟悉的同学们,可以按照以下的详细步骤分解彻底掌握。


要求基础:struts课程(2年)


准备工作:新建一个web工程,并且添加struts1.3支持。

为了添加struts的动态验证框架validator的支持,我们首先打开struts的配置文件struts-config.xml,添加一个插件。





是的,利用plug in 标签填加验证框架支持,我们按照图中所绘来配置struts-config文件,注意顺序,plug in标签一定放在最后的位置,否则出错。

在这里,向大家介绍一下配置的各项参数的意思,首先className属性是插件的实现类,主要是用来提供增加的插件功能的,我们也可以自己来编写struts的插件。pathnames是这个插件的配置属性,它的值就是动态验证框架需要的配置文件的位置。一共需要2个配置文件,一个是验证框架需要的验证规则文件,这个不需要你来编写,struts1.3为我们提供。另一个是我们针对ActionForm来编写的验证文件,主要是描述哪些属性需要验证,需要哪些验证等等。这个是需要我们来编写的,也就是说,按照上图的配置,你需要在你的WEB-INF下新建一个validation.xml文件。

我们暂时抛开新建的validation.xml不谈,先来新建一个ActionForm和配套的Action。要建立的ActionForm不要再继承org.apache.struts.action.ActionForm,而是继承org.apache.struts.validator.ValidatorForm或者org.apache.struts.validator.ValidatorActionForm.
如果你要使用动态ActionForm,那么就继承org.apache.struts.validator.DynaValidatorForm或者org.apache.struts.validator.DynaValidatorActionForm.最后建立一个Action,跟往常一样没任何变化.这里需要提示一点,ActionForm的validate方法依然可以重写,跟往常一样.

接下来,我们主要是围绕我们创建ActionForm时创建的表单jsp,我们刚才暂搁的validation.xml和资源文件来做工作.

我们首先打开我们加进来的struts-core-1.3.8.jar,看它的结构,找到如下画面,打开其中的validator-rules.xml,这是验证规则文件,我们需要拷贝一些默认的错误信息资源.



把文件内的错误消息拷贝到你的资源文件里:




我们可以看到里面有{0}这样的占位符,这个是我们可以添进去的补充消息.
好了,那么接下来我们要开始编写validation.xml文件了(这个可以拷贝我提供给你们的摸版,或者你们可以直接拷贝struts的空白工程里相应的文件),例子:




这里解释一下各参数的意思,form标签就是你的ActionForm的配置,由于你的工程很可能有多个ActionForm,那么在此验证文件里,你需要以form标签来分隔它们的配置.那么form标签里的name属性顾名思义就是你的form名称,这个和你在struts-config.xml里注册ActionForm的名字是一样的.field,就是你的ActionForm的属性,property是你的属性名字,depends是你要启用的验证规则,这个可以参考validator-rules.xml文件,当然,你也可以实现你自己的规则.在这里我启用的是required非空规则.最后的arg标签,这个是什么呢?我们可以看到刚才我们拷贝到资源文件里的错误消息有这么一条:



那么我们既然刚才启用了required非空验证,那么这里的arg标签实际上就是配置这个{0}占位符的内容. arg标签里面的key属性对应资源文件里的内容.可以看到例子里有个key为dyncForm.username的非空验证属性的配置.那么在我资源文件里一定有一个dyncForm.username=username 这样的key=value值对.如果出现错误,那么提示的错误消息就是username is required.

最后,我们来看一下我们创建的表单jsp,我们还需要在这里配置一些参数以使用动态验证框架提供的客户端验证生成的脚本.

具体配置看下面的例子:




这里解释一下这里的配置,由于我们要生成客户端验证脚本,所以要导入struts的html标签,因为我们要使用生成脚本.那么生成的脚本如何使用呢?这里要配置,这里要注意return函数的名字,validate是固定的,后面是你的ActionForm的名字,注意,第一个字母要大写.


那么一切工作就绪,我们来测试一下,如果什么都不填,那么点提交的时候,会弹出对话框,并且提交失败:



好了,以上是我们了解如何使用struts的动态验证框架的全部内容,那么下次呢,我会针对各种不同的验证规则,提供validation.xml的配置举例,另外还会提供其他的配置参数详解.针对这次的课程,如果有同学有不理解的地方,可以找我.希望看过这篇文章的同学回家做相关的练习,你们练习的结果发我邮箱,问题也可以发我邮箱,再次提醒我邮箱的地址yangaccp@gmail.com,邮件的主题按照我们之前定义的规则施行.



2008年10月27日星期一

一步一步了解如何使用struts1.3上传文件

今天下午休息,时间富裕很多,有空静下心来写点东西.这也是本博客第一篇技术类的文章.呵呵,我为什么要写这个题目呢?因为有学员强烈要求这方面的内容,正好明天要讲,那么今天这篇文章就算他们明天课后可以参考的笔记吧.


struts1.3相信大家都不陌生了,虽然已经出来许久了,但是因为它简单,用的人比较多,所以生命力依旧非常顽强,最重要的是它能完成你大部分的需求,而且用它来开发web应用确实可以获得很好的体验,所以,讨论它还是十分必要的.我这篇文章针对群体是我的学生,所以,难免写的罗嗦,大牛们可以闪开休息.



需要的基础:struts课程(2年)


首先,你需要有一个struts1.3的工程.我们在struts的配置文件struts-config.xml里新建三合一(我在班里说的俗语),看下面:


那么,接下来我们来设置一下ActionForm:



也许图片有点小,但请注意,我这里设置了一个file属性,用来保存文件的,那么我们要选择jsp input type下拉框中的file.

接下来,我们切换到jsp选项卡上,选择create JSP form,用来创建jsp页面.然后一路next下去直到完成.

当这一切操作都完成后,我们首先来看一下我们生成的jsp页面,注意,为了上传文件,我们需要这样改写:<html:form action="/你的action地址" enctype="multipart/form-data">

好了,接下来,我们再看看生成的ActionForm的源代码...我们发现,这里我们设置为文件类型的属性file,依然还是String类型的.这是不行的,我们需要改写它的类型,把它改写成为FormFile类型的,这个FormFile类需要导入org.apache.struts.upload.FormFile,希望视力不好的同学仔细些.

完成这部分的操作后,基本上接下来我们就要考虑如何来处理这个上传的文件了.我们首先要决定要把它放在哪里,然后还要考虑你是否要限制它的大小,因为你的硬盘不是无限大的.


为了简单起见,我这里在这里仅做个示范,我就直接在Action里面写文件处理了,通过这个过程,你可以学习到struts1.3专门为我们准备的用于上传的文件表单类的一些实用方法.以下是在Action的execute方法内的代码:



//这就是我们的ActionForm
MyUpForm myUpForm = (MyUpForm) form;
//获得struts文件类(这是我们ActionForm的一个属性)
FormFile file=myUpForm.getFile();
//获得上传的文件名
String filename=file.getFileName();
//获取输入流(因为我们要使用byte数组来保存文件数据,好写回到硬盘上,所以这里要先获取输入流把数据保存到byte数组里,这个输入流中已经保存有上传文件的数据了.)
InputStream inputStream=file.getInputStream();
//我们新建一个byte数组,数组的长度为文件的大小.新建它的目的就是为了保存上传文件的数据.
byte[] imageData=new byte[file.getFileSize()];
//我们把输入流中的上传文件数据保存到我们的byte数组中
inputStream.read(imageData);
//注意,操作完输入流需要关闭.
inputStream.close();
//为了写回到硬盘上,需要新建一个输出流
FileOutputStream outputStream=new FileOutputStream(new File("你要保存的具体位置"+filename));
//我们根据已经保存上传文件数据的byte数组写回你保存的具体位置上.
outputStream.write(imageData);
//最后,操作完输出流,一样要进行关闭操作.
outputStream.close();
//好了,你现在就可以去看看文件是否上传成功了,是不是很简单呢?简简单单就把上传文件给搞定了.很好玩吧.


希望看我这篇文章的同学能认认真真的回去自己试着做一次,有什么问题再问我,最后罗嗦一句,设置好编码格式,才能避免中文的文件上传后变成乱码.










2008年10月19日星期日

开业大吉

今天终于下定决心开了这个blog.很早以前就想开了,只是一直懒.想表达的太多,但留下的却几乎没有.所以,从今天开始,我要把想说的,想做的,想分享的,统统得在这里体现.虽然时间和精力有限,但我也会坚持下去.