其实也没什么,就是YOYOPlayer 默认的界面 播放列表里的 JSplitPane 使用的是系统提供的默认皮肤(在Java中提供的几个平台中的一个)。但是如果碰到Java不支持的桌面环境,界面就很难看了,于是就在网上找了点代码,学习了一下如何自定义一些组件,更改了YOYOPlayer默认界面中的那条白色的“竖条” ,如下图所示:

改进后的界面:(整体感觉是不是更好了点?
)

原理其实就是写个类 继承 BasicSplitPaneDivider,然后写个 UI类继承 BasicSplitPaneUI ,
在继承BasicSplitPaneUI 的类中,需要重写下面的方法:
public BasicSplitPaneDivider createDefaultDivider() {
}
最后写完以后,在代码中调用JSplitPane 的setUI() 方法就可以了。
最后在上一张完整无处理的图片:

摘要: JDK6 update18发布了,这次更新包含了许多值得关注的新特性以及性能的提升 阅读全文
摘要: 断断续续的学习NetBeans RCP 开发有一段时间了,也用NetBeans RCP开发了一个内部项目,在学习的过程中发现NetBeans真的很强大。 如果大家想学习NetBeans RCP开发的话,官方网站上的入门教程建议大家多看看,还有就是NetBeans Top10 API视频教程。官方网站上的NetBeans platform 教程有部分已经翻译成中文了,中文教程还在陆续的翻译中。
在学习的过程中,在NetBeans 官方网站上看到一篇关于NetBeans 快速搜索API使用教程,于是模仿着写了这个插件。这个插件功能比较弱,只能搜索到blogjava首页上的文章。有需要的可以拿去用用,开发的时候我用的是NetBeans6.8 。
阅读全文
摘要: JavaFX 设计器很快就要发布了, JavaFX 一直被人诟病没有可视化的设计器,现在终于有了。
大家可以到 netbeans 的wiki上看看 这个设计器的教程,了解这个设计器更多的特性。
http://wiki.netbeans.org/JavaFXComposer
大家还可以关注一下这个人的博客,了解JavaFX 设计器。
http://blogs.sun.com/lukas/
废话不多说了,先睹为快: 阅读全文
摘要: 经过漫长的等待,NetBeans6.8 &&JavaEE 6 && GlassFish v3 终于发布了!
NetBeans 6.8 一个你不可错过的版本。不仅功能上改进了非常多,性能上更是提升了不少。
NetBeans 6.8 的功能具体介绍:http://wiki.netbeans.org/NewAndNoteWorthy
NetBeans 6.8 视频教程 http://netbeans.org/kb/docs/intro-screencasts.html
阅读全文
摘要: NetBeans6.8正式发布,同时符合Java EE6规范的GlassFishV3也放出了正式版本。 阅读全文
今天邮箱里收到一封邮件,说是有一份文档与我分享,于是点了链接,跳出来的却是百度的文档分享平台,看了一下界面,和豆瓣,Google 的
文档显示界面基本上都是一样的,都是用Flex做的,到现在我才知道,原来百度 也开始涉水 文档服务了,就像Google book类似,不过听说最近
Google book 官司不断,不知道百度会如何应对将来发生的 图书纠纷呢?

JXTaskPane 类似XP 左边的导航栏,在开发Swing应用的时候很好用的。
下面两张截图反应了JXTaskPane的动画效果。可以自由的卷起和展开。

