- 浏览: 639721 次
- 性别:
- 来自: 北京
最新评论
-
2047699523:
java hibernate demo使用实例教程源代码下载: ...
hibernate延迟加载的原理与实现 -
在世界的中心呼喚愛:
hantsy 写道这种lazy的解释只对了一半,按java p ...
hibernate延迟加载的原理与实现 -
moguicy:
看了下时间,不是楼主是否还在开发
【翻译】Wicket启示录——理论与实践(一) -
xfan0828:
"最后但并不是最不重要的一点就是" BZ, ...
【翻译】深入浅出 EJB3.1(上) -
doudou87323:
十分感谢,正在学习中,受益匪浅
【翻译】深入浅出 EJB3.1(上)
第二部分 实践
Application(应用程序)
与以往大多数web应用程序框架不同,Wicket不使用XML来进行配置,只需要在web.xml做少许必须的配置。所有的配置都在Application的子类中进行。(Jetty的Fans自然对这种编程式的配置欣喜若狂)。Application class配置了你程序的方方面面,包括应用程序的主页(home page)以及错误处理(error handling).
简要的了解了Wicket核心概念后,我们可以开始创建Wicket应用程序了。
你的第一个Wicket
按照惯例,介绍一个新的框架或语言时,都会提供一个“Hello World”程序。我准备打破这种惯例,直切主题——一个简单的通讯录程序。我们的例子只有几个页面,但通过这几个页面也足够让你理解Wicket了。
当你在创建web应用程序的web这一环节时,通常会从最简单的markup文件入手,然后由Service来实现功能.这也正是我们今天要讲的开发方式,先来看一些需要用到的页面:
对于这个应用程序,我们实现了三个页面。第一个页面显示的是我们数据库里的联系人列表,并且也作为本程序的主页,此外它还提供了“查看”和“编辑”功能。每个页面都是不同的,但是还有很多方面是可以彼此共享的,稍后我会利用这一点来创建我们的Wicket应用程序。
l 每个页面都可以共享相同的CSS样式和头文件。我们就是利用markup的承继来实现的。
l 每页都有一个查找模块,并且该模块完美的封装成一个可复用的Panel组件。我们本可以简单的将查找组件放在base页面上,(原因就是上面说到的markup承继的子页面将共享父组件),但这样做显然违背了我要表达的目的。
现在我们有了一些页面以及实现其功能的想法,现在我们就来看看Wicket的Quickstart中的应用程序实例。(该实例用到了Maven,连接地址为:http://wicket.apache.org/quickstart.html)
(通过下图)应用程序框架模板已经为我们搭好了,我们只要从WicketAppliation类开始。
我给WicketApplication类加了三个方法(注意:不包括getHomePage与init方法)。前两个是为持久化操作提供了相应的ContactDao。第三个方法复写了Application的get()方法达到类型转换的目的,在这里我们要返回的是WicketApplication类。在这个例子中,WicketApplication使用了Service Locator模式(参见http://java.sun.com/blueprints/patterns/ServiceLocator.html)。当然有很多方法可以得到你的DAO和Seriver层,比如说使用Spring Annotation或Guice。最后,我将HomePage类的home page指向了一个不存在的ListContacts类。
public class WicketApplication extends WebApplication {
public Class getHomePage() {
return ListContacts.class;
}
private ApplicationContext getContext() {
return WebApplicationContextUtils
.getRequiredWebApplicationContext(getServletContext());
}
public ContactDao getContactDao() {
return (ContactDao) getContext().getBean("jdbcContactDao");
}
public static WicketApplication get() {
return (WicketApplication) WebApplication.get();
}
}
接下来我们需要建立一个base类来为作该应用程序页面的父类,该类利用了上文提到的markup继承。下面是相应代码,markup稍后给出:
public class BasePage extends WebPage {
public BasePage() {
add(new StyleSheetReference("stylesheet",
BasePage.class, "styles.css"));
}
}
我们的BasePage继承了WebPage类,它可以用来设置页面的markup类型,并且默认值为“text/html”。如果我们要返回的是XML而不是HTML的话,在子类中将getMarkupType()方法复写如下:
public String getMarkupType() {
return "text/xml";
}
通常来说,你在getMarkupType()里的markup类型设置,决定了相应扩展名的文件被加载进来。在我们的例子中,BasePage会去查找BasePage.html。默认情况下,这些markup文件(也就是*.html,*.xml,*.xslt等文件)与组件放在相同的文件下(这一点与我们常用的Webwork,Struts,Spring MVC不同),但是如果需要的话,也是很容易去重新配置的。
BasePage的构造函数引用了一个StyleSheetReference类,并该类插入了相应的CSS样式与页面上的<link wicket:id="stylesheet"/>对应起来。为什么不直接将CSS样式文件放在web根目录下,而“多此一举”的使用StyleSheetReference呢?假设一下你的应用程序想做到“本地化”,需要为用户显现不同的图片或样式,这个时候可能你就得有两套样式:styles_en.css和styles_fr.css。而StyleSheetReference会自动的帮你加载“本地化”文件。同样,Wicket在对待资源文件(比如说properties和image文件)如出一辙,非常方便。
BasePage.html相当简单:
<html>
<head>
<title>Introduction to Apache Wicket - Example Application</title>
<link wicket:id="stylesheet"/>
</head>
<body>
<h1>
My Contacts
</h1>
<form id="search-form">
<table>
<tr>
<td>Search</td>
<td><input type="text" name="search"/></td>
<td><input type="submit" value="Go" class="button"></td>
<td><a href="#">Add New Contact</a></td>
</tr>
</table>
</form>
<wicket:child/>
</body>
</html>
在上面的这个HTML 文件里,可能有两样东西引起了你的注意。首先在<link>元素里,多了一个wicket:id=”stylesheet”的属性。它来自于BasePage类所引用的StyleSheetReference。记住,Java代码的组件ID必须与页面上的ID一一对应。
其次,你还发现多了<wicket:child/>这么个东西。它的意思是当解释器看到<wicket:child/>标签时,会将继承该页面的子类显示出来。当运行到ViewContact页面时,你就会看到效果了。我们下一个目标就是建立一个可复用的查找表单模块,并将其放在BasePage中。
提到组件,Wicket有两类最基本的组件:带有markup的和不带markup的。刚才看到的Page就属于带markup文件的容器。现在我要谈的是Panel,它与Page不同,Panel如果不包含在一个Page里面的话,是无法独立存在的。尽管如此,Panels与Pages还是有很多共性的:都有自己的markup文件,都可以利用markup的继承特性。现在我们就来创建一个带有表单form的panel.
首先,我们建立好自己的Panel类:
public class SearchPanel extends Panel {
public SearchPanel(String id) {
super(id);
add(new SearchForm("searchForm"));
}
private class SearchForm extends Form {
private String searchString;
public SearchForm(String id) {
super(id);
add(new TextField("searchString",
new PropertyModel(this, "searchString")));
add(new BookmarkablePageLink("addContact",
EditContact.class));
}
public void onSubmit() {
PageParameters params = new PageParameters();
params.add("searchString", getSearchString());
setResponsePage(ListContacts.class, params);
}
public String getSearchString() {
return searchString;
}
public void setSearchString(String searchString) {
this.searchString = searchString;
}
}
}
这是到目前为止最长的代码段了,我们慢慢看。首先,是构造函数:
public SearchPanel(String id) {
super(id);
add(new SearchForm("searchForm"));
}
我们的SeachPanel继承自Panel,因此必须调用父类的构造函数来传递当前的组件ID。切记Panels无法独自使用,我们必须将其加入到一个Pages中去,因此我们需要在使用它的Page中markup一下SeachPanel (后面的代码将会看到)。
在调完super(id)函数后,SearchPanel将我们实现的一个SearchForm(在这里,我们的SearchForm是私有内部类)加入到里面。请看下面代码:
private class SearchForm extends Form {
private String searchString;
public SearchForm(String id) {
super(id);
add(new TextField("searchString",
new PropertyModel(this, "searchString")));
add(new BookmarkablePageLink("addContact",
EditContact.class));
setMarkupId("search-form");
}
public void onSubmit() {
PageParameters params = new PageParameters();
params.add("q", getSearchString());
setResponsePage(ListContacts.class, params);
}
public String getSearchString() {
return searchString;
}
public void setSearchString(String searchString) {
this.searchString = searchString;
}
}
SearchForm继承自Wicket的Form组件。Form组件可以包含其它组件,比如说TextFields, TextAreas 或 DropDownChoices等。尽管如此,Form并不局限于上述几种组件,你也可以像将Panel加到Page那样,也将一个Panel加到Form里去。
在上面的Form对象中,我加了一个组件ID为”searchString”的TextField组件,应该组件使用了PropertyModel来更新form的searchString属性.
add(new TextField("searchString", new PropertyModel(this, "searchString")))
当form提交后,TextField会自动将用户输入的值更新在form的searchString属性上.PropertyModel并不局限于更新form对象的属性,还可以更新Pojo或其它模型的属性.稍后的例子中,我们将会关于PropertyModel的更多细节.
除添加完TextField后,我还将一个跳转到EditContact类的link(超链接)也加到panel上.该link是一个BookmarkablePageLinks类,它是无状态的,这就意味着它并不需要去知道用户先前的请求是什么,来自于何方.
当所有的组件都在form上添加完后,还得告诉form当点提交按钮后要做什么操作.Wicket的form有一个默认的提交监听器,也就是说当你只有一个提交按钮的话,还是很管用的.
public void onSubmit() {
PageParameters params = new PageParameters();
params.add("q", getSearchString());
setResponsePage(ListContacts.class, params);
}
当form上所有的组件都验证通过并且模型对象更新完后,onSubmit() 方法的监听器就会被调用了.在上面的实现代码里,form提交后,searchString属性被装在PageParameters类里,PageParameters负责将存在里面的值封装成URL的query参数.最后,再调用setResponsePage(Class, PageParameters)方法,在这里我们把ListContacts作为请求后的响应Action.
SearchPanel建好后,我们看看与之相应的markup文件:
<wicket:panel>
<form wicket:id="searchForm">
<table>
<tr>
<td>Search</td>
<td>
<input wicket:id="searchString" type="text" name="search"/>
</td>
<td><input type="submit" value="Go" class="button"></td>
<td><a wicket:id="addContact" href="#">Add New Contact</a></td>
</tr>
</table>
</form>
</wicket:panel>
panel markup文件非常简洁并且与SearchPanel的结构是一致的.在它上面的form组件又有TextField和BookmarkablePageLink组件,而对于submit组件,我们不需要专门使用Wicket的submit,因为这里只有一个submit组件,我们使用了上文提到的默认监听器和onSubmit()方法.
接下来,我们需要更新一下BasePage类,将我们设计好的SearchPanel加入进去.(注意:Panel是不能单独使用的.)
public BasePage() { add(new StyleSheetReference("stylesheet",BasePage.class, "styles.css")); add(new SearchPanel("searchPanel"));
}
同样,BasePage的markup文件也需要更新一下:
<html>
<head>
<title>Introduction to Apache Wicket - Example Application</title>
<link wicket:id="stylesheet"/>
</head>
<body>
<h1>
My Contacts
</h1>
<span wicket:id="searchPanel"></span>
<wicket:child/>
</body>
</html>
除使用StyleSheetReference类外,我们还可以使用Wicket的HeaderContributor类或<wicket:link>元素.下面,我们来创建ListContacts页面,当然先从其Java类开始:
public class ListContacts extends BasePage {
public ListContacts(PageParameters params) {
final String searchString = params.getString("searchString");
IModel contactsModel = new LoadableDetachableModel() {
protected Object load() {
ContactDao dao = WicketApplication.get().getContactDao();
return dao.find(searchString);
}
};
ListView contacts = new ListView("contacts", contactsModel) {
protected void populateItem(ListItem item) {
Link view = new Link("view", item.getModel()) {
public void onClick() {
Contact c = (Contact) getModelObject();
setResponsePage(new ViewContact(c.getId()));
}
};
view.add(new Label("firstName",
new PropertyModel(item.getModel(), "firstName")));
view.add(new Label("lastName",
new PropertyModel(item.getModel(), "lastName")));
item.add(view);
item.add(new SmartLinkLabel("email",
new PropertyModel(item.getModel(), "email")));
item.add(new Link("edit", item.getModel()) {
public void onClick() {
Contact c = (Contact) getModelObject();
setResponsePage(new EditContact(c.getId()));
}
});
item.add(new Link("delete", item.getModel()) {
public void onClick() {
Contact c = (Contact) getModelObject();
WicketApplication.get().getContactDao().delete(c.getId());
setResponsePage(ListContacts.class);
}
});
}
};
add(contacts);
}
}
ListContacts实质就是一个ListView,它的markup文件包括了ListView组件的ID,它的作用就是将模型数据在markup文件上进行迭代输出.请看下面代码:
<div wicket:id="contacts" class="contact">
<table>
<tr>
<td>
<a wicket:id="view" href="#">
<span wicket:id="firstName"></span>
<span wicket:id="lastName"></span>
</a>
</td>
<td wicket:id="email"></td>
<td class="manage-contact-links">
<a wicket:id="edit" href="#">Edit</a>
<a wicket:id="delete" href="#">Delete</a>
</td>
</tr>
</table>
</div>
ListView的populateItem(ListItem)方法会作用到每一个被迭代的对象上,这样的话才能最终在页面相应的wicket:id中显示出来.当前迭代的对象在整个ListItem的getModel()和getModelObject()方法都是可见的,因此,我们可以很自由的生成相应的label和link(SmartLinkLabel组件作为Wicket的扩展已经可以使用了).现在我们更近一步的看看link是如何被添加到ListItem中去的:
Link view = new Link("view", item.getModel()) {
public void onClick() {
Contact c = (Contact) getModelObject();
setResponsePage(new ViewContact(c.getId()));
}
};
view.add(new Label("firstName",
new PropertyModel(item.getModel(), "firstName")));
view.add(new Label("lastName",
new PropertyModel(item.getModel(), "lastName")));
item.add(new Link("edit", item.getModel()) {
public void onClick() {
Contact c = (Contact) getModelObject();
setResponsePage(new EditContact(c.getId()));
}
});
item.add(new Link("delete", item.getModel()) {
public void onClick() {
Contact c = (Contact) getModelObject();
WicketApplication.get().getContactDao().delete(c.getId());
setResponsePage(ListContacts.class);
}
});
所有的link都可以得到ListItem所持有的模型,并且如果有必要的话,可以随时访问contact模型对象的属性.每个link都有相应的onClick()方法,用户在web页面点击时就会被调用到.比如说“view”和“edit”的link,先得到Contact模型对象的id属性,然后跳转到各自的相应页面――ViewContact和EditContact中去.这样的话“delete”link作用也类似,只不过当用户点击“delete”后,会直接返回ListContacts页面而已.
最后一部分火速跟进..................
评论
发表评论
-
【翻译】深入浅出 EJB3.1(下)
2009-05-07 23:37 8913Global JNDI names( 统一的 全局 ... -
【翻译】深入浅出 EJB3.1(上)
2009-05-06 20:59 11162终于有空将EJB3.1的最新文章与大家分享,原文请看: ht ... -
【翻译】Java EE 6体系结构的变革
2009-02-09 10:01 4526又看到 Reza 同学为 -
【翻译】Java EE 6体系结构的变革(完)
2009-02-09 10:00 6473JSF 2.0 尽 ... -
垃圾收集器是一个“宝贝收藏家”?
2008-11-25 23:58 3080原文请看:http://java.dzone.com/ar ... -
深入理解JBoss Cache3.0——Naga
2008-11-12 09:12 9743原文请看: http://java.dzone.com/ ... -
【翻译】Rod Johnson——关于当选JCP执行委员会的之言片语
2008-11-03 10:42 3192SpringSource 在上月底被宣布被加入 JCP ... -
【翻译】EJB3.1真的来了吗?EJB3.1系列文章(五) 终章
2008-10-16 14:37 9224历时9 个多月的EJB3.1 系列文章终于要划上圆满的句 ... -
【翻译】Rod Johnson——平衡的质疑:Spring维护策略的再次调整(完)
2008-10-09 09:33 4072不管你承不承认,Spring实际上已经是实事上JAVA企业开 ... -
【云计算专家Joseph Ottinger系列】应用服务器本质论
2008-09-08 08:58 3483原文请看: http://www.t ... -
Spring破坏了JEE规范吗?
2008-09-02 13:33 4094[TTS 编辑注:这是 TTS 论坛上的原帖。我现在把它 ... -
【翻译】spring配置全书(下)——附PDF完整版下载
2008-07-14 12:30 10844JMS 命名空间简介 Schema URI ... -
【翻译】spring配置全书(上)
2008-07-07 23:11 8950作者简介: Craig Walls 是 Texa ... -
【翻译】EJB3.1真的来了吗?EJB3.1系列文章(四)
2008-06-18 23:10 38219前言 Raza 同学终于又出 EJB3.1 文章了 ... -
【翻译】Rod Johnson——Spring的宣言:开源,开放(完)
2008-06-10 16:51 5616前言 这是本文的第二部分,里面提到并回答许多Spring用 ... -
【翻译】Rod Johnson——Spring的宣言:开源,开放
2008-06-06 13:06 6117原文地址: http://blog.sp ... -
【翻译】EJB3.1真的来了吗?EJB3.1系列文章(三)
2008-05-01 13:53 8839文本继续和大家分享EJB3.1特性,今天谈到的EJB Lite ... -
【Danny hui】运用抽象工厂模式自己动手写一个IoC
2008-04-23 16:34 6360本文的作者Danny hui似乎是TTS上的新人,我从Goog ... -
【翻译】Wicket启示录——理论与实践(三)完
2008-04-11 01:09 6286接下来,我们再看看EditContact类,把新建联系人的话和 ... -
【翻译】Wicket启示录——理论与实践(一)
2008-04-09 23:15 6810序 Wicket,当多数人看到它时,也许又是带着惯性思考 “j ...
相关推荐
博文链接:https://superleo.iteye.com/blog/181053
学习Apache Wicket 7不仅涉及理论知识,还需要通过实践项目来加深理解。熟悉其API、组件模型、事件处理和模板系统,将有助于你构建出高效、可维护的Web应用程序。同时,持续关注Wicket社区的更新和最佳实践,可以...
在本文中,我们将深入探讨如何使用QT5库来设计一个具有菜单、工具栏和文本编辑器功能的主窗口。QT5是一个跨平台的应用程序开发框架,由C++编写,广泛应用于图形用户界面(GUI)的构建。让我们逐一解析每个组成部分,...
在Wicket基础知识培训中,首先会涉及到的是Web开发的基础——Servlet技术。Servlet是一种用于扩展Web服务器功能的Java类,它允许开发者处理HTTP请求并生成响应。Servlet的核心特性包括其服务器端运行、遵循特定规范...
**二、Wicket 开发流程** 1. **创建页面类**:在Wicket中,每个页面都有一个对应的Java类,类中定义了页面的组件和行为。 2. **绑定HTML模板**:页面类与HTML模板通过`@MountPath`注解或`WebPage`的构造函数关联。 3...
**Wicket 开发指南** Wicket 是一个开源的、基于Java的Web应用程序框架,它以其组件化、模型-视图-控制器(MVC)架构和轻量级特性而受到...通过学习和实践,你可以掌握使用Wicket构建高效、可维护的Web应用的技能。
### Wicket 1.4 开发手记:Hello World与环境配置 #### 一、引言 在《Wicket 1.4 开发手记》系列的第一篇文章中,作者Steel.Ma分享了他对Wicket框架的一些见解,特别是针对Wicket 1.4版本的入门级介绍。文章首先对...
**Wicket简单实例详解** Wicket是一款开源的Java Web应用程序框架,它强调组件化和模型-视图-控制器(MVC)的设计模式。...在实践中不断探索和尝试,你将对Wicket有更深入的理解,并能开发出功能丰富的Web应用。
5. **易于扩展和定制**:Wicket具有高度的灵活性,可以方便地与其他库集成,例如Spring或Hibernate。 【压缩包子文件的文件名称列表】:`apache-wicket-6.16.0` 这个文件名表明包含的是Apache Wicket的6.16.0版本。...
25. Wicket最佳实践 25.1。正确封装组件 25.2。将模型和页面数据放在字段中 25.3。正确命名Wicket ID 25.4。避免在组件树上进行更改 25.5。正确实现组件的可见性 25.6。始终使用模型 25.7。不要在构造函数层次结构中...
- 安装 Wicket 的示例程序是了解框架特性和实践应用的有效方式。 - 示例程序通常包含了框架的核心功能演示,有助于理解各个组件的工作原理。 - **使用 Eclipse 开发:** - **安装 Eclipse:** Eclipse 是一个...
### Wicket 入门与 Eclipse 项目创建指南 在当今的 Web 开发领域,Java 框架扮演着举足轻重的角色,其中 Apache Wicket 是一个强大的、面向组件的 Java Web 应用框架,它简化了 Web 应用的开发过程。本文将详细介绍...