浏览 8205 次
该帖已经被评为新手帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-02-08
Appfuse应用的核心在于ant build任务的灵活应用和xdoclet模板的修改与使用。重要的工具是其提供的appgen,通过对ant build任务和appgen xdocet模板的修改将appfuse与自己的项目进行融合、与IDE进行融合。所以要用appfuse,学习ant工具和xdoclet是必不可少的第一步。 前提所需的软件 jdk1.4.2.6 tomcat5.0.28 ant1.6.2 appfuse1.82 mysql4.x 以上软件请访问 http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseQuickStart_zh 根据相关提示下载 同时对以上变量,都设置相关的HOME变量及路径。 下面开始一步步操作完成appfuse的布署工作 1,解压appfuse1.9.4(或更高版本),会产生一个appfuse的目录。 2,打开eclipse3.0或eclipse3.2,选择菜单,“新建工程”-->"Java Project"---->工程名"appfuse"后,指定一个工程目录后,完成。 3,先复制第一步中appfuse目录下所有文件,然后右键点击"appfuse"工程名,选择“粘贴”,把appfuse的所有的文件导入到appfuse工程中。 4,在eclipse下选择"windows"菜单--->"Preference"菜单--->"ant"--->"Runtime"---->点“ant home”按钮,设备ant-home目录,同时复制junit.jar到ant安装目录下的lib目录里 5,在安装mysql服务器后,如果设置了密码的话,要点,windows菜单--->show views---> ant 。出现ant工具界面,在界面上,点add buildfiles图标,把appfuse工程根目录下的build.xml文件中附加进来,然后再打开properties.xml文件,修改里面的root用户的密码为你的mysql数据库访问时的密码。然后在ant菜单界面中展开target列表,选择,setup目录安装所有装备工作, 详细ant任务可以参照http://www.kingbit.com/appfuse/index.php上所描述的ant任务详解。 运行ant setup-tomcat 然后再运行,ant start-tomcat 然后在浏览器中打http://localhost:8080/appfuse 看看有没有出现界面 操作用户名及密码是tomcat tomcat 6,当上面都配置正确后,我们就来开始写一个新的操作了,先写个dao类下的model类 在eclipse下,展开src/dao文档结构,在org.appfuse.model下面,建个Person.java文件, 内容如下图: /* * Created on 2006-5-22 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package org.appfuse.model; /** * @author Administrator * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates * @hibernate.class table="person" */ public class Person extends BaseObject{ private Long id; private String first_name; /** * @return Returns the id. * @hibernate.id column="id" generator-class="increment" * */ public Long getId() { return id; } /** * @param id The id to set. */ public void setId(Long id) { this.id = id; } /* (non-Javadoc) * @see org.appfuse.model.BaseObject#toString() */ public String toString() { // TODO Auto-generated method stub return null; } /* (non-Javadoc) * @see org.appfuse.model.BaseObject#equals(java.lang.Object) */ public boolean equals(Object o) { // TODO Auto-generated method stub return false; } /* (non-Javadoc) * @see org.appfuse.model.BaseObject#hashCode() */ public int hashCode() { // TODO Auto-generated method stub return 0; } /** * @return Returns the first_name. * @hibernate.property column="first_name" not-null="true" */ public String getFirst_name() { return first_name; } /** * @param first_name The first_name to set. * @spring.validator type="required" //该字段需要验证,用Spring的校验机制 */ public void setFirst_name(String first_name) { this.first_name = first_name; } } 在以上代码中注释javadoc区域中添加上xdoclet在生成hibernate所用到的XML文件的一些O/R映射信息。 建好上以Person.java后,我们就开始利用xdoclet工具,配合ant任务,生成我们所需用到了数据库表结构了, 点ant任务中的,先运行db-prepare的任务再 点ant db-create 后,可以在控制台下看到一系列建表的语句,同时可以到mysql控制台查看到相关信息. 表建好后,我们就开始利用appgen自动生成appfuse所需要的其它dao操作类,manage业务类,controller控制器类及Person.hbm.xml等相关文件 。操作过程如下,到dos命令行模式下,找到工程所在的根目录下\extras\appgen目录,点运行ant install-detailed 会根据提示,建Person及person相关文件。Build成功后,再回到eclipse下,右键点工程文件名appfuse,选择Refresh ,再运行ant deploy命令,再重新启TOMCAT,这样一个Person的添加,删除操作功能模块就完成了,开发就是这么easy and fast!!^_^ @spring.validator type="required" 是另外附 appgen生成的类文件如下: PersonDAO接口类 PersonDAOHibernate接口实现类 PersonManager业务接口类 PersonManagerImpl.java业务接口实现类 PersonController.java控制器类(根据客户端提交的请求,显示的是信息列表) PersonFormController页面控制器类(根据客户端提交的请求,修改,添加,删除操作控制类) 注意在生成dao接口类的时候,appgen会根据Person类中的hibernate的注释标记,生成对应的Person.hbm.xml文件 修改org.appfuse.dao.hibernate.applicationContext-hibernate.xml文件, 追加 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mappingResources"> <list> <value>org/appfuse/model/Role.hbm.xml</value> <value>org/appfuse/model/User.hbm.xml</value> <value>org/appfuse/model/UserCookie.hbm.xml</value> <value>org/appfuse/model/Person.hbm.xml</value> <value>org/appfuse/model/Book.hbm.xml</value> </list> </property> <!-- The property below is commented out b/c it doesn't work when run via Ant in Eclipse. It works fine for individual JUnit tests and in IDEA ?? <property name="mappingJarLocations"> <list><value>file:dist/appfuse-dao.jar</value></list> </property> --> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">@HIBERNATE-DIALECT@</prop> <!-- Create/update the database tables automatically when the JVM starts up <prop key="hibernate.hbm2ddl.auto">update</prop> --> <!-- Turn batching off for better error messages under PostgreSQL <prop key="hibernate.jdbc.batch_size">0</prop> --> </props> </property> </bean> 同时指定动态指定接口的实现类 <!--Person-START--> <bean id="personDAO" class="org.appfuse.dao.hibernate.PersonDAOHibernate" autowire="byName"/> <!--Person-END--> 注意在业务接口类操作时,要运用SPRING的IOC进行对业务逻辑的处理, 修改org.appfuse.service目录下的,applicationContext-service.xml文件 追加以下配置 <!--Person-START--> <bean id="personManager" parent="txProxyTemplate"> <property name="target"> <bean class="org.appfuse.service.impl.PersonManagerImpl" autowire="byName"/> </property> </bean> <!--Person-END--> 在personManagerImpl.java文件中装PersonDao接口的Instance注入到personManager容器中。 PersonDAO接口类 package org.appfuse.dao; import java.util.List; import org.appfuse.model.Person; public interface PersonDAO extends DAO { /** * Retrieves all of the persons */ public List getPersons(Person person); /** * Gets person's information based on primary key. An * ObjectRetrievalFailureException Runtime Exception is thrown if * nothing is found. * * @param id the person's id * @return person populated person object */ public Person getPerson(final Long id); /** * Saves a person's information * @param person the object to be saved */ public void savePerson(Person person); /** * Removes a person from the database by id * @param id the person's id */ public void removePerson(final Long id); } PersonDAOHibernate接口实现类 package org.appfuse.dao.hibernate; import java.util.List; import org.appfuse.model.Person; import org.appfuse.dao.PersonDAO; import org.springframework.orm.ObjectRetrievalFailureException; public class PersonDAOHibernate extends BaseDAOHibernate implements PersonDAO { /** * @see org.appfuse.dao.PersonDAO#getPersons(org.appfuse.model.Person) */ public List getPersons(final Person person) { return getHibernateTemplate().find("from Person"); /* Remove the line above and uncomment this code block if you want to use Hibernate's Query by Example API. if (person == null) { return getHibernateTemplate().find("from Person"); } else { // filter on properties set in the person HibernateCallback callback = new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Example ex = Example.create(person).ignoreCase().enableLike(MatchMode.ANYWHERE); return session.createCriteria(Person.class).add(ex).list(); } }; return (List) getHibernateTemplate().execute(callback); }*/ } /** * @see org.appfuse.dao.PersonDAO#getPerson(Long id) */ public Person getPerson(final Long id) { Person person = (Person) getHibernateTemplate().get(Person.class, id); if (person == null) { log.warn("uh oh, person with id '" + id + "' not found..."); throw new ObjectRetrievalFailureException(Person.class, id); } return person; } /** * @see org.appfuse.dao.PersonDAO#savePerson(Person person) */ public void savePerson(final Person person) { getHibernateTemplate().saveOrUpdate(person); } /** * @see org.appfuse.dao.PersonDAO#removePerson(Long id) */ public void removePerson(final Long id) { getHibernateTemplate().delete(getPerson(id)); } } PersonManager业务接口类 package org.appfuse.service; import java.util.List; import org.appfuse.model.Person; import org.appfuse.dao.PersonDAO; public interface PersonManager extends Manager { /** * Setter for DAO, convenient for unit testing */ public void setPersonDAO(PersonDAO personDAO); /** * Retrieves all of the persons */ public List getPersons(Person person); /** * Gets person's information based on id. * @param id the person's id * @return person populated person object */ public Person getPerson(final String id); /** * Saves a person's information * @param person the object to be saved */ public void savePerson(Person person); /** * Removes a person from the database by id * @param id the person's id */ public void removePerson(final String id); } PersonManagerImpl业务接口实现类 package org.appfuse.service.impl; import java.util.List; import org.appfuse.model.Person; import org.appfuse.dao.PersonDAO; import org.appfuse.service.PersonManager; public class PersonManagerImpl extends BaseManager implements PersonManager { private PersonDAO dao; /** * Set the DAO for communication with the data layer. * @param dao */ public void setPersonDAO(PersonDAO dao) { this.dao = dao; } /** * @see org.appfuse.service.PersonManager#getPersons(org.appfuse.model.Person) */ public List getPersons(final Person person) { return dao.getPersons(person); } /** * @see org.appfuse.service.PersonManager#getPerson(String id) */ public Person getPerson(final String id) { return dao.getPerson(new Long(id)); } /** * @see org.appfuse.service.PersonManager#savePerson(Person person) */ public void savePerson(Person person) { dao.savePerson(person); } /** * @see org.appfuse.service.PersonManager#removePerson(String id) */ public void removePerson(final String id) { dao.removePerson(new Long(id)); } } PersonController控制器类 注意在产生这个控制器类的作用是为了将PersonManager接口通过IOC注入并Instance 能够调用dao类取得的数据结果集返回给客户浏览器的请求。请求的mappingUrl地址又是在WEB/WEB-INF目录下action-servlet.xml 文件下进行配置的 <!--Person-BEAN-START--> <bean id="personController" class="org.appfuse.webapp.action.PersonController" autowire="byName"/> <bean id="personFormController" class="org.appfuse.webapp.action.PersonFormController" autowire="byName"> <property name="commandName" value="person"/> <property name="commandClass" value="org.appfuse.model.Person"/> <property name="validator" ref="beanValidator"/> <property name="formView" value="personForm"/> <property name="successView" value="redirect:persons.html"/> </bean> <!--Person-BEAN-END--> <!--Person-URL-START--> <prop key="/persons.html">personController</prop> <prop key="/editPerson.html">personFormController</prop> <!--Person-URL-END--> package org.appfuse.webapp.action; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.beanutils.BeanUtils; import org.appfuse.Constants; import org.appfuse.model.Person; import org.appfuse.service.PersonManager; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; public class PersonController implements Controller { private final Log log = LogFactory.getLog(PersonController.class); private PersonManager personManager = null; public void setPersonManager(PersonManager personManager) { this.personManager = personManager; } public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { if (log.isDebugEnabled()) { log.debug("entering 'handleRequest' method..."); } Person person = new Person(); // populate object with request parameters BeanUtils.populate(person, request.getParameterMap()); List persons = personManager.getPersons(person); return new ModelAndView("personList", Constants.PERSON_LIST, persons); } } PersonFormController添加修改删除操作控制器类。 package org.appfuse.webapp.action; import java.util.Locale; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.appfuse.model.Person; import org.appfuse.service.PersonManager; import org.springframework.validation.BindException; import org.springframework.web.servlet.ModelAndView; public class PersonFormController extends BaseFormController { private PersonManager personManager = null; public void setPersonManager(PersonManager personManager) { this.personManager = personManager; } protected Object formBackingObject(HttpServletRequest request) throws Exception { String id = request.getParameter("id"); Person person = null; if (!StringUtils.isEmpty(id)) { person = personManager.getPerson(id); } else { person = new Person(); } return person; } public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception { if (log.isDebugEnabled()) { log.debug("entering 'onSubmit' method..."); } Person person = (Person) command; boolean isNew = (person.getId() == null); Locale locale = request.getLocale(); if (request.getParameter("delete") != null) { personManager.removePerson(person.getId().toString()); saveMessage(request, getText("person.deleted", locale)); } else { personManager.savePerson(person); String key = (isNew) ? "person.added" : "person.updated"; saveMessage(request, getText(key, locale)); if (!isNew) { return new ModelAndView("redirect:editPerson.html", "id", person.getId()); } } return new ModelAndView(getSuccessView()); } } 在布署公司的产品过程中,mine的WAR应用,在执行ant compile-dao过程中,会报一个,找不到org.eclipse.jta的错误, 这是由于ant找不到eclipse的关于jta的插件的原因!解决办法是,在ant架包中,把eclipse 安装目录下的plugns目录下的org.eclipse.jdt.core_3.0. (E:\eclipse\plugins\org.eclipse.jdt.core_3.0.0\)目录中两个jar文件加入到ant的lib目录下! xdoclet在执行ant的deploy的任务时,有时候生成的XML文件格式会出现小小的问题,解决的办法是修改相关的JAVA文件,然后运行deploy脚本重新利用 xdoclet来生成相关的xml文件!直至成功! 首页登录在调用loginServlet时候,login.jsp页面能正确显示出来,但是提交到服务器的/authorize的action映射找不到,也就是找不到服务, 这是由于tomcat是启动在8080端口的服务,而程序中,用户登录的校验是根据properties.xml文件中,配置的 <property name="http.port" value="8080"/>这个端口号,默认的是80端口,可以通过把TOMCAT启动时监听80端口或,修改properties.xml文件中 http.port的value="8080",就可以找到服务器响应。注意,这里/authorize的映射,不是通过spring的IOC操作的,而是通过在web.xml文件中加入一个 <filter> <filter-name>securityFilter</filter-name> <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class> - <init-param> <param-name>targetClass</param-name> <param-value>net.sf.acegisecurity.util.FilterChainProxy</param-value> </init-param> </filter> <filter-mapping> <filter-name>securityFilter</filter-name> <url-pattern>/j_security_check</url-pattern> </filter-mapping> 来实现的 但是一定要记得,文件net.sf.acegisecurity.util.FilterChainProxy是在acegi-security-x.x.x.jar包里面的,调用前一定要记得放在应用的WEB-INF/lib/目录下才能正常使用。 当系统启动时会自动加载spring配置文件中所声明的类,在appfuse中这一声明是放在action-servlet.xml中的,因此必须将这个文件同其他的applicationContext.xml一起在web.xml中声明为contextConfigLocation的内容,如下: <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:META-INF/applicationContext-*.xml /WEB-INF/applicationContext-*.xml /WEB-INF/schedulingContext-timer.xml</param-value> </context-param> 在action-servlet.xml中定义如下(这个文件必须符合spring-beans.dtd的规范): <beans> <bean id="userAction" class="com.mywap.webwork.action.UserAction" singleton="false"> <property name="userManager"><ref bean="userManager"/></property> </bean> <!-- Add additional actions here --> </beans> acegi出了0.8,改动还真不少,原先0.7的应用,改了一个多小时才完全升级成功。备忘一下: 1 最贴心的改变莫过于 filter chains可以放在spring 容器中加载了,再也不用在Web.XML中声明长长的一串filter了。例如: <bean id="filterChainProxy" class="net.sf.aceGISecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,...... </value> </property> </bean> 2 HttpSessionIntegrationFilter 已经消失,使用net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter取而代之,如: <bean id="httpSessionContextIntegrationFilter" class="net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter"> <property name="context"><value>net.sf.acegisecurity.context.security.SecureContextImpl</value></property> </bean> 这个"context"属性不可不设哟。 3 新增了一个功能,可以在web.xml中声明一个HttpSessionEventPublisher context listener,想想Spring的现在还不很成熟的消息发布机制(AOP),主要是用来记日志。我暂时还没用到这个功能。 mine在通过ant deploy任务到TOMCAT下,会把hibernate的表映射文件,连同持久化的类文件,打包成一个,mine-dao.jar架包,放到web-inf/lib私有目录下 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-02-08
你说的这些我觉得appfuse的Documentation里面已经说的很清楚了,能不能重点总结一下典型的问题以及解决方法,我今天运行了一下1.9.4版的ant test-jsp,报了如下错误,不知道LZ有没有遇到过?
"we should see the login title" failed with message "Wrong document title found! Expected ".*??????.*" but got "登录 | AppFuse"" 是zh的资源文件有问题嘛? |
|
返回顶楼 | |
发表时间:2007-02-08
记得以前有一篇很好的帖子比较深入的分析了appfuse的优缺点,列举一些典型的问题,不知道哪位有没有实际项目应用的经验拿出来分享一下!即使是个toy,起码里面有很多值得借鉴的地方吧?
|
|
返回顶楼 | |
发表时间:2007-02-08
1.94是有这个BUG,不过你把它导入到eclipse下运行,就可以了,它那个test-all脚本是有问题的,我也碰到过了,
|
|
返回顶楼 | |
发表时间:2007-02-09
问题已解决,是资源文件编码的问题,把test\web\web-tests.xml文件里面的
<property file="${build.dir}/test/properties/ApplicationResources_${user.language}.properties"/> <property file="web/WEB-INF/classes/ApplicationResources.properties"/> 两行都删掉,改为 <property file="${build.dir}/web/classes/ApplicationResources_${user.language}.properties"/> 就可以了,应该是utf-8编码文件才能通过测试。 |
|
返回顶楼 | |
发表时间:2007-02-12
不知道2.0什么时候出来,顺便问一下我看看Easy CRUD with Struts 2的demo,不知道是不是基于Appfuse2.0的,GRUD部分的自动生成原理是什么?
|
|
返回顶楼 | |
发表时间:2007-03-29
这个版本是怎么用事务的?
|
|
返回顶楼 | |