JXTaskPane的的使用步骤:
1、新建一个 JXTaskPaneContainer
2、新建{i}个JXTaskPane (i>=1)
3、依次将 新建的JXTaskPane 添加到 JXTaskPaneContainer 中去。
4、最后将 JXTaskPaneContainer 添加到JFrame 中。
附上 SwingX doc中的示例代码
JXFrame frame = new JXFrame();
// a container to put all JXTaskPane together
JXTaskPaneContainer taskPaneContainer = new JXTaskPaneContainer();
// create a first taskPane with common actions
JXTaskPane actionPane = new JXTaskPane();
actionPane.setTitle("Files and Folders");
actionPane.setSpecial(true);
// actions can be added, a hyperlink will be created
Action renameSelectedFile = createRenameFileAction();
actionPane.add(renameSelectedFile);
actionPane.add(createDeleteFileAction());
// add this taskPane to the taskPaneContainer
taskPaneContainer.add(actionPane);
// create another taskPane, it will show details of the selected file
JXTaskPane details = new JXTaskPane();
details.setTitle("Details");
// add standard components to the details taskPane
JLabel searchLabel = new JLabel("Search:");
JTextField searchField = new JTextField("");
details.add(searchLabel);
details.add(searchField);
taskPaneContainer.add(details);
// put the action list on the left
frame.add(taskPaneContainer, BorderLayout.EAST);
// and a file browser in the middle
frame.add(fileBrowser, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
默认JXTaskPane 的动画功能是起用的,你也可以关闭 :
只要 myJXTaskPane.setAnimated(false); 就可以了。
摘要: Linux 下永中Office 对 doc 文件的兼容性比较好,所以在Linux 我用的最多的office 软件就是永中Office。
最近操作系统换成了 Fedora 11,安装永中Office 的时候遇到了一些问题,现在把我遇到的问题和解决办法
写下:
第一个问题: 在 3D环境下不能安装 永中Office
解决:关闭3D效果,然后再安装永中Office ,OK。
第二个问题: 在正常模式下可以很快的启动永中Office,但是在3D模式下就启动不了。
解决:请安下面的步骤进行 阅读全文
摘要: Linux 下的游戏没有Windows 多,而且想找游戏玩也比较麻烦,也不知道有什么游戏可以玩。
最近在网上看了djl 这个游戏管理软件,里面有上百个的游戏可以提供你玩。真的很不错,默认没有中文的
我顺手翻译了一下,翻译的不是很完整,不过够大家用的了。 阅读全文
摘要: 经常会遇到一个表格中有许多的数据,想要找到一条符合自己要求的数据会比较麻烦,需要一条一条的找。数据量小还好,但是如果有几百条上千条的数据找起来就比较麻烦了。Lucene 提供了一个拓展包 lucene-swing,可以很方便的对JTable进行搜索。 阅读全文
摘要: SQE 是 software quality enviroment 的缩写, NetBeans 的SQE 插件 官方的介绍是这样的:
SQE is an attempt at providing first class NetBeans integration for different Software Quality Tools as
* Code Defect Analysis
o FindBugs
o PMD
o CheckStyle
o Lint4j
* Metrics
o Dependency Finder
* Dependency Analysis
o Dependency Finder
我把它叫做软件质量测试工具,它可以帮你找到你写的代码中潜在的问题 还会有一些建议。
PMD 的介绍:
阅读全文
摘要: 针对NetBeans的 Substance 官方皮肤插件,已经有很长时间没有更新了,这次 NetBeans 梦之队 成员重新写了个 NetBeans的
Substance 皮肤插件,虽然现在的可定制性不如 官方的版本,但是官方的版本只支持 NetBeans 6.1 而这个却可以支持
NetBeans 6.7.1最新的版本。
阅读全文
摘要: NetBeans6.8 M1发布了!添加了嵌入式浏览器支持和JavaEE6 支持 ,此外还有 ruby maven, C++ 等增强特性.
有图有真相:
嵌入浏览器功能默认不开起,需要自己手动开启: 在 工具->选项
阅读全文
摘要: 性能问题一向是历代NetBeans发布时的关注焦点。和发布6.7之前的情形一样,6.8版本包含很多值得自豪的改进。 阅读全文
今天用到了一些SwingX 的类库,但是显示的时候都是英文的,感觉挺别扭的,于是就对SwingX做了一些国际化!
下载了源代码,然后找到对应的Properties 文件,发现其实SwingX已经有很多个国家的语言版本了,就是少了中国版的,唉!谁叫中国的程序员使用Swing的少呢? 呵呵!
用NetBeans打开 项目文件,找到properties文件,为每个原始的Properties文件添加一个 zh_CN的locale 。然后就是翻译了。这里不得不赞美一下NetBeans 对properties 文件的编辑功能相当的好用,可以直接写中文,而不必转换为Unicode。NetBeans 默认已经帮你完成了。
这是我第一次翻译,因为能力有限,所以翻译难免会有一点小毛病,有什么翻译问题请留言,或者发邮件告诉我,让我好改正。![]()
2009-11-04 更新:
翻译更新到SwingX1.6, SwingX1.6 是一个 Java 6 only 版本,也就是说这个版本需要用JRE1.6 。
2009-09-23 更新:
应朋友们的要求,今天放上来 SwingX-1.0 的国际化版本(并非本地化,仅仅只是国际化)。
修复LoginPanel 翻译的问题,原来翻译成中文有乱码,现保留为英文。
初步判断是SwingX 中使用了不支持中文的字体造成的。
2009-07-07 更新:
第一次对SwingX进行翻译
------------------------------传说中华丽的分割线-----------------------------------
(SwingX-1.0)点这里下载 (20090923)
摘要: Swing应用程序如果是在开源的Look&&Feel 之间切换,感觉很容易,但是如果把应用程序在开源外观下切换到系统默认的或者JDK自带的外观时,问题就来了。不是没有标题栏,就是标题栏的外观没有改变,用的是系统的窗口装饰。 阅读全文
期待已久的JDK 1.6.0_14 发布了。http://java.sun.com/javase/6/webnotes/6u14.html
本次更新是继Update 10以来最大的一次更新,包含了众多新特性和bug的修复,喜欢尝鲜的开发人员可以试试最新版本的JDK带来的益处。
需要关注的是JRE的安装界面,Sun标志的背景改为了红色,但愿Oracle能使Java更加辉煌吧。



摘要: 今天用Swing 做了一个模仿QQ2009的登录界面,用到了开源的Look&Feel (Substance),在使用的过程中遇到了一些问题,也学到了一些技巧。
Substance (https://substance.dev.java.net)有很多的外观可以选择,而且都很漂亮,还提供了强大的API供开发者使用。Substance 现在已经
发展到5.2RC 版了,一开始我使用的是5.1版,但是在使用的过程中发现了一些bug,当我使用Substance中提供的水印功能时,出现了许多的异常,这个bug在5.0的时候是没有的,后来我又下载了最新的5.2RC版,这个问题在5.2版中已经解决了。 阅读全文
摘要: 最近在学习Swing中的动画绘制,用到了Timer 这个类,于是写一点笔记,和大家分享。大家有什么好的例子不妨共享出来吧!!
计时器在java.swing包中的Timer类来创建,它可以看做是GUI的一个组件。与其他组件不一样的是,它没有可以显示在屏幕上的直观的外观。正如名字所表达的,它只帮我们来计时。
计时器对象按相等的时间间隔来产生动作事件。执行动画程序时,可以设置计时器来定期产生动作事件,然后在动作监听器中更新动画图形。
阅读全文
摘要: 有一段时间没写博客了,这几天我同学要赶着交毕业设计,让我帮他写个爬虫,专门抓搜狐的新闻,我用过爬虫,但是从来没有自己写过爬虫,于是Google了一下,找到了一篇不错的文章:使用 HttpClient 和 HtmlParser 实现简易爬虫 . 参考里面的代码,自己写了个简易的搜狐新闻爬虫。 阅读全文
摘要: netbeans 6.7 m3 基本开发完毕了,意味着netbeans6.7 的发布也不远了。6月份的 JavaOne 大会上,netbeans6.7
就会发布了。6.7 版本 重点的开发放到了Maven ,Test,Debug 等功能上的完善和增强。
我比较喜欢的几个功能的改进:
阅读全文
(2009年4月2日更新) 最近在网上找到了一些比较好的学习Swing 的网站,不敢独享,发表上来大家一起学习。 1.第一个就不用说了,Sun官方的教程 相当的不错。(英语基础不一定要很好,安装个Lingoes 就可以了) Swing : http://java.sun.com/docs/books/tutorial/uiswing/TOC.html Java2D: http://java.sun.com/docs/books/tutorial/2d/index.html btw:你也可以将教程下载到本地上看 2. 第二个也是个英文的网站 代码和实例都很多,也是难得的学习Swing 和Java2D 的好地方 Swing:http://aplcenmp.apl.jhu.edu/~hall/java/Swing-Tutorial/ Java2D:http://www.apl.jhu.edu/~hall/java/Java2D-Tutorial.html Swing :http://www.zetcode.com/tutorials/javaswingtutorial/ Java2D:http://www.zetcode.com/tutorials/java2dtutorial/ Java2D Games:http://www.zetcode.com/tutorials/javagamestutorial/ (这个游戏教程不错) 4.第四个还是英文的学习站点 ,这个个站点的学习文章比较多,涉及的方面也比较广,是个不错的学习java GUI 的 站点。 Swing:http://life.csu.edu.au/java-tut/uiswing/ ps:为什么国外的Swing教程那么多呢?而且质量也不错! 今年的工作不好找,只好再努力的巩固基础,厚积薄发!
3.第三个还是英文的网站,这个网站上介绍的组件不多,但是代码很经典,而且还有几个简单的游戏教程。
Mark Occurrences (元素高亮)指的是当鼠标放在某个类元素上时,在当前文件高亮出该元素的 声明和引用。
如果你使用过 Find Usages 的话,你应该能知道这个功能的好处。但是 Mark Occurrences 比起 Find Usages 来属于轻量级的。因为:
- Mark Occurrences 只搜索当前文件
- Mark Occurrences 为动态的,不需要菜单来激活只需要将鼠标放在要查看的元素上即可。
- Mark Occurrences 懂得语义,比如将鼠标指向当前类的超类,它将显示所有被实现/覆盖的方法;放在方法的返回类型上,将显示方法的所有返回的语句上;...
- 成员作用域

- 方法返回点

- 特定异常抛出点

如果你使用的是 NetBeans 5.x 系列的话,你需要注册一个更新中心,然后下载插件,具体步骤如下:
- 选择 Tools | Options
- 单击 Advanced Options 按钮
- 选择 Options | IDE Configuration | System | Autoupdate Types
- 右击并选择 New | General Update Center
- 在 Name 输入域中输入Sandip Chitale's Modules 然后单击 Finish
- (此步骤不必,如果你在完成上述步骤后立即进行下面的步骤时) 展开Autoupdate Types node, 选择 Sandip Chitale's Modules
- 在右边的窗口中的第一个属性值Server URL,输入: http://blogs.sun.com/roller/resources/scblog/update-center.xml
- 确保Enabled 属性勾上。然后关闭当前窗口
现在这个更新中心就可以用了,我们目标是得到 Mark Occurrences 插件,它就在这个更新中心中:
选择Tools | Update Center 菜单. 勾上 Sandip Chitale's Modules 项,如果它还没被勾上的话。依照更新向导在 Select Modules to Install 窗口中选择
Sandip Chitale's Modules 选择Make Occurrences
虽然作者声明:这个模块是个实验性的模块,但是到目前为止在我的工作中我一直在用它,而且没有出现任何问题(比起一些 Eclipse 的插件可强多了!)
注意: 安装完后(不记得要不要重启 NetBeans), 你应该能看到工具条上出现一个黄色的按钮(如下图),或者你可以从 View | Mark Occurrences 激活它:
文档内容
- 概览
- Struts 表示层组件 FormBean
- FormBean 配置
- FormBean 类层次
- BaseActionForm 子类实例 AccountActionForm
- 避免重复提交
- Struts 的事务 Token
- 我们还缺什么?
- 客户端校验
- 漂亮的页面
- 总结

在阅读本篇文章之前,请先仔细阅读前面系列的相关内容。
概览
在各种框架欣欣向荣的今天,你能想象最初 Java WEB 开发者的日子吗?要知道,就算是JSP,当时都被寄予厚望,因为当时,开发者不得不在Servlet 中书写之如:out.println("<html><head><title>My God</title></head><body>");
你能想象,以这种方式做一个象样的页面是怎样的一种情形。这种情况下,是将“表示层”的内容(HTML标记)渗透进Java代码中了,你哪怕是修改页面上的一个文字,你都不得不在上述的 println 中修改 -> 编译 -> 测试-> ...
于是,JSP应运而生,可是很快,开发者发现,情况反过来了:在JSP页面代码中到处散布有之如:
<%
String amount =
request.getParameter("amount");
if
( amount != null &&
amount.length() > 0 ) {
...
%>
也就是说,此时表示逻辑的代码渗透进页面代码中了。
于是才有后来的 JavaBeans, <jsp:useBean>, Taglibs 等,以及术语 WEB MVC, MVC2 等。
毫无疑问,对于在JAVA Web 领域工作多年的老手,看到我这篇关于 Struts 的文章肯定会觉得好土,或者甚至老掉牙了! 的确,这也是我这段时间一直在考虑是否需要写这样一个系列的原因。
不管现在 JSF. WebWorks/Struts2, SpringMVC , JBoss Seam 被如何鼓吹,Struts 作为 Web
框架的先行者,还是有它的位置。尽管此例子中所采用的方法比起最新的 Struts (Struts 1.3.x 系列)也同样显得有些陈旧,但是正如 JAVA 领域中的一惯作法,“在引入新功能前先考虑向后兼容”,因此,新的功能尽管加入吧,你可以欣喜若狂,但我也同样可以一直运行已经稳定运行好几年的产品。
随便提一下,本人并不认为上述新的WEB框架使开发工作简化了多少,相反,倒是增加了不少复杂性。作为新手,很难保证在研究这些框架一周后能开发出一个稳
定可靠的方案。相反象几个简单的框架反而在引入面向 Page 的设计方法的同时,简化了开发的难度:Wicket Click ,而且更加符合当今的 Web2 的需求。
再有,由于 JSTL 的流行,几乎所有的 Web 框架都依靠它来排除JSP脚本。但是我们不会在这里介绍每个 JSTL 标记的用法,具体的用法见工程的JSP 源代码。
好了,一来就说了这么多,无非是为了引入主角 Struts,但是请原谅,关于整个Struts
的介绍是需要一整书才能介绍完的。所以我们还是以代码为依托,一步步来吧。
我们的主题是表示层的相关技术。
Struts 表示层组件 FormBean
FormBean 配置
FormBean 即是我们熟悉的 JSP + JavaBean 设置方式中的 JavaBean,只不过它作为 Struts 框架的组件担任起页面表单与 Struts Action的信息传递的使者。
为了弄清 FormBean 的工作原理,我们现在给出我们整个的 struts-config.xml 文件的内容
<?xml version="1.0"
encoding="GBK"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software
Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<!-- 配置此应用中的所有 FormBean
-->
<form-beans>
<!-- 这种复用
FormBean 的方式值得讨论,见紧随其后的说明 1 -->
<!--
与注册帐户和帐户信息相关的页面使用的 FormBean -->
<form-bean name="accountForm"
type="org.springframework.samples.jpetstore.web.struts.AccountActionForm"/>
<!--
与购物车相关的页面使用的 FormBean -->
<form-bean name="cartForm"
type="org.springframework.samples.jpetstore.web.struts.CartActionForm"/>
<!-- 没有对应的页面元素的
FormBean, 例如点击一个链接或按下搜索按钮等等功能,被设计成不需要 FormBean 来收集用户输入 -->
<form-bean
name="emptyForm"
type="org.springframework.samples.jpetstore.web.struts.BaseActionForm"/>
<!-- 与帐户修改相关的页面使用的
FormBean,因为此时也许在当前的 session 已经存在了一个 accountForm -->
<form-bean
name="workingAccountForm"
type="org.springframework.samples.jpetstore.web.struts.AccountActionForm"/>
<!-- 与所有定单操作相关的页面使用的 FormBean -->
<form-bean
name="workingOrderForm"
type="org.springframework.samples.jpetstore.web.struts.OrderActionForm"/>
</form-beans>
<!-- 全局跳转声明,这此跳转可以被所有的
Action 中共享 -->
<global-forwards>
<forward
name="failure" path="/WEB-INF/jsp/struts/Error.jsp"
redirect="false"/>
<forward
name="unknown-error" path="/WEB-INF/jsp/struts/Error.jsp"/>
<forward
name="global-signon" path="/WEB-INF/jsp/struts/SignonForm.jsp"/>
</global-forwards>
<!-- 以下为所有的 Action 映射
-->
<action-mappings>
<!--
点击链接将一只宠物加入购物车 -->
<action path="/shop/addItemToCart"
type="org.springframework.samples.jpetstore.web.struts.AddItemToCartAction"
name="cartForm" scope="session" validate="false">
<forward name="success" path="/WEB-INF/jsp/struts/Cart.jsp"/>
</action>
<!-- 结算购物车
-->
<action path="/shop/checkout"
type="org.springframework.samples.jpetstore.web.struts.ViewCartAction"
name="cartForm" scope="session" validate="false">
<forward name="success" path="/WEB-INF/jsp/struts/Checkout.jsp"/></action>
<!--
修改帐号信息 -->
<action path="/shop/editAccount"
type="org.springframework.samples.jpetstore.web.struts.EditAccountAction"
name="workingAccountForm" scope="session" validate="true"
input="/WEB-INF/jsp/struts/EditAccountForm.jsp">
<forward name="success" path="/shop/index.do"/>
</action>
<action
path="/shop/editAccountForm"
type="org.springframework.samples.jpetstore.web.struts.EditAccountFormAction"
name="workingAccountForm" scope="session"
validate="false">
<forward name="success"
path="/WEB-INF/jsp/struts/EditAccountForm.jsp"/>
</action>
<action
path="/shop/index"
type="org.springframework.samples.jpetstore.web.struts.DoNothingAction"
validate="false">
<forward name="success" path="/WEB-INF/jsp/struts/index.jsp"/>
</action>
<action
path="/shop/help"
type="org.springframework.samples.jpetstore.web.struts.DoNothingAction"
validate="false">
<forward name="success" path="/WEB-INF/jsp/struts/help.jsp"/>
</action>
<action
path="/shop/listOrders"
type="org.springframework.samples.jpetstore.web.struts.ListOrdersAction"
name="accountForm" scope="session" validate="false">
<forward name="success"
path="/WEB-INF/jsp/struts/ListOrders.jsp"/>
</action>
<action
path="/shop/newAccount"
type="org.springframework.samples.jpetstore.web.struts.NewAccountAction"
name="workingAccountForm" scope="session" validate="true"
input="/WEB-INF/jsp/struts/NewAccountForm.jsp">
<forward name="success" path="/shop/index.do"/>
</action>
<action
path="/shop/newAccountForm"
type="org.springframework.samples.jpetstore.web.struts.NewAccountFormAction"
name="workingAccountForm" scope="session" validate="false">
<forward name="success"
path="/WEB-INF/jsp/struts/NewAccountForm.jsp"/>
</action>
<!--
进入结算中心页面后,点击继续进入此 -->
<action path="/shop/newOrderForm"
type="org.springframework.samples.jpetstore.web.struts.NewOrderFormAction"
name="workingOrderForm" scope="session" validate="false">
<forward name="success"
path="/WEB-INF/jsp/struts/NewOrderForm.jsp"/>
</action>
<!--
fixed by pprun: 将原先混在一起的逻辑打破成几个小部分,否则在多步向导式提交
页面中的任何一步出错都无理地返回到 NewOrderForm.jsp 页面,而不是真正的出错的页面
-->
<!--
<action
path="/shop/newOrder"
type="org.springframework.samples.jpetstore.web.struts.NewOrderAction"
name="workingOrderForm" scope="session" validate="true"
input="/WEB-INF/jsp/struts/NewOrderForm.jsp">
<forward name="confirm"
path="/WEB-INF/jsp/struts/ConfirmOrder.jsp"/>
<forward name="shipping"
path="/WEB-INF/jsp/struts/ShippingForm.jsp"/>
<forward name="success" path="/WEB-INF/jsp/struts/ViewOrder.jsp"/>
</action>
-->
<!--
填写定单信息的多页向导式页面 -->
<!--
当第一页校验失败时,需要跳回填写购物单的第一页 -->
<action path="/shop/newOrderStep1"
type="org.springframework.samples.jpetstore.web.struts.NewOrderAction"
name="workingOrderForm" scope="session" validate="true"
input="/shop/newOrderForm.do">
<forward name="confirm"
path="/WEB-INF/jsp/struts/ConfirmOrder.jsp"/>
<forward name="shipping"
path="/WEB-INF/jsp/struts/ShippingForm.jsp"/>
</action>
<!--
(只有页面上填写了将宠物送到不同的地址时,默认为送到当前用户的地址),
才会出现此面。此页校验失败,毫无疑问应该回到这个新地址填写页,
而不是整个流程的第一页。这就是原版中的BUG所在处,因为它将这个向导性的流程
处理放到了一个映射中,所以没法处理这种情况 -->
<action
path="/shop/newOrderStep2"
type="org.springframework.samples.jpetstore.web.struts.NewOrderAction"
name="workingOrderForm" scope="session" validate="true"
input="/WEB-INF/jsp/struts/ShippingForm.jsp">
<forward name="confirm"
path="/WEB-INF/jsp/struts/ConfirmOrder.jsp"/>
</action>
<!--
当在最后一步确认时出错,需要跳回填写购物单的第一页 -->
<action
path="/shop/newOrderStep3"
type="org.springframework.samples.jpetstore.web.struts.NewOrderAction"
name="workingOrderForm" scope="session" validate="true"
input="/WEB-INF/jsp/struts/NewOrderForm.jsp">
<forward name="success" path="/WEB-INF/jsp/struts/ViewOrder.jsp"/>
</action>
<!-- fixed
end -->
<action
path="/shop/removeItemFromCart"
type="org.springframework.samples.jpetstore.web.struts.RemoveItemFromCartAction"
name="cartForm" scope="session" validate="false">
<forward name="success" path="/WEB-INF/jsp/struts/Cart.jsp"/>
</action>
<action
path="/shop/searchProducts"
type="org.springframework.samples.jpetstore.web.struts.SearchProductsAction"
name="emptyForm" scope="session" validate="false">
<forward name="success"
path="/WEB-INF/jsp/struts/SearchProducts.jsp"/>
</action>
<action
path="/shop/signon"
type="org.springframework.samples.jpetstore.web.struts.SignonAction"
name="accountForm" scope="session" validate="false">
<forward name="success" path="/shop/index.do"/>
</action>
<action
path="/shop/signonForm"
type="org.springframework.samples.jpetstore.web.struts.DoNothingAction"
validate="false">
<forward name="success"
path="/WEB-INF/jsp/struts/SignonForm.jsp"/>
</action>
<action
path="/shop/updateCartQuantities"
type="org.springframework.samples.jpetstore.web.struts.UpdateCartQuantitiesAction"
name="cartForm" scope="session" validate="false">
<forward name="success" path="/WEB-INF/jsp/struts/Cart.jsp"/>
</action>
<action
path="/shop/viewCart"
type="org.springframework.samples.jpetstore.web.struts.ViewCartAction"
name="cartForm" scope="session" validate="false">
<forward name="success" path="/WEB-INF/jsp/struts/Cart.jsp"/>
</action>
<action
path="/shop/viewCategory"
type="org.springframework.samples.jpetstore.web.struts.ViewCategoryAction"
name="emptyForm" scope="session" validate="true"
input="/WEB-INF/jsp/struts/index.jsp">
<forward name="success" path="/WEB-INF/jsp/struts/Category.jsp"/>
</action>
<action
path="/shop/viewItem"
type="org.springframework.samples.jpetstore.web.struts.ViewItemAction"
name="emptyForm" scope="session" validate="true"
input="/WEB-INF/jsp/struts/Product.jsp">
<forward name="success" path="/WEB-INF/jsp/struts/Item.jsp"/>
</action>
<action
path="/shop/viewOrder"
type="org.springframework.samples.jpetstore.web.struts.ViewOrderAction"
name="accountForm" scope="session" validate="false">
<forward name="success" path="/WEB-INF/jsp/struts/ViewOrder.jsp"/>
</action>
<action
path="/shop/viewProduct"
type="org.springframework.samples.jpetstore.web.struts.ViewProductAction"
name="emptyForm" scope="session" validate="true"
input="/WEB-INF/jsp/struts/index.jsp">
<forward name="success" path="/WEB-INF/jsp/struts/Product.jsp"/>
</action>
</action-mappings>
</struts-config>
说明:
1. 从FormBean 的数量和每个使用了FormBean的 Action 映射可知,这里存在 FormBean
复用问题,即用一个来服务多个 Action, 这种方式可以大大减少 FormBean 的数量,
但是,在 Action中的逻辑变得复杂了。因为在 FormBean 中包括了所有 Action 的需求,
而在Action中不得不排除它所不需要的元素的干扰。这样使代码看起来很混乱。
2. 有了全局声明,在 Action 的代码中就可以随时发出 mapping.findForward("failure");
之类的代码,而不需要在对应的 Action 映射中配置该 <forward> 子元素.
3. 注释掉的 Action 映射是为了修复一个BUG:
因为在涉及到定单提交时,采用的是多页提交(也就向导页面)方式,即收集的信息是从连续多个
页面中获得的,而不是普通的从一个页面中得到的。这样就涉及到,当其中的一个页面出现校验
失败时,将要将流控跳转到出错的页面,通过将原先混在一起的逻辑打破成几个小部分,
否则在多步向导式提交页面中的任何一步出错都无理地返回到 NewOrderForm.jsp 页面,
而不是真正的出错的页面,请看相应的映射元素的注释说明。
4. 为了保持连贯性,关于每个映射元素的每个属性,我们重复 Hibernate
JPetstore 系列之三: 控制层技术 中的 ActionForm <-- struts-config.xml -->Action 部分的内容:
1. path=/shop/editAccount
所有要去住 /shop/editAccount (严格地讲,如果按照Struts 的方言是 /shop/editAccount.do)
的请求,都要遵循这里的配置
2. name="workingAccountForm"
都将绑定 workingAccountForm ,注意 form-bean 在 Action 中引用是通过 name
属性来引用的,它是在一开始定义的: <form-bean name="workingAccountForm"
type="org.springframework.samples.jpetstore.web.struts.AccountActionForm"/>
3. scope="session" 该 bean
将在整个会话其间始终有效 ,但注意这个配置是多余的,默认就是 session 上下文的,反而如果 bean 只在
request上下文时,才需要明确地声明。
4. validate="true" 将对表单的输入调用 form-bean 的 validate 方法。但我们发现在
AccountActionForm.java 中,只有 doValidate(...) 方法,并没有 validate()方法,
但细心的话,应该发现了,和所有的Action 都是从BaseAction 中派生而来一样,
所有的ActionForm 中都是从一个基类 BaseActionForm.java 中派生下来。
其中定义了所有 formbean都需要的东西,对于校验错误的处理。
其中就是 validate(...) 方法,并在其中调用了 doValidate() 方法,
而每个BaseActionForm 的子类只要override 这个doValidate() 方法,
如果 validate="true"声明了的话,那么子类中的 doValidate() 方法将会被调用。这是多态性的表现。
5. input="..." 一般来讲,一个表单在校验失败后都需要回去重纠正错误的输出项,
所以我们通过这个值来告诉 Struts该回到哪去纠错.FormBean 类层次
与 Action 类一样,FormBean 也基于类的继承关系设计的,这样子类 FormBean
只需实现父类 FormBean指定的约束,所有的子类都复用父类中的功能并按照这种设计约束工作。基类 BaseActionForm
该类本身又是从 抽象类 org.apache.struts.action.ActionForm 派生而来,
所以应用中的所有 FormBean只要从 BaseActionForm 派生即可:
public class BaseActionForm
extends ActionForm {
/**
*此乃最原始的错误处理方法,将所有错误信息加入到一个列表后,然后存入到
*Servlet 请求属性中供页面使用.
*更现代的方法是使用 Struts1.1 之后的 commons-validator,关于这个功能在
* 各种关于Struts 的参考或书籍中都有介绍。
*
*是否为调用此方法是通过属性 validate 来控制的,如:
*<action path="/shop/signon"type="org.springframework.samples.jpetstore.web.struts.SignonAction"
*name="accountForm" scope="session" validate="false">
*是不会调用的,因为 validate="false".
* 这是“模板方法”(Template method) 设计模式中的“方法”
*/
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errorMessages =
null;
// 整个系统的错误信息列表,通过调用doValidate(mapping, request, errorList);
// addErrorIfStringEmpty 会将错误信息加入到列表当中,并且它被存入了请求属性当中.
ArrayList errorList = new
ArrayList();
doValidate(mapping, request,
errorList);
request.setAttribute("errors", errorList);
if (!errorList.isEmpty()) {
errorMessages = new org.apache.struts.action.ActionErrors();
errorMessages.add(ActionErrors.GLOBAL_MESSAGE, new
ActionMessage("global.error"));
}
return errorMessages;
}
/**
*此方法被设计为供子类覆盖的(overriding).
*任何子类实现了这个方法,将自动被上面的 validate 方法调用。
*
* 这是“模板方法"模式中的默认钓子方法,由子类的实现方法来替换。
*
* @param mapping
* @param request
* @param
errors
*/
public void doValidate(ActionMapping mapping,
HttpServletRequest request, List errors) {
}
/**
*此辅助方法被用来给定的页面输入内容是否为空,如果是空的话,将显示给定的出错信息。
*
* @param errors 错误信息列表
* @param message 当 value 为空时,将显示这个错误信息
* @param value 页面元素对应的值
*/
protected void addErrorIfStringEmpty(List errors,
String message, String value) {
if (value == null ||
value.trim().length() < 1) {
errors.add(message);
}
}
}BaseActionForm 子类实例 AccountActionForm
我仅介绍一个子类 AccountActionForm :
public class AccountActionForm
extends BaseActionForm {
/** 用于检验的常量定义,因为在新建帐户与修改帐户时检验逻辑是不一样的。
* 至少在修改帐户时,帐户名是已经存在了 */
public static final String VALIDATE_EDIT_ACCOUNT = "editAccount";
public static final String VALIDATE_NEW_ACCOUNT = "newAccount";
/** 用于存贮用户的首先语言的列表 */
private static final ArrayList LANGUAGE_LIST = new ArrayList();
/* Private Fields */
// 看起来好象与 Account 中的成员重复了,这是因为此 Form 被多个页面重复使用的
// 结果,因为在登录页面时,那时根本不存在 Account, 所以不可能通过
// account.getUsername() 和 account.getPassword() 来得到用户的输入值的,
// 下面两项即是在登录当时收集输入 信息,
// 其它情况(比如修改,新建帐户时)都是间接使用了 Account 中的成员,因当时都
// 已经在 session 中存放了一个 Account 的实例
// 所以重用是有代价的(使代码不那么直观了,如果是一个页面表单 Form 对应一个
// FormBean 的话,以下成员与页面中的输入元素是一一对应的)
// 供登录页面使用的 元素
private String username;
private String password;
// 登录后,与帐户相关的元素
private String repeatedPassword;
private List languages;
private List categories;
/**
* 这个成员的值是通过页面隐藏元素传入的:
* NewAccountForm.jsp 中: <html:hidden name="workingAccountForm" property="validate"
value="newAccount"/>
* EditAccountForm.jsp 中:<html:hidden name="workingAccountForm" property="validate" value="editAccount" />
*/
private String validate;
/**
* 用来记住用户是从哪里跳转过来的,因为准备对购物车进行结算时,如果没有登录
* 的话,首先将结算中心页面的地址存入此成员中,登录成功后再跳转过去。
* 如果没有这样一步操作的话,那么就会出现讨厌的将你送回首页面(也就是程序
* 的逻辑流程打扰了用户的进程,这是最应当避免的。)
*/
private String forwardAction;
/**
* 所有的帐号信息放在这个 POJO 中
*/
private Account account;
/**
* 用于显示标语,当你在用户信息页面选择显示标语时
*/
private String bannerName;
/**
* 用于显示根据用户的喜好被推荐的宠物列表,当你选择了显示该列表时。
*/
private PagedListHolder myList;
/**
* 用户最喜欢的宠物类别
*/
private String favCategoryName;
/* Static Initializer */
static {
LANGUAGE_LIST.add("english");
LANGUAGE_LIST.add("japanese");
}
public AccountActionForm() {
languages = LANGUAGE_LIST;
}
public PagedListHolder getMyList() {
return myList;
}
public void setMyList(PagedListHolder myList) {
this.myList = myList;
}
public String getForwardAction() {
return forwardAction;
}
public void setForwardAction(String forwardAction) {
this.forwardAction = forwardAction;
}
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 getRepeatedPassword() {
return repeatedPassword;
}
public void setRepeatedPassword(String repeatedPassword) {
this.repeatedPassword = repeatedPassword;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public List getLanguages() {
return languages;
}
public void setLanguages(List languages) {
this.languages = languages;
}
public List getCategories() {
return categories;
}
public void setCategories(List categories) {
this.categories = categories;
}
public String getBannerName() {
return bannerName;
}
public void setBannerName(String bannerName) {
this.bannerName = bannerName;
}
public String getFavCategoryName() {
return favCategoryName;
}
public void setFavCategoryName(String favCategoryName) {
this.favCategoryName = favCategoryName;
}
public String getValidate() {
return validate;
}
public void setValidate(String validate) {
this.validate = validate;
}
/**
* 覆盖父类中的方法”默认钓子“方法,用于特定于此子类的输入校验
*/
public void doValidate(ActionMapping mapping,
HttpServletRequest request, List errors) {
if (validate != null) {
if (VALIDATE_EDIT_ACCOUNT.equals(validate) ||
VALIDATE_NEW_ACCOUNT.equals(validate)) {
if (VALIDATE_NEW_ACCOUNT.equals(validate)) {
// 是新建帐户时,需要额外的校验
account.setStatus("OK");
addErrorIfStringEmpty(errors, "User ID is required.",
account.getUsername());
if (account.getPassword() == null ||
account.getPassword().length() < 1 ||
!account.getPassword().equals(repeatedPassword)) {
errors.add("Passwords did not match or were not provided. " +
"Matching passwords are required.");
}
}
if (account.getPassword() != null &&
account.getPassword().length() > 0) {
if (!account.getPassword().equals(repeatedPassword)) {
errors.add("Passwords did not match.");
}
}
addErrorIfStringEmpty(errors, "First name is required.",
this.account.getFirstname());
addErrorIfStringEmpty(errors, "Last name is required.",
this.account.getLastname());
addErrorIfStringEmpty(errors, "Email address is required.",
this.account.getEmail());
addErrorIfStringEmpty(errors, "Phone number is required.",
this.account.getPhone());
addErrorIfStringEmpty(errors, "Address (1) is required.",
this.account.getUserAddr().getAddr1());
addErrorIfStringEmpty(errors, "City is required.",
this.account.getUserAddr().getCity());
addErrorIfStringEmpty(errors, "State is required.",
this.account.getUserAddr().getState());
addErrorIfStringEmpty(errors, "ZIP is required.",
this.account.getUserAddr().getZipcode());
addErrorIfStringEmpty(errors, "Country is required.",
this.account.getUserAddr().getCountry());
}
}
}
/**
* 此方法是一个很重要的方法,我们看看基类中对该方法的描述:
*
* Reset bean properties to their default state, as needed.
* This method is called before the properties are repopulated by the
controller.
* 在需要时,复位 Bean 的属性值,此方法是在控制器重新组装Bean的属性值之前调用的。
*
* The default implementation does nothing. In practice, the only
properties
* that need to be reset are those which represent checkboxes on a
* session-scoped form. Otherwise, properties can be given initial values
* where the field is declared.
* 默认的实现,并没有做任何事。实际上,唯一需要重置的属性是那些基于
* session 作用域的复选框页面元素。否则这些元素将使用页面上声明的默认值。
* 是勾选还是未勾选。
*
* If the form is stored in session-scope so that values can be collected
* over multiple requests (a "wizard"), you must be very careful of
which properties,
* if any, are reset. As mentioned, session-scope checkboxes must be
reset to
* false for any page where this property is set. This is because the
client
* does not submit a checkbox value when it is clear (false).
* If a session-scoped checkbox is not proactively reset, it can never
be set to false.
* 假如表单是存贮在 Session 作用域中(如:
* <action
path="/shop/signon"
type="org.springframework.samples.jpetstore.web.struts.SignonAction"
* name="accountForm" scope="session"
validate="false">
* 即声明为 session 范围的 formBean)的话,表单元素的值可以在多个请求(即多页向导性页面)
* 中被收集,此时必须小心对等哪些输入域必须重置。象我们前面所述,session
* 作用域范围内的 checkbox(复选按钮),在为它们设置值之前必须重置为 false,
* 因为客户端(即浏览器)在复选按钮未被勾选时并不会发送任何值到服务器端。(否则,
* 就出现这样的问题:如果之前该复选按钮是勾选状态,并且用户请求这一页面
* 该按钮显示为勾选状态,在后续的操作中,用户取消选中状态。但是因为 checkbox
* 在取消选中状态后,浏览器并不发送任何关于这个控件的信息,但 ActionForm 中
* 要改变控制的状态,必须比较浏览器传上来的状态和当前状态,但因为浏览器并未
* 告知它,所以 ActionForm 认为这个控件的状态并未改变。因为从这时开始,无论
* 用户怎么做,这个控件将永远保持为选中状态)
*/
public void
reset(ActionMapping mapping, HttpServletRequest request) {
super.reset(mapping, request);
setUsername(null);
setPassword(null);
setRepeatedPassword(null);
// BUG here: by pprun
// 按照此方法的 api 文档说明,说 checkbox 的值必须在此复位,
//可是 NewAccountForm.jsp 中 Enable MyList 和 Enable MyBanner 却没有
// 所以当用户第一次选中后,以后想改为未选中是没门了,(除了象程序控制那样:
// 比如:
acctForm.getAccount().setDisplayMylist(
//
request.getParameter("account.displayMylist") != null);
// acctForm.getAccount().setDisplayBanner(
//
request.getParameter("account.displayBanner") != null);)
//
// 但是当输入错误时重新显示当前页面时,上次选为未选中状态被丢失了!
//
// 因为按照 api 的说明
// 当 checkbox 为未选中状态时,浏览器是不会发信息到服务器端的,所以
// struts 无法设置其值
// 解决办法:
if (getAccount() != null) {
getAccount().setDisplayMylist(false);
getAccount().setDisplayBanner(false);
}
}
}基于 JSTL 和 Struts HTML Tag 的 JSP
我们主要介绍一下JSP文件的总体结构。
由于此应用在表示层来讲,大体上还是属于 Demo 级别的,所以并未采用 Struts Tile
技术来对页面布局进行管理。而是使用传统的JSP表态包含指令,来包含进公共部分,如页眉,页脚及导航区域等。
所有以 Include 前缀命名的JSP都用来被其它JSP页面包含的页面块。例如:
<%@ include
file="IncludeTop.jsp" %>
页面的具体内容
<%@ include
file="IncludeBottom.jsp" %>
在 IncludeTop.jsp 中声明:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
<%@ taglib prefix="html" uri="http://jakarta.apache.org/struts/tags-html" %>
这样我们就不需要在所有用到JSTL的页面中重复声明。
同时,我们并没有使用 Struts 的 Bean 和 Logic 等标记库,因为在 Struts 网站上声明有:
Note: - Many of the features in this taglib are also
available in the
JavaServer Pages Standard Tag Library (JSTL). The Apache Struts
group encourages the use of the standard tags over the Struts specific
tags when possible.避免重复提交
避免重复提交是一项挑战性的工作,如果你曾经真正参与过一个基于 B/S 结构的项目的话,
甚至基于 C/S结构的界面也同样有这样的工作,正不过在那个领域叫做控制状态管理,
比如,当你按下一个登录按钮后,而按钮并没有变为disable/不可用状态,
你可能在不经意间又点了一次该按钮,那么在一瞬间你肯定登录了两次,这种情况还好,
因为登录并不伤害系统的其它情况,只不过统计系统或许会感觉到纳闷,
为什么在不到两秒钟内,你登录了两次?
但是如果这个操作是插入一条数据或者是删除一条数据呢?
对于插入一条数据,如果系统没设唯一性检查,则两条相同的数据生成了;
对于删除数据,则第二次删除必然会失败。
知道问题的重要性了,可是对B/S 开发人员来说,问题还不止这些:
1.典型的,网络状况不是很好时,为完成一个插入操作可有会等上好几十秒的时间,
用户此时会“再点”一次,还是会“回退”,甚至是忍无可忍关掉浏览器呢?
2. 对于回退,如果前一操作是删除操作,是否需要再次进行一次删除操作?
3. 如果用户收藏起了这一个进行删除或插入操作的URL,在他/她重新激活这一链接后,
该做何处理,如果这一操作需要授权呢?
我们要介绍的机制并不是完美的机制,事实上这些现实的问题并没有列入大多数的WEB
框架的设计议程中,所以做WEB应用开发是乏味的,甚至有时会让人冒火!Struts 的事务 Token
通过使用Struts 的事务Token 来防止重复提交是可行的,
仔细阅读org.apache.struts.action.Action中的如下方法的 javadoc
- generateToken
- saveToken
- isTokenValid
- resetToken
- <html:link
transaction="true"> If set to true, any current transaction
control token will be included in the generated hyperlink, so that it
will pass an isTokenValid() test in the receiving Action.
我们通过提交定单的例子来看这个事务 Token 的工作流:
我们的例子中,是要在显示确认页面中,如果点 'Continue' 按钮,会将一个定单插入到数据库中,
显然,我们需避免重复点击该按钮。
解决方案:
我们得看看这个过程的映射配置:
<!-- 进入结算中心页面后,点击继续进入此 -->
<action path="/shop/newOrderForm"
type="org.springframework.samples.jpetstore.web.struts.NewOrderFormAction"
name="workingOrderForm" scope="session" validate="false">
<forward name="success"
path="/WEB-INF/jsp/struts/NewOrderForm.jsp"/>
</action>
<!--
填写定单信息的多页向导式页面 -->
<!--
当第一页校验失败时,需要跳回填写购物单的第一页 -->
<action path="/shop/newOrderStep1"
type="org.springframework.samples.jpetstore.web.struts.NewOrderAction"
name="workingOrderForm" scope="session" validate="true"
input="/shop/newOrderForm.do">
<forward name="confirm"
path="/WEB-INF/jsp/struts/ConfirmOrder.jsp"/>
<forward name="shipping"
path="/WEB-INF/jsp/struts/ShippingForm.jsp"/>
</action>
<!--
(只有页面上填写了将宠物送到不同的地址时,默认为送到当前用户的地址),才会出现此面。
此页校验失败,毫无疑问应该回到这个新地址填写页,而不是整个流程的第一页。
这就是原版中的BUG所在处,因为它将这个向导性的流程处理放到了一个映射中,
所以没法处理这种情况 -->
<action
path="/shop/newOrderStep2"
type="org.springframework.samples.jpetstore.web.struts.NewOrderAction"
name="workingOrderForm" scope="session" validate="true"
input="/WEB-INF/jsp/struts/ShippingForm.jsp">
<forward name="confirm"
path="/WEB-INF/jsp/struts/ConfirmOrder.jsp"/>
</action>
<!--
当在最后一步确认时出错,需要跳回填写购物单的第一页 -->
<action
path="/shop/newOrderStep3"
type="org.springframework.samples.jpetstore.web.struts.NewOrderAction"
name="workingOrderForm" scope="session" validate="true"
input="/WEB-INF/jsp/struts/NewOrderForm.jsp">
<forward name="success" path="/WEB-INF/jsp/struts/ViewOrder.jsp"/>
</action>
1. 因为最后三个映射使用的是同一个 NewOrderAction,再有作重复提交检查就是在这个 Action 中,因此,不可能在这个Action 的 exeute 方法中调用 saveToken(request);,
一般来说,总是在进行重复提交检查的前一个Action 中放一个 Token, 即调用 saveToken(request);方法,因此根据这个流程,我们只能在 NewOrderFormAction
中生成:正如你可以在源码中看到一样:
//避免重复提交
saveToken(request);
return mapping.findForward("success");
2. 因为我们是要避免重复按 ConfirmOrder.jsp
中的 'Continue' 按钮,因此我们需要这样写:
<%-- prevent duplication submit --%>
<center><html:link
page="/shop/newOrderStep3.do?step=3&newOrder=true" transaction="true">
<img border="0"
src="../images/button_continue.gif" />
</html:link>
</center>
3. 最后,在处理的 Action 中(即 NewOrderAction) 进行有效性检查:
protected ActionForward doExecute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
if (!isTokenValid(request, false)
{
// 如果结果不是同一个令牌,为多重提交
//resetToken(request); // 判断完不自动销毁,留待下面的逻辑处理
request.setAttribute("message", "多重提交!");
request.getSession().removeAttribute("workingOrderForm");
request.getSession().removeAttribute("cartForm");
// Fixed by pprun for duplicate-submitand bug in the next time submit:
// 竟然不再需要确认了!
request.getSession().removeAttribute("orderForm");
return mapping.findForward("failure");
} else {
// 多页表单
OrderActionForm orderForm = (OrderActionForm) form;
// 是否要进入可选的 shipingAddress 页面
if
(orderForm.isShippingAddressRequired() && orderForm.getStep().equals("1")) {
// 需要将物品寄给别人,而不是自己
return mapping.findForward("shipping");
// 两种情况:
// 1.
从页面1直接进入确认页面(不需要寄到不同的地址时)
// 2. 从 shipingAddress
进入到确认页面
} else if
((orderForm.getStep().equals("1") && orderForm.isShippingAddressRequired() == false)
|| orderForm.getStep().equals("2")) {
// 进入确认页面
return mapping.findForward("confirm");
} else if (orderForm.getOrder() != null) {
// 最终处理
// 销毁事务标记(放在此处,最开始处很重要,
// 以保证不管再快的多重提交都会得到无效的判断的)
resetToken(request);
Order order = orderForm.getOrder();
// todo 这段逻辑应该放在 DAO 层?
getPetStore().insertOrder(order);
// 成功进行后,移除会话状态,
// 以便 NewOrderFormAction 中检查出是否用户后退操作
request.getSession().removeAttribute("workingOrderForm");
request.getSession().removeAttribute("cartForm");
// Fixed by pprun for duplicate-submit and bug in the next time submit:
// 竟然不再需要确认了!所以必须移除它
request.getSession().removeAttribute("orderForm");
request.setAttribute("order", order);
request.setAttribute("message", "Thank you, your order has been
submitted.");
// 选择 ViewOrder.jsp 中的显示方式
request.setAttribute("newOrder", true);
return mapping.findForward("success");
} else {
request.setAttribute("message",
"An error occurred processing your order (order was null).");
return mapping.findForward("failure");
}
}
}
调用 isTokenValid(request,false) 判断我们上述的 1, 2, 3 三处步骤是否是按顺序成功处理完,如果中途哪个步骤重新执行,比如在执行到第三步的 doExecute()的代码resetToken(request)之前,又来了一个请求,由于此时 Token 还在,未被 resetToken, 此时比较已经存在的 Token 和 link 带进的
Token,发现它们俩不同,因此isTokenValid(request,false)将返回 false,告之多重提交,并跳到错误页面。
我们之所以调用 isTokenValid(request, false) 这个方法并传一个 false是因为我们使用的向导页面,在这个判断之后到最终的确认页面还有一个或两个页面要处理,因此我们不能在判断完后,立即销毁 Token,而是要等到真正处理完时才这样做。但是对简单逻辑的页面,可以直接调用isTokenValid(request) 或isTokenValid(request,true) 在判断完后,直接销毁 Token.
我们还缺什么?
客户端校验
基于 JavaScript 的检验方式。Struts支持这种处理方式,只不过我们没有把这一功能加入进来而已。因为客户端检验可以在第一时间发现输入数据的问题,而不至于浪费一个数据传输来回(提交错误数
据 -> 在 FormBean 中判断为无效 -> 以错误信息的形式显示给用户)。
但是,请记住!
服务端校验是一定要做的,因为有人总喜欢在中途拦截、篡改客户发来的数据而骗过客户端的校验器。而服务端是发生在服务器上,只要服务器没被攻破,黑客是不
可能篡改这段 FormBean 代码的。
漂亮的页面
现在的页面只是个原型,离最终的漂亮还有段距离。但是这是需要美工设计人员介入的,因为一个人总不可能样样在行的。
总结
对于新手而言,看基于 Struts 的实现代码,有时的确会失去方向。此时,最好将 Strut-config.xml
文件打印一份在手边,然后对应页面上的每一个动作(提交,链接点击等)得到其要去往的URL,然后在Strut-config.xml 中找到对应的Action 映射。例如:
在 SignonForm.jsp 页面中有:
<a href="<c:url
value="/shop/newAccountForm.do"/>">
<img
border="0" src="../images/button_register_now.gif" />
</a>
于是我们在struts-config.xml 文件中搜索“/shop/newAccountForm” 找到:
<!-- 修改帐号信息 -->
<action path="/shop/newAccountForm"
type="org.springframework.samples.jpetstore.web.struts.NewAccountFormAction"
name="workingAccountForm"
scope="session" validate="false">
<forward name="success"
path="/WEB-INF/jsp/struts/NewAccountForm.jsp"/>
</action>
这样我们得知:
1. 在页面 SignonForm.jsp 中,如果点击了 注册 按钮的话,Struts 将使用 workingAccountForm
(即,类AccountActionForm) 来收集页面的即将的输入值,
2. validate="false" 所以这时不需要做任何校验,因为此时,用户还没输入数据,只是在
注册页面上点了“注册”按钮被带到了注册信息填写页面。
3. 执行 NewAccountFormAction#execute()方法,在成功处理后,将前进到页面 NewAccountForm.jsp
4. 用户输入用户信息数据
我们看到在 NewAccountForm.jsp 页面中有:
<html:form action="/shop/newAccount.do"
styleId="workingAccountForm" method="post" >
5. 我们再次在 struts-config.xml 文件中找 "/shop/newAccount", 得到
<action path="/shop/newAccount"
type="org.springframework.samples.jpetstore.web.struts.NewAccountAction"
name="workingAccountForm" scope="session" validate="true"
input="/WEB-INF/jsp/struts/NewAccountForm.jsp">
<forward name="success" path="/shop/index.do"/>
</action>
6. 这一次还是利用同一个 FormBean(已经在前面收集了用户的输入数据),
因为这一次 在NewAccountAction#execute()方法中要用到 前面的输入值.
7. 判断输入数据的合法性
如果不合法,将跳转到同一页面,但此时将显示错误信息
如果合法,则继续向前,这一次是回到首页,即这一流程宣告结束。
NetBeans 6.0 M9 (Preview) 已经出来好些天了,还剩下最后一个里程碑就要进入测试阶段。
对我来说,自从从 Oracle JDeveloper 转向 NetBeans 以来,在工作中我一直坚持用它。也许是的我工作表现迫使远在美国那边的同事放弃了说服我使用 Eclipse 吧。你也许想知道,作为一名NetBeans 的老用户,我期待 6.0 的什么,虽然它已经很好了。
1.不要因为整个 Editor 的体系重组,而使强“稳定性”的口碑打折扣 (基本上大部分模块都重新Retouche了),因为我拒绝使用 Eclipse 的原因之一就是: JVM OutOfMemoryError.
2.Occurrences Highlight 我在之前的文章中写过关于这一功能
3.Javadoc and Declaration View 我已经等了好几年,我甚至曾经自己利用 NetBeans 的API 实现过一个类似的模块,但是因为NetBeans本身的问题(java meta data record),功能不完整。有了这两个窗口,就永远不用 Go to Source, Show JavaDoc 了,所有的信息都在手边,只需将鼠标放在想看的类元素上。
4.Code Generation dialog 我的确很厌倦写类的构造器的实现,特别是类的成员很多的情况下。还有标准的、功能完善的、性能良好的 Common Methods: equals, hashcode 的实现等。
有了它,在右图中的例子中我只需要输入
private long id;
private String name;
private int age;
其它的代码都是由它产生的。
5. Local History
或许有些功能被我忽视了,如是这样的话,请见此处的详细列表。还有整个重写的 Editor 的功能都陆续地出现在这。
是的,我也保留些目前还未完善的功能,我本人也没有加紧试用。如果我认为有用的话,我会进一步写出来的。
update: (这个BUG只会在中文操作系统下出现,在英文版的操作系统上一切正常。看来是一些模块在编写时没有正确地加载对应locale 的 properties 文件)
在我看来,在日常的工作平台,JDK/NetBeans 的i18n 字体问题已经成为历史了。但是我前些天又登记了一个 BUG 到 NetBeans 的 IssueZilla 中:
1. 下载多语言版本的安装包,安装
2. 因为我不喜欢那些翻译的不准确的词,所以我打算回退到英文的 locale:
增加一个启动参数到 $NetBeans/etc/netbeans.conf 文件:
netbeans_default_options="$默认的配置 --locale en"
语法为: --locale language[:country[:variant]]
3. 重启后,你将看到“著名的字体问题”重新又出现了,显示为小方框:
当前,只有两种办法可以解决这一问题:
1. 去掉加上的 locale 参数,但必须忍受翻译得不佳的词了。
2. 下载英文版,继续用吧。但这样的话,在 Welcome 中你将看不到中文的 Blog.
如果你打算使用 GlassFish/Sun App Server,并且打算使用 MySql 的 XA 数据源的话。在目前的配置过程中,会遇到如下问题:
重现步骤:
1. (如果之前没做这一步的话)将 Mysql 的 Connector/J 包 (如我的:mysql-connector-java-3.1.12-bin.jar)放入 GlassFish/Sun App Server 安装目录下子目录 \AppServer\lib\ 中
2. 启动 GlassFish/Sun App Server. 可通过 右击 Runtime | Servers | Sun App Server 选择 start
3. 启动后,右击 Sun App Server 选择 View Admin console
4. 登录WEB 管理后台
5. 在左侧导航器中 点击 Resources | JDBC | Connection Pool s,在表格的头部点击 New... 按钮
6. 在右侧中填入:
Name: MySql
Resource Type: javax.sql.XADataSource
Database Vendor: mysql
然后点击 next
7. 注意在 Datasource class name 中自动填入了: com.mysql.jdbc.jdbc2.optional.MysqlXaConnectionPoolDataSource,这个值是不对的。
你如果想试试的话,在最下面的 Properties 窗格中填入 :
点击 Finish
8. 在结果窗口中点击 Mysql
9. 在打开的页面中可以看到一个ping 按钮,点击是用来测试配置成功与否,点击一下,将出现如下错误:
解决的办法:
如果解开mysql-connector-java-3.1.12-bin.jar 文件,在包com.mysql.jdbc.jdbc2.optional 中可 看到:
其中并没有默认填入的 com.mysql.jdbc.jdbc2.optional.MysqlXaConnectionPoolDataSource, 但是有 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
com/mysql/jdbc/jdbc2/optional/
com/mysql/jdbc/jdbc2/optional/CallableStatementWrapper.class
com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.class
com/mysql/jdbc/jdbc2/optional/MysqlConnectionPoolDataSource.class
com/mysql/jdbc/jdbc2/optional/MysqlDataSource.class
com/mysql/jdbc/jdbc2/optional/MysqlDataSourceFactory.class
com/mysql/jdbc/jdbc2/optional/MysqlPooledConnection.class
com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.class
com/mysql/jdbc/jdbc2/optional/MysqlXADataSource.class
com/mysql/jdbc/jdbc2/optional/MysqlXAException.class
com/mysql/jdbc/jdbc2/optional/MysqlXid.class
com/mysql/jdbc/jdbc2/optional/PreparedStatementWrapper.class
com/mysql/jdbc/jdbc2/optional/StatementWrapper.class
com/mysql/jdbc/jdbc2/optional/SuspendableXAConnection.class
...
在页面Application Server > Resources > JDBC > Connection Pools > MySql 中:
1.将 Datasource class name 的值改为: com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
2.点击 Save 按钮
3. 点击 Ping 按钮,成功显示:
不喜欢 NetBeans 的开发者往往指出 NetBeans 没有这个功能,没有那个功能。无可厚非,当时他们是对的,但随着时间的推移,现在也许错了:
1. Last Edit (是近更改按钮,带星号的那个),将你带到最近更改的地方
2. Diff SideBar (差异侧条), 根据所在行代码是增加、更改还是删除,在侧条中显示不同的小条,右击可以使用进一步的功能
3. JUnit4 支持(也就是现在可以使用基于 JDK 5 Annotation 的单元测试了)
4. Find/Replace in Project (全工程范围内搜索),是的,这个功能我真的也非常需要:
看到左下方的"Replace" 按钮了吗?
值得注意的是,这个功能在 M9 中被屏蔽了,但在每日构建的版本中可以使用。
![[nb-find-replace.png]](http://1.bp.blogspot.com/_GUaFO77rw-w/RcDNGbkZUrI/AAAAAAAAAAg/t_qTqZMw834/s1600/nb-find-replace.png)
另外,大部分初次使用NetBeans 的开发者,不知道更改“自动完成弹出窗口”的键绑定,因为最常用的"Ctrl + 空格" 是不可工作的,因为在中文操作系统中被绑定到输入法的切换了。所以我一般把它改成 'Ctrl + Enter' , 如下进行:
- Tools | Options -> Keymap -> Other
- 找到 Show Code Completion Popup, 选中它,点击Add...
- 按下任何所你希望的键序列,但是如果直接按 Ctrl + Enter 的话,系统提示这个组合键已经被绑定到 Split Line,所以如果我们要使用这个组合键的话,要先把它与 Split Line 解除绑定
- 在 Show Code completion Popup 下方第六个即是 Split Line, 选中它,点击移除。你可以为这个功能提供另外的组合键,如果经常使用这一功能的话。
- 然后,按照上述把"Ctrl + Enter " 加到 Show Code Completion Popup 中去。
(期待下一篇)
此篇文章介绍一个在 NetBeans 6 中同时查看鼠标指针处的源代码和
Javadoc (不再Go to Source .../ Show JavaDoc)
1. 首先打开它们:Window | Other | Declaration View 和 Window | Other | Javadoc View, 它们都被搁浅在 Output 窗口的位置,但此时只能看到一个窗口的内容,因为无论切换到其中的任何一个,它们都占据整个下端窗口。如下:
2. 我们要将它们分开,点击其中任一窗口的上方(类似标题栏区域),按住不放,将其拖向左侧(或右侧也可),当出现一个红色的方框后释放,如下:
释放后的效果如下:
这些位置会被记录下来,只要你在设置之后正常退出了。在下次启动 NetBeans 后,你可以看到同样的布局。
这个截图中显示的是 Integer.toHexString 方法的 Javadoc 和 实现源码。
(期待下一篇)
JSCP NetBeans 插件的作用
大家知道,SCP 广泛使用于SSH出现之前的 Unix 之类的平台上,它允许在 Client <-> Server 间进行双向的文件传输(ScpTo, ScpFrom)
JSCP NetBeans plugin 作为一个 TopComponet 插入到 NetBeans 的 Navigator 方位,通过 Tools | Java SCP 调用。
SCP 可进行文件双向传输的
- 向支持 SCP 的 Unix/Linux 服务器上传文件(ScpTo)
- 从支持SCP的 Unix/Linux 服务器获得文件(ScpFrom)
这两种工作模式是分别作为 JTabbedPane 的 两个 Tab 出现在 JScp 这个 TopComponent 中
JSCP NetBeans 插件的使用方法
安装 .NBM 文件
- Tools | Update Center
- 选择 Install Manually Downloaded Modules (.nbm Files) 后,点击 Next
- 点击 Add... , 在 Select Directory or .nbm Files 对话框中,导航到此插件的两个 .nbm 文件(com-jcraft-jsch.nbm 和 org.pprun-jscp.nbm),同时选中它们后点击 Ok
- 点击 Next
- 点击 Next
- 点击 Next, 在View Certificates and Install Modules 界面点击 Include 列下面的多选框中打上勾。界面将出现版权及插件签名信息。(如果你希望使用计算机的所有用户都使用这个插件,可以将在 Global 列下打勾)
- Finish, 不出意外,将显示插件更新界面。
- 等到NetBeans 的状态条中显示 Turing on modules... done. 后,点击 Tools 菜单,此时将在菜单最底端看到 Java SCP 菜单项,如下:
使用说明
前提条件:
- 保证网络可以访问到一台支持 SCP/ SSH1 的 Unix/Linux 服务器
- 保证具有以上服务器上的一个帐户并且对其中的一个目录具有“写”权限(如果你只使用 ScpFrom 的话,此项可选)
ScpTo (文件上传)
(如果还没打开 JScp Window 的话)通过 Tools | Java SCP 打开,它会出现在左下角并停靠在 Navigator 所在的窗口中,如下图所示:
- LocalFile 上传的文件,通过右边的按钮来选择
- User@Host 用户名和主机名(或IP地址) 的组合
- Password 上述用户的密码
- RemoteDir 上传的文件在服务器上放置的目录

请注意在输入的过程中,会动态对输入域的值进行校验,如下,桔色的字显示没有指定服务器主机名(或IP地址):

如果所有的输入都合法的话,按钮 Scp 将可用,点击它将进行网络传输,进度条指示这一过程:

如果一切正常,最终进度条将停止指示。反之,如果后台操作出现错误的话,错误将显示:

ScpFrom (文件下载)
(如果还没打开 JScp Window 的话)通过 Tools | Java SCP 打开,它会出现在左下角并停靠在 Navigator 所在的窗口中,如下图所示:
- User@Host 用户名和主机名(或IP地址) 的组合
- Password 上述用户的密码
- RemoteFile 要下载的服务器上的文件
- LocalDir 下载的文件放置的目录,通过右边的按钮来选择

如果所有的输入都合法的话,按钮 Scp 将可用,点击它将进行网络传输。
总结
自从 NetBeans 5.0 开始,编写基于 NetBeans 的插件或平台应用已经变得非常简单。对于新来者,最大的障碍无非是一些NetBeans专用的术语及早期遗留下来的几个不大好理解的概念。不过还好, NetBeans 自己在快速前进的同时并没有忘记为开发者提供便利。
NetBeans wiki 是各种信息的大轮盘
planetnetbeans 则是全世界NetBeans开发者的乐园。大家为了 NetBeans 开怀畅谈。
Geertjan's Weblog 不得不看
文档内容
- 概览
- 获得工程代码
- 配置
- 数据库初始化
- MySQL 5.x
- Oracle 9i, 10g, HsqlDB, Postgres 及其它
- 应用服务器初始化
- 本地数据源(非JNDI 数据源)
- Tomcat 5.x,
- Sun Application Server8.x, 9.x / GlassFish 1.x, 2.x
- Jetty 6.1.3
- JNDI 数据源
- Sun Application Server8.x, 9.x / GlassFish 1.x, 2.x
- JBoss 4.0.4 +
- Jetty 6.1.3
- 部署并运行
- 总结
这个过程还是比较烦的,况且老外们的工作效率普通不如我们,每次交流至少等上一周左右才有回应。试想申请、审批,确认,上载等过程,其实令我这个急性子试 图想把自己家里的电脑搬到主机托管中心,申请一个域名了事!
还好,它终于出来了 (hjpetstore)!但愿没让你失望。
在阅读本篇文章之前,请先仔细阅读前面系列的相关内容。
概览
对于传统的J2EE 项目,当项目开发完后,其工作并未结束,紧接着的部署过程其实是很令开发者头痛的,特别是象重量级的应用服务 WebLogic, WebSphere 等。还好 NetBeans 现在抬简化了这一过程。我们这个例子是基于无存在数据库的方案,所以在我们演示结果前,我们将要导入一些数据。但首先我们得创建相应的数据库用户和数据库方案(Schema).
获得工程代码
1.从 hjpetstore 得到工程源代码,具体的步骤网站上有说明,在 NetBeans 中就很简单了:CVS | checkout:
cvs root: :pserver:username@cvs.dev.java.net:/cvs (这个 username 是你必须到 java.net 上注册的用户名称,目前 anonymous 好象不能工作了)
password:
下一页中, module: hjpetstore 下载完后,NetBeans 会问你是否打开该工程,选择是。
2. 你可能需要调整一下lib 的位置,这是 NetBeans 的一个缺陷,保存的路径不是相对路径。
右击工程 | properties
点 Libraries,在Compile 页中将所有 .jar 文件 选中后 'remove',
再加入下载下来的WEB-INF/lib 目录下的所有 jar 文件
3. 确保 Clean And Build project 成功
配置
数据库初始化
我这里只介绍 MySql 的 配置,其它的数据库配置列作 TBD. (待做,其实大部分脚本已经在工程中了,等待你的加入吧!因为我不是一个数据库专家,也没有太多时间去研究这个。)我成功配置过oracle 和 hsqldb.注 意:因为下面的脚本会删除 'hjpetstore'数据库用户及其所有资源,请确保用户 'hjpetstore' (oracle) 或数据库 hjpetstore (mysql) 目前没被使用,如果使用了,请修改数据库脚本。所以最好的办法是使用你的个人数据库来作演示。
MySQL 5.x
1. 创建用户hjpetstore 和 数据库 hjpetstore
# 在命令行下以 root 身份运行创建脚本
# $hjpetstore 是用真实的工程路径代替
# 其它值根据你的设置作相应的改变,比如你如果连非本机的数据库,那 'localhost' 就是那个机器在 ip 了
> mysql -h localhost -u root -p < $hjpetstore\conf\jpetstore_mysql.sql Enter password: ******** 如果程序的输出显示了 hjpetstore, 则表明成功了: Database information_schema
hjpetstore
mysql
...
或者,如果有mysql query browser 的话,用它直接运行如下命令也可:
-- frist drop database hjpetstore and user hjpetstore
drop database if exists hjpetstore;
create database hjpetstore;
-- create user hjpetstore and give the password hjpetstore
grant all privileges on hjpetstore.* to hjpetstore identified by 'hjpetstore';
show databases;
2. 得用 hibernate.hbm2ddl.auto 自动生成数据库方案
确保 web/WEB-INF/dataAccessContext-hibernate.xml 中 设置了 update
这个属性的具体含义,我在前面的系列中已经讲过了,在产品初始化,你就可以安全地把它注释掉。
3. 在 NetBeans 右击工程 Run project
这一步将所有的数据库表创建出来, 只是没有数据。
4. 加裁数据
使用 NetBeans Sql Editor
4.1 注册mysql 驱动
Runtime | DataBases 右击 -> new Driver
Add ... -> 导航到工程WEB-INF/lib/下的 mysql-connector-java-3.1.12-bin 点 OK
4.2 创建连接
右击刚注册的驱动 MySql (Connector/J driver) -> Connect using ....
Database URL: jdbc:mysql://localhost:3306/hjpetstore?useUnicode=true&characterEncoding=UTF-8
user name: hjpetstore
password: hjpetstore
点 Ok 后,在Databases 下应该会出现一个新的连接。
4.3 执行 SQL 脚本
1. 在 Files 窗口中导航到 db/mhsql/jpetstore-mysql-dataload.sql 并双击打开它
2. 在编辑器的工具条中 Connection: 选择 刚创建的数据库连接:jdbc:mysql://localhost:3306/hjpetstore?useUnicode=true&amp;amp;amp;amp;amp;amp;amp;ampamp;characterEncoding=UTF-8
3. 点击编辑器工具条上,紧挨着下拉框的 run sql
确保没有显示错误信息。
Oracle 9i, 10g, HsqlDB, Postgres 及其它
数据库脚本都已经在工程中了,你所要做的就是利用这些数据库提供的工具创建一个用户 'hjpetstore',
之后的步骤与上述相同。
应用服务器初始化
本地数据源(非JNDI 数据源)
Tomcat 5.x,
事实上,工程默认是使用 Tomcat 服务器的,所以现在你根本不需要改动什么就可以运行工程了。
有关数据源的配置是在 web/META-INF/ context.xml 文件中
Sun Application Server8.x, 9.x / GlassFish 1.x, 2.x
同样的配置,只不过要生成一个 sun-web.xml 文件,
很好,NetBeans 会帮你自动产生,如下:
右击工程 -> Run | Server: 选择注册的Sun App Server (如果你还没注册 Sun App Server 的话,你需要先注册一下,具体步骤见相关文档)
此时,文件已经产生,右击工程 -> Run Project
Jetty 6.1.3
所有的配置文件已经在 WEB-INF 下了: jetty-web.xml, jetty-env.xml, 所以要做的只剩下将dist 上下生成的 hibernateJpetstore.war
放到 Jetty 的部署目录,还好这个目录跟 Tomcat 的目录同名叫 webapps
在 Jetty 目录下运行:
java -jar start.jar
然后在浏览器中请求: http://localhost:8080/hjpetstore/
JNDI 数据源
使用JNDI数据源当然是为了使用其 JTA(包容器管理的事务及其数据库连接池的实现),
只需要按正确的名称 jdbc/hjpetstore 在管理界面配好数据库连接池和相应的数据源,运行起来还是挺方便的,
Sun Application Server8.x, 9.x / GlassFish 1.x, 2.x
1. 首先按照这篇文章介绍的步骤正确配置 mysql 数据源连接池
(中文) http://pprun.blogspot.com/2007/05/glassfishsun-app-server.html
(English) http://enpprun.blogspot.com/2007/05/problem-in-setting-mysql-xa-datasource.html
注意,我文章中介绍的是使用root/root 作为用户名/密码,此时可以设置成hjpetstore/hjpetstore
2. 配置数据源
在应用服务器的 管理 界面 导航Resources | JDBC | JDBC Resources
点击右边主页面中的 new 后进入配置页面,填入:
JNDI Name: jdbc/hjpetstore
Pool Name: 选择前面配置的数据源:连接池:mysql
完成后点击 Ok
JBoss 4.0.4 +
1. 使用 JBoss 也许是冲着所谓的 #1 应用服务器而来的吧,但其配置有一些变化:
第一它实现了自己的一套日志方式,所以需要把 web.xml 中的
org.springframework.web.util.Log4jConfigListener
注释掉。
2. 它的数据源的配法也不相同,只需要将相应的数据库的配置文件(如:mysql-ds.xml ,内容见随后)放到
jboss-4.0.4.GA\server\default\deploy 目录下,
再在 jboss-4.0.4.GA\server\default\conf\login-config.xml 中加入:
<application-policy name = "MySqlDbRealm">mysql-ds.xml 相应的内容如下:
<authentication>
<login-module code
= "org.jboss.resource.security.ConfiguredIdentityLoginModule" flag =
"required">
<module-option name ="principal">hjpetstore</module-option>
<module-option name ="userName">hjpetstore</module-option>
<module-option name ="password">hjpetstore</module-option>
<module-option name
="managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=hjpetstore-mysql</module-option>
</login-module>
</authentication>
</application-policy>
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>hjpetstore-mysql</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/hjpetstore</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>hjpetstore</user-name>
<password>hjpetstore</password>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
<!-- should only be used on drivers after 3.22.1 with "ping" support
<valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name>
-->
<!-- sql to call when
connection is created
<new-connection-sql>some arbitrary sql</new-connection-sql>
-->
<!-- sql to call on an
existing pooled connection when it is obtained from pool -
MySQLValidConnectionChecker is preferred for newer drivers
<check-valid-connection-sql>some arbitrary
sql</check-valid-connection-sql>
-->
<!-- corresponding
type-mapping in the standardjbosscmp-jdbc.xml (optional for ejb) -->
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>
3. 还有,就是JBoss 的 JNDI 的名称有些怪:
<bean id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<!-- JBoss
-->
<property name="jndiName" value="java:/hjpetstore-mysql">
<!-- other standard Java EE server
<property name="jndiName"
value="java:comp/env/jdbc/hjpetstore">
-->
</bean>
看到区别了吗?它只需要java:/hjpetstore-mysql
Jetty 6.1.3
目前,还未测试成功!
部署并运行
在 NetBeans 中,只需要在 工程属性中选定所要运行的 服务器后,点 Run Project 即可运行在本地数据源配置上。
此外,还可以按照服务指定的自动部署目录,将生成的 dist/hibernateJpetstore.war 文件放到该目录,
如果服务器已经运行,一切就 ok 了,如果没有,启动服务器即可。
如果要运行在 JNDI 配置上,则需要改一下 web.xml :
<!--
- Location of the XML file that defines the root
application context.
- Applied by ContextLoaderServlet.
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<!-- local datasource -->
<param-value>
/WEB-INF/dataAccessContext-hibernate.xml
/WEB-INF/applicationContext.xml
</param-value>
<!-- jndi datasource and JTA (for a transactional
JNDI DataSource)
<param-value>
/WEB-INF/dataAccessContext-hibernate-jndi.xml
/WEB-INF/applicationContext.xml
</param-value>
-->
</context-param>
这几行配置说的应该很明白了,上面的是默认情况下的本地数据源,如果使用JNDI数据源,是这样了:
<context-param>
<param-name>contextConfigLocation</param-name>
<!-- jndi datasource and JTA (for a
transactional JNDI DataSource) -->
<param-value>
/WEB-INF/dataAccessContext-hibernate-jndi.xml
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
只要按照上述的步骤配置好了应用服务器的数据源,现在运行的效果应该跟本地数据源是一样的。
总结
NetBeans 对于 Java EE 的开发是全面的,除了几个服务器还未集成进来之外,其它的功能已经走在了所有IDE的最前列,
但这也不防碍开发者使用这些未集成的服务器,因为大部分服务器都支持热部署,当NetBeans 给你的工程生成了 WAR 文件后,
剩下的就是“将它放入热部署目录”了。
看运行在 Jetty6.1.3 上的效果 (注意脚注部分显示,当前运行在什么服务器上):
经过“漫长”的等待,beta1 终于出来了!其实我一直在用它的最近的 daily build, 因为 M10 实在是太不稳定了。
摘要: 显示GIF图片一直是swing的诟病,本文给出一个用swing处理gif类型图片的参考实现 阅读全文
![]()
尽管这一版 6.5 一直在“鼓吹”给 PHP 的朋友听,
但是NetBeans team 还是没有忘本,有关JAVA IDE 的特征也不少:
NetBeans IDE 6.5 Release Client - New and Noteworthy
6.5 Release Information
下面这些是我个人比较喜欢的:
- Automatic Compile on Save
- Improved Eclipse project import and synchronization
- Java Call Hierarchy
- Analyze Javadoc
- CamelCase code completion
- Customize formatting settings per project
- Enhanced support for Spring, Hibernate
- New multi-threaded debugging with improved UI and work-flow
Have fun!
依次执行如下命令
C:\Documents and Settings\pprun>ver
Microsoft Windows XP [版本 5.1.2600]
C:\Documents and Settings\pprun>java -version
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) Client VM (build 11.0-b15, mixed mode, sharing)
C:\Documents and Settings\pprun>java -Xmx2048m -version
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
2 G 内存,很新鲜吗?
我刚加了一条,才百多块。
然而,直到我试到 1446 这个可爱的幸运数字时,才成功:
C:\Documents and Settings\pprun>java -Xmx1447m -version
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
C:\Documents and Settings\pprun>java -Xmx1446m -version
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) Client VM (build 11.0-b15, mixed mode)
我立即切换到 Ubunut8.04,进行了一下测试:
pprun@pprun-t61:~$ uname -r
2.6.24-21-generic
pprun@pprun-t61:~$ sudo lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 8.04.1
Release: 8.04
Codename: hardy
pprun@pprun-t61:~$ java -Xmx3072m -version
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) Server VM (build 11.0-b15, mixed mode)
pprun@pprun-t61:~$ java -Xmx3722m -version
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) Server VM (build 11.0-b15, mixed mode)
pprun@pprun-t61:~$ java -Xmx3723m -version
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
是不是 JAVA 也赞成 Windows XP 黑屏?
竟然不能够分配超过 1446m (1.446g) 内存堆!
摘要: 一、NetBeans 教程系列:
NetBeans6.1 入门教程系列(1)--- 数据库的基本操作
NetBeans6.1 入门教程系列(2)--- 数据库的设计查询以及创建视图 阅读全文
Python in Netbeans is a go!!!!

