飞天老鼠

Wicket系列(1)--从一个简单的例子看wicket

Wicket是一个组件化的Web框架,Java社区里面,轮子特别多,都有点泛滥成灾的感觉了。不过Wicket作为apache的顶级项目,必有它的过人之处。其官方的列表中给出了如下的Feature:

Swing-like OO Component Model
Ease of Development
Separation of Concerns
Secure
Transparent, Scalable Clustering Support
Transparent Back Button Support
Reusable Components
Simple, Flexible, Localizable Form Validation
Typesafe Sessions
Factory Customizable
Detachable Models
Border Components
Support for All Basic HTML Features
Programmatic Manipulation of Attributes
Automatic Conversions
Dynamic Images
Pageable ListView
Tree Component
Localization
Examples

详细的描述请参见Wicket的官方介绍

可惜的是Wicket的关注度并不是很高,很多资料是很久以前的内容了,仅有部分参考价值。那么今天就从一个简单的例子,看一下开发Wicket应用是一个怎么样的过程以及Wicket本身的一些特点。单从一个例子不能看到全部,只能给人一个初步的印象,将在以后的系列中详细讲解一下wicket。Wicket在写本文时的最新稳定版是1.4.10,1.5的现在正在开发中,最新版为1.5-M1,本系列使用当前最新的稳定版1.4.10。我们使用Maven来做build工具(为的就是方便嘛,不用先下载一堆东西了)。

首先创建一个maven的project,使用如下命令:

mvn archetype:create -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=1.4.10 -DgroupId=com.mycompany -DartifactId=myproject

具体信息,可以根据自己需要修改。创建完后,发现wicket的依赖很简单,只依赖了slf4j与log4j的jar包,完全没有apache commons那些东西。

我们的Wicket应用至少需要一个Wicket Application:

package com.mycompany;

import org.apache.wicket.Page;
import org.apache.wicket.protocol.http.WebApplication;

public class SampleApplication extends WebApplication {

	@Override
	public Class<? extends Page> getHomePage() {
		return Index.class;
	}

}

SampleApplication .java

Wicket的WebApplication比Java EE定义的Web应用的粒度更小,一个War包中可以对应多个Wicket的WebApplication(与传说中的CAR包有几分相似)。getHomePage方法指定了首页,一个类对应一个页面,所以Index.class就能表示一个页面资源。根据下面index页面的实现代码,就更能体会这一个类是如何对应到一个页面的。

 

package com.mycompany;

import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.link.Link;

public class Index extends WebPage {
	public Index(){
		add(new Link<String>("lnk1"){
			@Override
			public void onClick() {
				 setResponsePage(FormSample.class);
			}
			
		});
	}
}

Index.java

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Wicket Sample</title>
</head>
<body>
    <a wicket:id="lnk1">Go to Form Sample</a>
</body>
</html>

Index.html

这两个文件就是作为首页需要的全部内容,默认配置下,这两个文件需要在同一个package内。html内的wicket:id="lnk1与java代码内的new Link<String>("lnk1")相对应,所有带wicket:id属性的标签,全部会被服务器端组件生成的内容替换。这里我们看到,java端有个onClick方法,这表示我们的link支持服务器端事件,点击后服务器端会执行onClick方法内的内容,重定向到FormSample页面。

接下来,我们再来看一下FormSample这页面,这个页面实现最简单的表单提交功能,在一个文件框内输入文字后提交,服务器端会把刚才输入的文字在一个span内打出来。

package com.mycompany;

import org.apache.wicket.IClusterable;

public class FormInputModel implements IClusterable {
	private static final long serialVersionUID = 5201088805280471789L;
	private String inputString;

	private String info;

	public String getInputString() {
		return inputString;
	}

	public void setInputString(String inputString) {
		this.inputString = inputString;
	}

	public void setInfo(String info) {
		this.info = info;
	}

	public String getInfo() {
		return info;
	}

}

FormInputModel.java

package com.mycompany;

import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.Model;

public class FormSample extends WebPage {

	public FormSample() {
		add(new InputForm("form1"));
	}

	public static class InputForm extends Form<FormInputModel> {

		public InputForm(String id) {
			super(id, new CompoundPropertyModel<FormInputModel>(new FormInputModel()));
			add(new TextField<String>("inputString").setRequired(true).setLabel(new Model<String>()));
			add(new Label("info"));
			add(new Button("saveButton"));
		}

		@Override
		public void onSubmit() {
			FormInputModel model = (FormInputModel) getDefaultModelObject();
			model.setInfo(model.getInputString());
		}

	}
}

FormSample.java

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Wicket Examples - helloworld</title>
    <link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
    <form wicket:id="form1">
    	<input wicket:id="inputString" type="text" />
    	<br />
    	<span wicket:id="info"></span>
    	<br />
    	<input wicket:id="saveButton" type="submit" value="submit" />
    </form>
</body>
</html>

FormSample.html

这里的Form需要一个Model,具体与Form里的字段对应,在这个Form里面,有inputString,info共两个字段,所以我们的model也是这么简单的一个Bean。Form提交的时候,同样也是服务器端事件:由onSubmit这个方法来处理。处理也很简单,只需要修改一个Model的值。

最近,怎么把这些代码组成一个Wicket应用呢?看一下web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
	version="2.4">

	<display-name>Wicket Examples</display-name>
	<filter>
		<filter-name>WicketExampleApplication</filter-name>
		<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
		<init-param>
			<param-name>applicationClassName</param-name>
			<param-value>com.mycompany.SampleApplication</param-value>
		</init-param>
	</filter>

	<filter-mapping>
		<filter-name>WicketExampleApplication</filter-name>
		<url-pattern>/examples/*</url-pattern>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>INCLUDE</dispatcher>
	</filter-mapping>

	<session-config>
		<session-timeout>5</session-timeout>
	</session-config>

	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>

</web-app>

 

一个Wicket的WebApplication有一个Filter来处理,如果有多个就可以配置多个。这里其实也可以有用Servlet,用Filter可以实现更强大的功能。

最后,整个project是如下的一个目录结构:

myproject
│  pom.xml
│
├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─mycompany
│  │  │              FormInputModel.java
│  │  │              FormSample.html
│  │  │              FormSample.java
│  │  │              Index.html
│  │  │              Index.java
│  │  │              SampleApplication.java
│  │  │
│  │  ├─resources
│  │  └─webapp
│  │      └─WEB-INF
│  │              web.xml
│  │
│  └─test
│      ├─java
│      └─resources
└─target

总结一下:

1.Wicket的编程模型与Swing比较相似,开发与理解都还比较简单。

2.Wicket的组件化框架对前端友好,不需要做特别的学习就能掌握。

3.Wicket的页面都是

4.Wicket的事件必须Override父类的方法来实现,不支持类似于EventListener的方式,会产生大量的内部类,导致代码结构不易维护。

5.Wicket里面每个组件都必需要有一个Model,Model的结构必须与组件的结构相匹配,这里其实,不够面向对象,要定义一个Model,或多或少都要了解一些组件的内部实现。单从编码的角度来说,也更容易出错。

下期将讲解一些常用组件的使用。

posted on 2010-08-28 22:47  飞天老鼠  阅读(3087)  评论(0编辑  收藏  举报

导航