忙里抽闲在《Maven2小记》 之后准备把 Appfuse 的一些使用心得记录一下,以备参考:
简介:Appfuse是一个开放源码的项目和应用程序,它由 Matt Raible开发,它集成了流行的Spring、Hibernate、ibatis、struts、Xdcolet、junit等基础框架,并提供了对 Taperstry和JSF等的支持,非常适合作为J2EE项目的骨架,特别是和Maven的整合,使它更加光芒耀眼。在用AppFuse开发时,用户可以自由选择Struts、Spring MVC、Webwork、Taperstry和JSF这几个MVC框架。它采用测试驱动(TDD)的开发方式,使用JUnit测试各层。
1、安装与部署:
“快速”这就是Appfuse的一大优点,所以它的安装与部署过程也十分简略。首先当然保证机器上必须有Maven(如果有问题可以参考《Maven2小记》 ),然后就可以开始建立项目了,以下是大致步骤(这里以Appfuse-Spring标准结构为例):
〉新建一个目录,准备安放Appfuse项目工程。例如为:d:/workspace,运行Maven命令:mvn archetype:create -DarchetypeGroupId=org.appfuse.archetypes -DarchetypeArtifactId=appfuse-basic-spring -DremoteRepositories=http://static.appfuse.org/releases -DarchetypeVersion=2.0.2 -DgroupId=com.appfuse.app -DartifactId=appfuse,运行过程中,会看到一系列的waring警告,不用管。等看到:Builde Success,表示成功了。maven会在d:/workspace下新建appfuse目录,里面含有最重要的pom.xml文件。
〉然后就是修改pom.xml的参数,这些参数都在文件底部,若你是mysql数据库,则很简单,只需修改用户名和密码(默认为root和空)。若是其他数据库,请参照pom.xml里面的数据库配置文件进行替换修改。
〉最后,进入d:/workspace/appfuse目录,运行mvn appfuse:full-source进行安装,过程很快,然后就是运行mvn jetty:run-war启动jetty,在测试时会有一些异常信息。不用理会,只是一些测试数据没有准备好。启动完毕后打开 http://localhost:8080 就可以看到Appfuse的登录页面。
这里有个很有意思的地方,如果在安装过程中出现
[INFO] null
Illegal character in path at index 18 : file:/C:/Documents and Settings/Administrator/.m2/repository/org/apache/ant/ant/ 1.7 . /ant- 1.7 . .jar
...
类似错误的话可能是由于你的maven库安装目录是window下的默认目录 C:/Documents and Settings...这个路径里面含有有空格所以触发的ant的一个bug导致出错,解决办法很简单:你可以按照QuickStart的提示,设置maven的settings.xml里面选项<localRepository>c:/docume~1/username/.m2/repository</localRepository>,当然你也可以找一个不带空格的目录(如:/path/to/local/repo)然后设置settings.xml<localRepository>/path/to/local/repo</localRepository>就可以了~
2、准备开发:
首先,当然要把代码导入到IDE中,比如我们用Eclipse,那么就在项目目录下,运行mvn eclipse:eclipse,然后到Eclipse>File>Import导入项目。然后我们就可以开始阅读、添加或者修改Appfuse的源码了~
3、开发笔记:
目前准备按照官方开发文档里 http://appfuse.org/display/APF/Developer+Guide 的开发文档进行实践性的讲解,以下是一个Appfuse开发DEMO的建立过程:
a> 我们先建立 Employee 表:
CREATE TABLE `Employee` (
`id` bigint(20) NOT NULL auto_increment,
`code` varchar(10) NOT NULL,
`dept` varchar(50) NOT NULL,
`name` varchar(20) NOT NULL,
`status` varchar(10) NOT NULL,
`telephone` varchar(20) default NULL,
`title` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
b> 然后由表生成model 运行mvn appfuse:gen-model
c> 接下来你会在model package中发现新的Employee.java
d> 在@Id @GeneratedValue(strategy=IDENTITY) @GeneratedValue(strategy = GenerationType.AUTO)两个ID生成策略中选择一个(我选择@GeneratedValue(strategy = GenerationType.AUTO)),保存好
e> 然后就是由model生成CRUD 运行mvn appfuse:gen -Dentity=Employee会生成employeeList.jsp、employeeForm.jsp、 EmployeeAction.java但是没有自动生成dao与service 而是采用的GenericManager<Employee, Long>中的方法,解决方法如下:
在项目下的pom.xml中查找genericCore,大概在940行 找到 将属性true 改为false
像这样<amp.genericCore>false</amp.genericCore>
重新运行 mvn appfuse:gen -Dentity=Employee
在myeclipse中查看代码 dao 与 service也都生成了
f> 大功告成,运行mvn jetty:run在浏览器中查看界面吧
g> 但是我发现最后还有个问题 就是appfuse页面中 显示乱码
解决方法如下:
修改pom.xml中
找到 native2ascii-utf8 的 execution 把 includes 里的 ApplicationResources_zh*.properties 改为 *_zh*.properties
找到下方 excludes 段落中的 <exclude>ApplicationResources_zh*.properties</exclude> 改成 <exclude>*_zh*.properties</exclude>
如果发现问题依然存在,注意必须先 mvn clean 一下,然后再 mvn jetty:run 这样才能把缓存清除干净哦:)
接下来就是具体的开发过程了,待续~~ 由于篇幅原因请看新作《Appfuse 源代码分析 》~~
这里附上一个 web.xml 的常见配置实例,还是比较有使用价值的:)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name> appfuse </display-name>
<!-- precompiled jsp mappings -->
<!-- 定义默认的 CSS Theme -->
<context-param>
<param-name> theme </param-name>
<param-value> simplicity </param-value>
</context-param>
<!-- Define the basename for a resource bundle for I18N -->
<context-param>
<param-name> javax.servlet.jsp.jstl.fmt.localizationContext </param-name>
<param-value> ApplicationResources </param-value>
</context-param>
<context-param>
<param-name> javax.servlet.jsp.jstl.fmt.fallbackLocale </param-name>
<param-value> en </param-value>
</context-param>
<!-- Context Configuration locations for Spring XML files -->
<context-param>
<param-name> contextConfigLocation </param-name>
<param-value>
/WEB-INF/classes/springconfig/applicationContext-*.xml,
/WEB-INF/classes/springconfig/security.xml
</param-value>
</context-param>
<!--
十大过滤器之一 :
FilterChainProxy(org.acegisecurity.util.FilterChainProxy)是acegi的一个类
通过使用acegi我们可以用spring aop直接对service bean的每一个method做权限管理
-->
<filter>
<filter-name> securityFilter </filter-name>
<filter-class> org.acegisecurity.util.FilterToBeanProxy </filter-class>
<init-param>
<param-name> targetClass </param-name>
<param-value> org.acegisecurity.util.FilterChainProxy </param-value>
</init-param>
</filter>
<!--
十大过滤器之二 :
OSCache标记库由OpenSymphony设计,它是一种开创性的JSP定制标记应用,
提供了在现有JSP页面之内实现快速内存缓冲的功能。
-->
<filter>
<filter-name> cacheFilter </filter-name>
<filter-class> com.opensymphony.oscache.web.filter.CacheFilter </filter-class>
</filter>
<!--
十大过滤器之三 :
appfuse中使用Clickstream来跟踪用户的页面操作。它通过监听器来开始一次会话跟踪过程。
用户的每一条点击信息是通过一个servlet filter来捕捉的。当用户的session结束后把整个跟踪
记录保存在一个文件里或打印输出。可以发现用户是不是一个“人”。
并且进行过滤。可以通过jsp或servlet显示用户的当前的点击信息。
-->
<filter>
<filter-name> clickstreamFilter </filter-name>
<filter-class> com.opensymphony.clickstream.ClickstreamFilter </filter-class>
</filter>
<!--
十大过滤器之四 :
spring的编码转换过滤器
-->
<filter>
<filter-name> encodingFilter </filter-name>
<filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class>
<init-param>
<param-name> encoding </param-name>
<param-value> UTF-8 </param-value>
</init-param>
<init-param>
<param-name> forceEncoding </param-name>
<param-value> true </param-value>
</init-param>
</filter>
<!--
十大过滤器之五 :
spring 的hibernate Session过滤器
-->
<filter>
<filter-name> hibernateFilter </filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<!--
十大过滤器之六 :
URL重写
-->
<filter>
<filter-name> rewriteFilter </filter-name>
<filter-class> org.tuckey.web.filters.urlrewrite.UrlRewriteFilter </filter-class>
<init-param>
<param-name> logLevel </param-name>
<param-value> commons </param-value>
</init-param>
</filter>
<!--
十大过滤器之七 :
sitemesh是由一个基于web页面布局、装饰以及与现存web应用整合的框架。
它能帮助我们在由大量页面构成的项目中创建一致的页面布局和外观,
如一致的导航条,一致的banner,一致的版权,等等。它不仅仅能处理动态的内容,
如jsp,php,asp等产生的内容,它也能处理静态的内容,
如htm的内容,使得它的内容也符合你的页面结构的要求。
甚至于它能将html文件象include那样将该文件作为一个面板的形式嵌入到别的文件中去。
-->
<filter>
<filter-name> sitemesh </filter-name>
<filter-class> com.opensymphony.module.sitemesh.filter.PageFilter </filter-class>
</filter>
<!--
十大过滤器之八 :
Display Tag Lib是一个标签库,用来处理jsp网页上的Table,功能非常强,
可以对的Table进行分页、数据导出、分组、对列排序等等,
而且使用起来非常的方便。能够大大减少代码量。
-->
<filter>
<filter-name> exportFilter </filter-name>
<filter-class> org.displaytag.filter.ResponseOverrideFilter </filter-class>
</filter>
<!--
十大过滤器之九 :
性能优化,将输出流压缩
-->
<filter>
<filter-name> compressionFilter </filter-name>
<filter-class> com.lady.webapp.filter.GZIPFilter </filter-class>
</filter>
<!--
十大过滤器之十 :
自定义,国际化
-->
<filter>
<filter-name> localeFilter </filter-name>
<filter-class> com.lady.webapp.filter.LocaleFilter </filter-class>
</filter>
<filter-mapping>
<filter-name> encodingFilter </filter-name>
<url-pattern> /j_security_check </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> encodingFilter </filter-name>
<url-pattern> /dwr/* </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> encodingFilter </filter-name>
<url-pattern> *.html </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> encodingFilter </filter-name>
<url-pattern> *.jsp </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> securityFilter </filter-name>
<url-pattern> /j_security_check </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> securityFilter </filter-name>
<url-pattern> /dwr/* </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> securityFilter </filter-name>
<url-pattern> *.html </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> securityFilter </filter-name>
<url-pattern> *.jsp </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> cacheFilter </filter-name>
<url-pattern> *.jsp </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> hibernateFilter </filter-name>
<url-pattern> *.html </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> clickstreamFilter </filter-name>
<url-pattern> *.html </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> localeFilter </filter-name>
<url-pattern> *.html </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> localeFilter </filter-name>
<url-pattern> *.jsp </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> exportFilter </filter-name>
<url-pattern> *.html </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> compressionFilter </filter-name>
<url-pattern> *.css </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> compressionFilter </filter-name>
<url-pattern> *.jsp </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> compressionFilter </filter-name>
<url-pattern> *.js </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> compressionFilter </filter-name>
<url-pattern> *.html </url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name> rewriteFilter </filter-name>
<url-pattern> /* </url-pattern>
<!-- dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher -->
</filter-mapping>
<filter-mapping>
<filter-name> sitemesh </filter-name>
<url-pattern> /* </url-pattern>
<!-- dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher -->
</filter-mapping>
<filter-mapping>
<filter-name> clickstreamFilter </filter-name>
<url-pattern> *.html </url-pattern>
</filter-mapping>
<!--
五大监听器之一 :
listener开始一次跟踪,filter捕捉每一次请求,在这里捕捉以html结尾的请求。
在项目主页http://www.opensymphony.com/clickstream/提供了显示当前在线信息的jsp和servlet
clickstream.jsp,viewstream.jsp 以及ActiveStreamServlet.
appfuse直接使用了上诉的两个jsp文件
几乎没有做任何改动。
-->
<listener>
<listener-class> com.opensymphony.clickstream.ClickstreamListener </listener-class>
</listener>
<!--
五大监听器之二 :
struts 的菜单处理监听器
-->
<listener>
<listener-class> net.sf.navigator.menu.MenuContextListener </listener-class>
</listener>
<!--
五大监听器之三 :
spring中的提供了一个名为org.springframework.web.util.IntrospectorCleanupListener的监听器。它主要负责处理由
JavaBeans Introspector的使用而引起的缓冲泄露。spring中对它的描述如下:它是一个在web应用关闭的时候,清除JavaBeans
Introspector的监听器.在web.xml中注册这个listener.可以保证在web 应用关闭的时候释放与掉这个web 应用相关的class
loader 和由它管理的类如果你使用了JavaBeans Introspector来分析应用中的类,Introspector 缓冲中会保留这些类的引用.
结果在你的应用关闭的时候,这些类以及web 应用相关的class loader没有被垃圾回收.不幸的是,清除Introspector的唯一方式是刷
新整个缓冲.这是因为我们没法判断哪些是属于你的应用的引用.所以删除被缓冲的introspection会导致把这台电脑上的所有应用的
introspection都删掉.需要注意的是,spring 托管的bean不需要使用这个监听器.因为spring它自己的introspection所使用的缓冲
在分析完一个类之后会被马上从javaBeans Introspector缓冲中清除掉.应用程序中的类从来不直接使用JavaBeans Introspector.
所以他们一般不会导致内部查看资源泄露.但是一些类库和框架往往会产生这个问题.例如:Struts 和Quartz.单个的内部查看泄漏会导致整
个的web应用的类加载器不能进行垃圾回收.在web应用关闭之后,你会看到此应用的所有静态类资源(例如单例).这个错误当然不是由这个类自
身引起的.
-->
<listener>
<listener-class> org.springframework.web.util.IntrospectorCleanupListener </listener-class>
</listener>
<!--
五大监听器之四 :
-->
<listener>
<listener-class> com.lady.webapp.listener.StartupListener </listener-class>
</listener>
<!--
五大监听器之五 :
-->
<listener>
<listener-class> com.lady.webapp.listener.UserCounterListener </listener-class>
</listener>
<!--
两大servlet之一 :
-->
<servlet>
<servlet-name> springMVC </servlet-name>
<servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class>
<init-param><param-name> contextConfigLocation </param-name>
<param-value>
/WEB-INF/classes/springconfig/springMVC.xml
<!-- /WEB-INF/lj-springapp-servlet.xml
/WEB-INF/ysm-springapp-servlet.xml -->
</param-value>
</init-param>
<load-on-startup> 2 </load-on-startup>
</servlet>
<!--
两大servlet之二 :
-->
<servlet>
<servlet-name> dwr-invoker </servlet-name>
<servlet-class> uk.ltd.getahead.dwr.DWRServlet </servlet-class>
<init-param>
<param-name> debug </param-name>
<param-value> true </param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name> springMVC </servlet-name>
<url-pattern> *.html </url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name> dwr-invoker </servlet-name>
<url-pattern> /dwr/* </url-pattern>
</servlet-mapping>
<session-config>
<session-timeout> 10 </session-timeout>
</session-config>
<welcome-file-list>
<welcome-file> index.jsp </welcome-file>
</welcome-file-list>
<error-page>
<error-code> 500 </error-code>
<location> /error.jsp </location>
</error-page>
<error-page>
<error-code> 400 </error-code>
<location> /index.jsp </location>
</error-page>
<error-page>
<error-code> 403 </error-code>
<location> /403.jsp </location>
</error-page>
<error-page>
<error-code> 404 </error-code>
<location> /404.jsp </location>
</error-page>
</web-app>
最后,抽点时间介绍一下 Tapestry :
同样是很优秀的 JavaEE 开发框架,同样有 maven 的支持,他的设计风格却与 Appfuse 大相径庭,不过基于 servlet 的模块式开发思想,整洁的模板代码风格,以及 Tapestry 广泛使用的 org.apache 系列的类库,这可能也是他也很有“人缘”的原因了,不惜为 developer 们相当不错的选择~
首先同样是安装(比 Appfuse 更方便):
mvn archetype:create -DarchetypeGroupId=org.apache.tapestry -DarchetypeArtifactId=tapestry-simple -DarchetypeVersion=5.0.2 -DgroupId=org.example -DartifactId=tapestry -DpackageName=org.example.tapestry -Dversion=1.0.0-SNAPSHOT
注意 artifactId 和 packageName 必须对应否则 Eclipse Maven2 会报错哦。
然后直接打开 Eclipse 执行 Eclipse>File>Import 导入项目即可。
最后进入tapestry项目目录,运行mvn jetty:run查看效果。
然后是开发中的技巧:持续更新中,可以看看新作《Appfuse 源代码分析 》
Keep walking ...