After
a 6 months of development. nbPython has been given the green light to
be release as the official python build for Netbeans. The EA release
will be released with Netbeans6.5. This feels like a real achievement
for us. I would like to thank all the people who made this possable:
- Ted Leung
- Tor Norbye
- Frank Wierzbicki
- Jean-Yves Mengant
- Amit Saha
- The rest of the nbPython Development team
- Netbeans QA Team
Most of all the user community, With out you this would have been all for nothing.
摘要: 用过MS SQL的朋友都知道他有个视图设计器,可以很方便的创建视图。在NetBeans6.1 中也有这样的功能。大家看看截图: 阅读全文
摘要: 用了Linux 突然间想写点C的程序,大家都说GTK 好用,所以就拿GTK 作实验。
第一步:搭建开发环境
1.gcc和java,这个应该不难,一般的发行版里都有gcc,Java可以到www.sun.com下载,安装配置,google 一下到处都是。
2.到www.netbeans.org 下载netbeans IDE ,有专门的C++ 版。
3.Gtk+可以直接安装libgtk2.0-dev软件包,也可以从http://www.gtk.org/下载源码,编译安装。可能需要其他依赖的软件包如下:
* pkg-config
* GNU make
* JPEG, PNG and TIFF image libraries
* FreeType
* fontconfig
* GNU libiconv library
* GNU gettext
* GLib
* Pango
* ATK
阅读全文
摘要: 关键字: swinghacks,swing
接着上次的进度,上次写完了背景,
SwingHacks学习笔记(1)-----自定义JPanel(一个以图像填充的组件)
现在可以考虑标签和按钮了。
这个标签是位于背景上的某个位置的静态图像。
例1.3:一个图像标签类 阅读全文
测试ScribeFire 工具,如果好用,以后就用他了。linux 下用这个很方便。这个Firefox 的拓展 很不错。
摘要: Swing 自定义组件系列-SwingHacks学习笔记(1)
一、自定义JPanel(一个以图像填充的组件)
例1.1 :一个JPanel 的定制子类
ImagePanel.java: 阅读全文
摘要: 以前用过ubuntu ,但是对我的机器支持的不好,特别是显卡,于是换了块显卡,ubuntu 还是不支持,装了受限驱动,屏幕的分辨率又有问题,真是拿他没办法,于是换了现在的Everest (珠穆朗玛峰) linux,安装完以后默认没有3d驱动,但是屏幕不闪,至少眼睛不疼了(Ubuntu 下就不行了,安装完驱动,刷新率只有61,看得我眼睛疼)。更新源里的显卡驱动相对老了点,于是到官方下了个最新的驱动,安装完以后,3d 就能打开了,而且一点也不卡。眼睛舒服多了。 阅读全文
摘要: 最近在重构自己的小Demo 想把自己的下Demo 变成可以配置的程序。但是遇到了一些困难,走了不少的弯路,最终还是解决了。 如果你是个牛人,你不用看了,写这些东西是给和我一样的菜鸟看的。
先说说我的Demo吧,我写的是一个简单新闻管理系统,很简陋的那种,不过麻雀虽小,但是五脏俱全。
基本的增、删、查、改,都有,用到了FCKeditor。一开始我连接数据库用的是最原始的方法,把数据库的连接信息全写在代码里,写完以后就没去管他了,十一放假这几天,看了看自己的代码,觉得代码结果不好,于是就开始重构自己的代码,首先就是重写数据库的连接管理我把连接数据库的一些基本信息写到了 database.properties 文件里,然后从程序中读取连接数据库所需要的信息。但是看似简单的东西,比且很容易的完成的工作,我却遇到了不少麻烦。首先就是路径的问题,其次是该以何种方式读取;就这两个问题困扰了两天。(呵呵,见笑了) 阅读全文
摘要: What is freeform?
Freeform is a NetBeans project type that allows you to use Ant build script supplied with your sources. Typical usecase can be that you have already some sources, you are developing them "in you own way" (other IDE, or using VI, or...) and you want to work on them using NetBeans. Other common usecase for free-form can be that you check out some opensource project and you want to work on it in NetBeans IDE. 阅读全文
The MySQL community -- who create, maintain and support the leading
free database -- are raising funds for Andrii Nikitin, a MySQL support
engineer in Ukraine whose little boy, Ivan, needs a $400,000
bone-barrow transplant.
"My family got bad news - doctors said allogenic bone marrow transplantation is the only chance for my son Ivan.
"8 months of heavy and expensive immune suppression brought some positive results so we hoped that recovering is just question of time.
"Ivan is very brave boy - not every human meets so much suffering during whole life, like Ivan already met in his 2,5 years. But long road is still in front of us to get full recover - we are ready to come it through.
"Ukrainian clinics have no technical possibility to do such complex operation, so we need 150-250K EUR for Israel or European or US clinic. The final decision will be made considering amount we able to find. Perhaps my family is able to get ~60% of that by selling the flat where parents leave and some other goods, but we still require external help."
摘要: 这里推荐3个 blog :
* Chris Oliver's Weblog
* Jim Weaver's JavaFX Blog
* Joshua Marinacci's Blog
顺便贴几张JavaFX demo 截图:
阅读全文
摘要: 这个不是最终版,想尝鲜的朋友可以到官方 网站上下载了!
更新:最经中文的好像没了,大家还是下载英文的吧。Netbeas 已经开始做语言包插件了
相信很快就会出来了。
http://bits.netbeans.org/download/trunk/nightly/latest/ml/?pagelang=zh_CN
NetBeans 6.5 带来很多新的特性,大家可以尝试一下,说不定 你就会喜欢上他的。呵呵!
下面是NetBeans 6.5 中新增的特性以及 增强的功能 一览表:
http://wiki.netbeans.org/NewAndNoteWorthyMilestone1NB65
http://wiki.netbeans.org/NewAndNoteWorthyMilestone2NB65 阅读全文
今天真是很不顺啊,不是停电就是 登不上论坛,害我想写点东西都没心情了。幸好宿舍晚上不熄灯,可以让我在下半夜写东西。唉!明天要睡一个早上了!
结识NetBeans 是在2007 年五月份,那时候自己刚开始自学java ,一开始用的是最原始的方法NotePad2 + JDK
。后来看到csdn 上关于NetBeans的插件开发教程,才开始接触NetBeans的,那个时候NetBeans是5.5.1
版本。在下载了视频教程看以后,我就到官方网站下载了NetBeans,感觉NetBeans太棒了,特别是GUI
设计,当时感觉太神奇了,那么快就可以建立一个桌面应用程序。后来自己对java 学的相对有点进阶的时候,发现自己对NetBeans
的了解也更深了点,应该说是NetBeans的的操作更熟练了,为了学习NetBeans的操作,我把csdn
上的所有视频教程都下载来看。直到NetBeans6.0 的发布。我才真正有点了解NetBeans。说到这里有人会说了“ NetBeans
不过就是个开发工具嘛!至于要那样努力学吗?不要本末倒置了!“ 对于这句话,我想说的是: 一个语言如何,从用它写的IDE
里就可以看出不少东西来,我记得国外有一篇博客就讲到”The IDE is the Language!“ 。因为我对java
比较喜欢,特别是Swing ,用Siwng
开发桌面应用,我感觉自己很有成就感,特别是我写出我自己的第一个桌面应用程序,当初学C语言的时候就想写一些GUI
的程序,但是我当时不知道原来有很多的C 的拓展库,原因是我刚接触C 语言的时候用的是TC2.0 只能写控制台程序,不能写GUI
程序。感觉学习C语言满足不了我的要求,于是就开始自学java。
学习了一些java基本知识之后感觉
java 比C
简单多了。而且还能很快的写出GUI程序。这是我一直想要做的事情。之后对java的了解更进一步点,开始到个大论坛去转,看到了不少的好东西,学到了很
多。最初接触的是csdn 的论坛,后来时Javaeye上的论坛。还有一些其他的论坛我就不说了,去的比较少,现在基本上都在Javaeye
上潜水了,我发现Javaeye上的牛人特多,我是不敢轻易在论坛上发言,感觉自己的水平还不够,所以更多的时间是在潜水。
NetBeans 6.0 出来
以后,我就第一时间下载了,按照官方的例子做了一些Demo ,感觉太棒了。因为官方上的教程大部分都是英文的,所以也就促使我
更加努力的学习英语,争取能够明白教程上讲的是什么。 现在让我看一些英语的blog ,已经不是太困难了,自从我把自己的blog 加入到www.planetnetbeans.org (NetBeans 星球) 里以后我就经常的关顾这个网站,看到了不少的好文章。学到了不少东西。
从我开始接触NetBeans到现
在,NetBeans 经历了5.5.1,6.0,6.1 还有现在的6.5
,一路走来感觉NetBeans的进步太多了,无论从速度上,还是从代码编辑器上,以及对不同语言的支持上,都有长足的进步。真的很感谢NetBeans
团队,让我们能用上这么好的IDE 。在接触NetBeans的同时我也接触了Eclipse
,网上有很多关于NetBeans和Eclipse的比较文章,感觉有的很片面,比较的不是很客观。有很多人把NetBeans 和那些
收费的Eclipse进行对比,这对NetBeans 是很不公平的,他们都要求NetBeans 要比那些收费的Eclipse
插件更好用才会说NetBeans 好用。
还有的是说NetBeans的启动速度慢,从我用Eclipse的经验来看,Eclipse的启动速度在3.3之前都比NetBeans快一点,当不是很
多。在不同的机器,不同的操作系统上的表现也不一样,在Windows 下,Eclipse
可能要快一点,但是到了Linux下就变了。NetBeans 绝对比Eclipse 快。Eclipse 3.4
发布有一段时间了,我发现他的启动速度真是不敢恭维,比NetBeans 还要慢!我的机器CPU AMD 闪龙3000+ 1.6GHZ ,960
M的内存,跑Eclipse3.4 比跑NetBeans6.1 要卡的多,特别是builde 几个项目以后。最新的NetBeans6.5
也试用了几天,感觉上比NetBeans6.1 又快了一点。对项目的扫描也更快了,内存占用也降低了,NetBeans 真是越来越好用了。
今天比较晚了,明天在接着写吧。看看时间已经凌晨4:19分了。现在已经是8月15 了!!祝大家中秋节快乐!!
先让大家看看效果图吧:

中文版的NetBeans 外观:

还不错吧,只是有点遗憾的是标题栏没有改变!如果标题栏也改变了,那就完美了!如果谁有更好的方法
不妨留言交流一下!共同学习!
具体的方法是:启动NetBeans 的时候添加启动参数
netbeans -cp:p D:/NBpro/quaqua.jar --laf ch.randelshofer.quaqua.QuaquaLookAndFeel
红色部分表示的是你的laf jar包所在文件夹。quaqua jar包 点击这里下载
用这种方法还可以设置其它的外观,不仅如此,这样还修正了NetBeans在Windows 默认的主题下
显示的问题(第一张图片红色框框部分)
具体内容你们也可以看看这篇博客:http://mrhaki.blogspot.com/2008/09/using-jtattoo-look-and-feel-with.html
摘要: 这个是sun 官方论坛里的一个主题贴,这个帖子很有代表性,他回答了大部分Flash 开发人员的问题.
下面是问题和解答的详细内容: 阅读全文
简介:
SwingDesigner 是用Eclipse开发的 一款免费的、开源的、功能上与Mattise Project相近的界面设计工具插件. 他可以简化您开发应用程序的步骤,缩短开Swing于VE(Eclipse的另一款插件),每个组件用一个getXXX返回,代码可读性很强,而且开发者可以自由修改代码,保存后保持和界面同步更新.Designer 发周期.它具有很多Mattise 所不具有的功能. 生成的代码也没有NetBeans 生成的代码那样复杂, 这个工具不需要form文件,生成的代码也是类似
开发工具 : Eclipse3.4
JDK版本 : JDK 1.6 (NimbusLookAndFeel 需要JDK1.6 u10)或更高
开发平台 : Windows XP SP2
开发动机:(为什么是基于Eclipse的SwingDesigner?)
一直以来非常喜欢Swing,对Swing的研究也有很长一段时间了,一直希望Swing在Java桌面开发中扮演重要的角色。但是很久以来Java桌面开发始终是个弱项,其中很大一部分原因是缺乏比较好用的界面设计工具。
NetBeans的界面设计工具(以前叫Matisse Project)的出现给Java的Gui开发尤其是Swing开发带来了希望,但遗憾的是当前Java集成开发环境仍然是Eclipse的天下,据统计,目前市场上至少2/3的份额是被eclipse占有。虽然netbeans已经获得长足的进步,并进一步吸引了更多的developer,但是由于历史习惯和遗留系统等等问题,这个市场份额在最近几年肯定还是eclipse的天下。
当然eclipse也有很多很优秀的界面工具插件,可惜的是免费的插件其质量难以与netbeans的匹敌,好用的插件又都是收费的。因此一直想为eclipse开发一款免费的、开源的、功能上与Mattise Project相近的界面设计工具,算是为Swing的发展做一点贡献。
从今年1月份开始,我来到一家新公司,主要做基于eclipse插件平台的开发,得以学习了eclipse的插件开发知识。以前曾经使用 swing做过一个swing的界面设计工具,但由于是一款独立的工具,没有集成到任何IDE中,因此几乎没有实用价值。因此决定在闲暇时间将这个工具重新用eclipse插件技术进行开发。
开发这款工具的目标计划:
1. 界面布局模仿Netbeans界面设计工具,操作和netbeans设计工具基本一模一样,容易直观的实现布局。这是第一目标。目前已经实现。
2. 代码的生成和解析不需要辅助form文件,直接从源代码文件进行解析生成。生成代码可读性要强,要可以编辑并且同步。目前已经基本实现,有些折中处理,采用约定代替配置的办法提高代码解析速度。
3. 直接支持树和表的界面设计,不需要写代码,直观的采用界面操作,便可以直接生成表和树的数据模型代码。此功能已经实现。而且目前的框架可以很容易扩展,实现类似其他复杂组件的界面设计。
4. 工具的性能良好,界面设计功能流畅,代码解析/生成速度快。目前来看,速度和性能还不错,初步的打算是将速度放在最后处理优化。
5.支持在设计时切换LookAndFeel,并能生成所设定LookAndFeel的代码。这样就能做到设计时和运行时完全一致。而NetBeans的设计工具只能以NetBeans自身相同的LookAndFeel设计,然后使用另外的LookAndFeel预览。
6.更多的特性 将在以后的版本中添加.
代码位置
http://code.google.com/p/visualswing4eclipse/
授权方式:
本工具使用的是LGPL授权方式。照顾商业利用和开源改进而采用此授权。
目前支持的Eclipse平台是3.4,JDK请使用1.6
联系方式:
Msn : rehte @ hotmail . com
常见问题解答:
1、变量命名为什么是$nameLabel这样的,是为了读取方便么?
Re:这儿是netbeans form解析法和VE的AST语法数解析法的一个折中,提高解析速度,降低
解析复杂度,同时有抛弃了form文件的一个折中办法,被设计的界面组件的field名称需要以$作为识别,当然这个$是可以替换的。目前还没有做这一步。
2、方法名字为什么是changeBtn_action_actionPerformed这样的,不符合java的规范,有配置可以改么?
Re:这个以后会增加配置进行配置,但目前太多其他的细化工作要做,本人精力实在有限。
3、我这里用的英文版的eclipse3.4,改变变量时,确认和取消按钮为乱码,没有国际化支持么?
Re:目前只是出于功能实现阶段,国际化还没有考虑,不过eclipse的国际化是很简单的事情,打算把它作为最后阶段解决的问题。
4、netbeans中双击button可以直接生成action调用方法,希望也提供这个功能。
Re:这个没有问题。只不过这儿双击是调出in-place editor来实地编辑组件值。比如双击Table和tree能够调出直接编辑表格和树的设计器。
5、怎么没有直接切换到代码的视图,还有到了代码后我直接 运行 怎么出来不了东西。。?
Re:目前不好用是因为功能还没有完全完成。很正常,因此我把版本定在0.9.0,甚至应该更低,但是目前大部分功能框架和实现已经完成,缺少只是细化,所以我希望对于Swing和SWT以及Eclipse RCP开发功底比较深的人能够加入进来,帮助完善。
开发步骤:
1、新建一个Java工程
2、安装插件以后,在New Class Wizard中可以发现一个Visual Swing Class,选择该项以生成可视化JPanel,目前只支持JPanel,以后可以很容易扩展,会有更多的支持。
初始化界面
目前完成的特性截图:
下面是一个典型的设计界面的场景,红框标出的是该插件提供的视图和按钮,支持LookAndFeel切换:
这儿是拖拽组件时显示布局提示,和netbeans的界面布局设计类似:
这是生成的源代码,可以直接修改源代码,保存后,会自动同步的到设计界面上去:
这是一个表格的设计器,你可以直接在界面上拖拽,添加删除编辑表格:
这是一个树的设计器,你可以直观的添加删除编辑树的节点:
多LookAndFeel同时设计的抓图,含有NimbusLookAndFeel
NimbusLookAndFeel显得得体大方,字体也很好看,图标精致,组件显得既圆润而又不过分华丽。不知你注意没有,新的Java2D的字体渲染是使用本地渲染库渲染的,已经完全和本地程序的字体一模一样的。的确不错:)
今天我下载了NetBeans6.5 的每日更新版,感觉和beta版又有些不同了,好像修复了1600多个bug,
下面是一篇blog上的内容!
and if you try a recent build, you can notice that there was fixed many issues.
In Issuezilla there are more then 1600 fixed issues during last three weeks.
I would like to hihglight some improvements in PHP support:
* The performence of code completion was significantly improved.
* The editor has about 40 fixes since the beta.
The code completion is more context sensitive and it is able to offer more precise results.
* There was also improved the navigation functionality.
Fixes in the PHP Navigator, Hyperlink and also implementation of Go To Symbol was added.
* Fixes in the project and debugger.
* Small improvements in FTP support.
Over all there are still things which can be fixed and improved. I would like to thanks to all,
who tried the PHP support in NetBeans and entered an issue. We have a few more weeks to stabilizing
and fixing. Thanks for your help.
具体大家可以自己到NetBeans星球博客看看。
NetBeans6.5 增强了项目导入的功能,导入功能不再单一的显示黄色的图标而是不同项目显示的图标

Eclipse 项目的导入功能也增强了,不要在为把Eclipse项目导入到NetBeans 中感到头痛了!下面
是引用只NetBeans wiki 上的一幅图片。

还有增强的Subversion 客服端,这个是NetBeans 最新的Subversion 客户端!
下面是一段blog的原文:
We only have to go to Tools | Options | Miscellaneous | Versioning | Subversion.
There we have a input field Specify the SVN home folder with a Browse button.
Here we can specify where we installed our latest Subversion client software.

摘要: 假期终于结束了! 面临毕业的时间越来越近了!时间真的过的好快啊! 今天发一个上个学期期末的时候写的关于如何使用NetBeans来管理数据的文章,也是 号召志愿者合写一本开源免费的Netbeans 6.1 教程
这个计划的第一篇文章,肯定有一些不足之处,也希望大家能够指点出来,给点建议!帮忙改进.先谢谢大家了!
阅读全文
2008年7月15日开课。
参加方法:
1。提前阅读材料
2。阅读课程讲稿,动手实验
3。完成作业
4。加入课程邮件列表提问答疑
发空白邮件到邮件列表 ruby-on-rails-programming-with-passion-subscribe@googlegroups.com,即可注册加入课堂论坛。
课程安排 (7-8月):
1。Ruby Basics (7/15/2008)
2。Ruby Meta-programming (7/22/2008)
3。JRuby Basics(7/29/2008)
4。Ruby On Rails Basics (8/5/2008)
5。Scaffolding (8/12/2008)
6。JRuby and Rails Support in NetBeans (8/12/2008)
FAQ:
不清楚的问题,见FAQ。
更多在线课程:
请点击此处。


