- 浏览: 53505 次
- 性别:
- 来自: 香港
文章分类
最新评论
-
夜游神:
看完此文身有感处,每次写代码都是copy来copy去,程序员快 ...
自动编码的探讨与实现 -
chen4059:
双机冷备,HA吧。
想好就要投入啊。
赛的VCS不错。
连接池控制多个数据源 -
jayxu:
你的应用场景没必要这样做
连接池控制多个数据源 -
whitesock:
使用LVS
连接池控制多个数据源 -
taojingrui:
Weblogic 有multiple datasource 的 ...
连接池控制多个数据源
在SSH项目中,我们应用了service layer模式,所以针对一个模块,它就存在pojo、dao、daoImpl、service、serviceImpl,再到struts中的action、form。假设设计是面向数据库的,针对一个数据库表,那么就要产生7个java文件,如果还要做异常处理,那么就是8个java文件。如果数据库有50个表,那么就是50*8=400个java文件。工程不小。
至于为什么要用service layer模式,论坛上已有讨论http://www.iteye.com/topic/29867
然而我们都知道,web中出现最多的操作是CURD,这400个java文件中有多少代码是重复的?几乎占了80%甚至更多。编写这样重复的代码是很枯燥无味的,而且如果是由不同人负责不同的模块的分工方式,程序员编码的风格是各不相同(虽然可能有规范约束,但是最后出来的东西还是避免不了的带有程序员个人风格的)。
所以为了节省时间和精力,便做一个程序来生成程序。
只要配置好你的项目名,你的模块名,模块路径,就可以在几秒之内完成一个模块的CURD代码,同时你可以自定义模板。
这是工具的大概设计思路:
由ant处理编译、生成目录的工作,velocity处理程序模板,contentEngine为核心处理程序。
产生的目录结构和代码路径:
模块名
--子模块1
----model
------businessobject
------dao
--------hibernate
----service
------impl
----view
------action
------form
----Exception
--子模块2
...
其中model/businessobject中是pojo和hbm.xml,这个由hibernate工具根据数据库表产生。
我们假设模块名为course,子模块名为table,类名为CourseMember。因篇幅问题,我们只看一个daoImpl的例子。
首先我们利用建立一个daoImpl的模板
ObjectDaoHibernateImpl.vm
声明:
1)其中${}是模板语言中的变量,变量的来源一是通过对应的.properties文件,另外是通过参数传递。
2)注释部分因是分页查询条件,这个涉及到具体字段,无法预知,所以需要在产生代码之后程序员根据查询条件自行修改。另外也涉及到个人项目的分页方法,这个根据具体情况自定义模板。
template.properties
公共属性文件,是所有template文件(.vm)的变量声明处,这个会在后面代码中进行设置。
对于属性文件,可有两种方式:
一是针对每一个template模板文件都建立一个属性文件,优点是在后面ant中设置的参数就少了,而且方便修改。缺点是模板文件数量增多,另外公共部分声明重复。
二是设定一个公共属性文件,将特定的变量交给参数传递。
我们这里先用公共属性文件的方式。
有个想法,能不能把这个思想延伸到页面的生成。在有几个项目的开发中,页面处理花费了大部分时间,远远超过后台代码的编写时间。而且如果页面上的代码有所不同,体现出来就会给用户很大很直接的不同;如果后台代码实现不同,但是功能实现成功,用户是无法知道的。
当然可以生成页面, rails的scaffold不就是这样的吗, 只不过所有具有这个功能的框架的页面生成的部分都不够完美而已
也就是说生成的不够完美,以至于我们在用它们的时候却忘记他们是生成。手工写页面的情况还是占据多数,页面上自动化远没有后台代码自动化那么成熟,至少页面上没有像xdoclet那么好用的工具。也是因为页面的表现复杂性导致了工具无法完善。
java5 的APT机制,没有了解过。搜索过也是很少资料,看你的描述它的编译和迭代功能还是比较吸引的。能不能给点资料来参考一下呢。^^
TOB (http://tob.ableverse.org) 就是用的APT机制, 不过TOB本身目前还没有开源计划, 教程也还没写好.
WoW (http://www.webofweb.net) 是基于TOB开发的, 开源的, 如果想体验一下, 可以到 http://wow.dev.java.net 下载源码自己编译一回看.
不过现在Eclipse的APT支持还有bug, 必须通过JDK的APT来生成代码, 而JDK1.5的javac也有bug, 生成出来的java代码还必须通过Eclipse来编译. 比较郁闷.
WoW的项目代码包里有个 BUILDING 文件, 按照那里的步骤可以成功完成编译.
Jack Herrington选择了ruby,在2000年写《code generation》一书的时候他就看中了ruby的作为脚本语言的轻便。选择ruby大肆流行,不得不说jack有眼力。
有个想法,能不能把这个思想延伸到页面的生成。在有几个项目的开发中,页面处理花费了大部分时间,远远超过后台代码的编写时间。而且如果页面上的代码有所不同,体现出来就会给用户很大很直接的不同;如果后台代码实现不同,但是功能实现成功,用户是无法知道的。
页面的组件化,现在也做了很多。比如jsf中就有一个很好的分页组件。如果将常用控件做成模版,引用时传递你需要显示的数据,那么页面处理的时间将大大缩短。模版做成组件,组件搭建前台。
应该很多公司都致力于类似这种工具的开发吧。
java5 的APT机制,没有了解过。搜索过也是很少资料,看你的描述它的编译和迭代功能还是比较吸引的。能不能给点资料来参考一下呢。^^
至于为什么要用service layer模式,论坛上已有讨论http://www.iteye.com/topic/29867
然而我们都知道,web中出现最多的操作是CURD,这400个java文件中有多少代码是重复的?几乎占了80%甚至更多。编写这样重复的代码是很枯燥无味的,而且如果是由不同人负责不同的模块的分工方式,程序员编码的风格是各不相同(虽然可能有规范约束,但是最后出来的东西还是避免不了的带有程序员个人风格的)。
所以为了节省时间和精力,便做一个程序来生成程序。
只要配置好你的项目名,你的模块名,模块路径,就可以在几秒之内完成一个模块的CURD代码,同时你可以自定义模板。
这是工具的大概设计思路:
由ant处理编译、生成目录的工作,velocity处理程序模板,contentEngine为核心处理程序。
产生的目录结构和代码路径:
模块名
--子模块1
----model
------businessobject
------dao
--------hibernate
----service
------impl
----view
------action
------form
----Exception
--子模块2
...
其中model/businessobject中是pojo和hbm.xml,这个由hibernate工具根据数据库表产生。
我们假设模块名为course,子模块名为table,类名为CourseMember。因篇幅问题,我们只看一个daoImpl的例子。
首先我们利用建立一个daoImpl的模板
ObjectDaoHibernateImpl.vm
${package_Hibernate} ${import_SQLException} ${import_List} ${import_HibernateCallback} ${import_HibernateObjectRetrievalFailureException} ${import_HibernateDaoSupport} ${import_HibernateException} ${import_Query} ${import_Session} ${import_ObjectNameDao} ${import_ObjectName} ${import_Finder} ${import_Page} ${import_Criteria} ${import_Projections} /** * The Hibernate implementation of the <code>${ObjectName}Dao</code>. * * @author ${Author} * @see ${ObjectName}Dao */ public class ${ObjectName}DaoHibernateImpl extends HibernateDaoSupport implements ${ObjectName}Dao { /** * Default constructor. */ public ${ObjectName}DaoHibernateImpl() { super(); } /** * @see ${ObjectName}Dao#save${ObjectName}(${ObjectName}) */ public ${ObjectName} save${ObjectName}(${ObjectName} ${objectname}) { this.getHibernateTemplate().save(${objectname}); return ${objectname}; } /** * @see ${ObjectName}Dao#get${ObjectName}(String) */ public ${ObjectName} get${ObjectName}(String id) { return (${ObjectName})this.getHibernateTemplate().load(${ObjectName}.class, id); } /** * @see ${ObjectName}Dao#update${ObjectName}(${ObjectName}) */ public void update${ObjectName}(${ObjectName} ${objectname}) { this.getHibernateTemplate().update(${objectname}); } /** * @see ${ObjectName}Dao#delete${ObjectName}(${ObjectName}) */ public void delete${ObjectName}(${ObjectName} ${objectname}) { this.getHibernateTemplate().delete(${objectname}); } /** * @see ${ObjectName}Dao#getAll${ObjectName}s() */ public List getAll${ObjectName}s() { return getHibernateTemplate().executeFind(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { StringBuffer sb = new StringBuffer(100); //sb.append("select distinct ${objectname} "); sb.append("SELECT ${objectname} "); sb.append("FROM ${ObjectName} ${objectname} "); sb.append("order by ${objectname}.id"); Query query = session.createQuery(sb.toString()); List list = query.list() ; return list; } }); } public Object query(final ${ObjectName} ${objectname}, final int pageNo, final int maxResult) { return getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Criteria criteria=session.createCriteria(${ObjectName}.class); Criteria anothercriteria=session.createCriteria(${ObjectName}.class); criteria.setProjection(Projections.rowCount()); // if (!${objectname}.get${objectname}Name().equals("") // && ${objectname}.get${objectname}Name() != null) { // criteria.add(Expression.ilike("contactName","%"+customerContactForm.getContactName()+"%")); // anothercriteria.add(Expression.ilike("contactName","%"+customerContactForm.getContactName()+"%")); // } Integer count=(Integer)criteria.uniqueResult(); List list=anothercriteria.setFirstResult((pageNo-1)*maxResult).setMaxResults(maxResult).list(); Page page=new Page(count.intValue(), maxResult, pageNo); return new Finder(list, page); } }); } public boolean deleteBybatch(final String[] chxSong) { StringBuffer cusIdList = new StringBuffer(200); cusIdList.append("delete from ${ObjectName} where ${objectName}No="); for (int i = 0; i < chxSong.length; i++) { if (i == 0) cusIdList.append(chxSong[i]); else cusIdList.append(" or ${objectName}No=" + chxSong[i]); } this.getSession().createQuery(cusIdList.toString()).executeUpdate(); return true; } }
声明:
1)其中${}是模板语言中的变量,变量的来源一是通过对应的.properties文件,另外是通过参数传递。
2)注释部分因是分页查询条件,这个涉及到具体字段,无法预知,所以需要在产生代码之后程序员根据查询条件自行修改。另外也涉及到个人项目的分页方法,这个根据具体情况自定义模板。
template.properties
公共属性文件,是所有template文件(.vm)的变量声明处,这个会在后面代码中进行设置。
对于属性文件,可有两种方式:
一是针对每一个template模板文件都建立一个属性文件,优点是在后面ant中设置的参数就少了,而且方便修改。缺点是模板文件数量增多,另外公共部分声明重复。
二是设定一个公共属性文件,将特定的变量交给参数传递。
我们这里先用公共属性文件的方式。
Author = Cmas R&D Team import_Arraylist = import java.util.ArrayList; import_List = import java.util.List; import_Set = import java.util.Set; import_FacesException = import javax.faces.FacesException; import_BeanUtils = import org.apache.commons.beanutils.BeanUtils; import_Log = import org.apache.commons.logging.Log; import_LogFactory = import org.apache.commons.logging.LogFactory; import_SQLException = import java.sql.SQLException; import_HibernateCallback = import org.springframework.orm.hibernate3.HibernateCallback; import_HibernateObjectRetrievalFailureException = import org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException; import_HibernateDaoSupport = import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import_HibernateException = import org.hibernate.HibernateException; import_Query = import org.hibernate.Query; import_Session = import org.hibernate.Session; import_Map = import java.util.Map; import_HashMap = import java.util.HashMap; import_Iterator = import java.util.Iterator; import_Criteria=import org.hibernate.Criteria; import_Projections=import org.hibernate.criterion.Projections; import_DispatchActionSupport=import org.springframework.web.struts.DispatchActionSupport; import_Action=import org.apache.struts.action.*; import_HttpServletRequest=import javax.servlet.http.HttpServletRequest; import_HttpServletResponse=import javax.servlet.http.HttpServletResponse; import_BeanUtils=import org.apache.commons.beanutils.BeanUtils; import_DataIntegrity=import org.springframework.dao.DataIntegrityViolationException;
评论
15 楼
sg552
2007-06-05
楼主的思想不错。
建议多看看 RATIONAL ROSE 等根据设计而生成代码的工具。
建议多看看 RATIONAL ROSE 等根据设计而生成代码的工具。
14 楼
davexin
2007-06-05
可以用freemaker来做
13 楼
cherami
2007-04-12
呵呵,个人感觉不如使用类继承来解决代码重复,基类使用类名来进行规则处理。代码生成也没有必要,如果有人修改代码,你就不能再生成了,毕竟有些逻辑还是要修改的。
让人重复写代码和让计算机重复都是不可取的。
让人重复写代码和让计算机重复都是不可取的。
12 楼
cwx714
2006-10-31
WebWork的eclipse插件--EclipseWork就是用Velocity作为代码生成模板的。
11 楼
xyz20003
2006-10-31
反正是生成基本的操作,特别的需求也不可能指望程序帮你想出来,倒是因为java的mvc框架太多不知道用哪个东西生成才对。
10 楼
pedestrian_I
2006-10-30
kuky 写道
pedestrian_I 写道
有个想法,能不能把这个思想延伸到页面的生成。在有几个项目的开发中,页面处理花费了大部分时间,远远超过后台代码的编写时间。而且如果页面上的代码有所不同,体现出来就会给用户很大很直接的不同;如果后台代码实现不同,但是功能实现成功,用户是无法知道的。
当然可以生成页面, rails的scaffold不就是这样的吗, 只不过所有具有这个功能的框架的页面生成的部分都不够完美而已
也就是说生成的不够完美,以至于我们在用它们的时候却忘记他们是生成。手工写页面的情况还是占据多数,页面上自动化远没有后台代码自动化那么成熟,至少页面上没有像xdoclet那么好用的工具。也是因为页面的表现复杂性导致了工具无法完善。
9 楼
歆渊
2006-10-29
pedestrian_I 写道
complystill 写道
生成java代码的话用Java5的APT机制比较正统一些, 是和编译结合在一起的, APT会自动调用Annotation Processor, 对生成的新的Java代码会自动编译, 如果还有Annotation就在再迭代, 最后所有的原始代码和生成的代码都编译好以后才结束.
不过ANT目前还不官方支持APT, 结合有点烦琐.
不过ANT目前还不官方支持APT, 结合有点烦琐.
java5 的APT机制,没有了解过。搜索过也是很少资料,看你的描述它的编译和迭代功能还是比较吸引的。能不能给点资料来参考一下呢。^^
TOB (http://tob.ableverse.org) 就是用的APT机制, 不过TOB本身目前还没有开源计划, 教程也还没写好.
WoW (http://www.webofweb.net) 是基于TOB开发的, 开源的, 如果想体验一下, 可以到 http://wow.dev.java.net 下载源码自己编译一回看.
不过现在Eclipse的APT支持还有bug, 必须通过JDK的APT来生成代码, 而JDK1.5的javac也有bug, 生成出来的java代码还必须通过Eclipse来编译. 比较郁闷.
WoW的项目代码包里有个 BUILDING 文件, 按照那里的步骤可以成功完成编译.
8 楼
pedestrian_I
2006-10-29
引用
对于复杂流程的代码生成, 更高级一点的方式是使用antlr一类的语言识别和解释程序, 适合生成流程很复杂的代码, 如mda, dsl的应用, antlr的语句难写也难看懂一点, 如果仅仅是生成crud, 用template, xdoclet就好了
Jack Herrington选择了ruby,在2000年写《code generation》一书的时候他就看中了ruby的作为脚本语言的轻便。选择ruby大肆流行,不得不说jack有眼力。
有个想法,能不能把这个思想延伸到页面的生成。在有几个项目的开发中,页面处理花费了大部分时间,远远超过后台代码的编写时间。而且如果页面上的代码有所不同,体现出来就会给用户很大很直接的不同;如果后台代码实现不同,但是功能实现成功,用户是无法知道的。
页面的组件化,现在也做了很多。比如jsf中就有一个很好的分页组件。如果将常用控件做成模版,引用时传递你需要显示的数据,那么页面处理的时间将大大缩短。模版做成组件,组件搭建前台。
应该很多公司都致力于类似这种工具的开发吧。
7 楼
galaxystar
2006-10-29
思想还是不错的!如果能把模版技术与xml技术用得如火纯青,我想业务代码生成器这样的工具也是指日可待de!
6 楼
pedestrian_I
2006-10-28
代码生成的主要几种实现方式(来自Jack Herrington《Code Generation in action》)
1、模板技术:代码生成通常意味着创建具有复杂结构文本类型的文件。为了维护生成器的简单性和完整性,你可以使用文本模板工具,这样你可以把逻辑的定义和逻辑的代码格式相分离,这是最理想的情况。
模板一直以来都是CodeGeneration的主要实现手段。C++使用模板来实现泛型机制。而众多的建模工具和IDE工具都使用模板来重用代码。在Apache组织的旗下,有一个名为Velocity的项目,它的目的就是提供一种易用的模板技术。Velocity使用了一种脚本语言,叫做Velocity Template Language (VTL)。目前,Velocity主要用于生成Web站点的动态内容。此外,还有更出色的FreeMaker,它比Velocity更全面,可以说Velocity是轻量级的模板技术,而Freemaker是一个强大重量的模板引擎,相比velocity而言,其强大的过程调用、递归和闭包回调功能让freemaker可以完成几乎所有我们所想的功能。此外还有很多的模板技术,这里就不一一介绍了。
2、面向属性编程
英文缩写虽然同样都是AOP,但面向属性编程(Attribute-Oriented Programming )和面向切面编程(Aspect-Oriented Programming )可不是一回事。面向属性编程是通过在代码中添加元数据(属性)的方式来自动产生代码,添加功能。而这方面最优秀的软件莫过于xDoclet。
XDoclet 是一个通用的代码生成实用程序,是一个扩展的Javadoc Doclet引擎(现已与Javadoc Doclet独立),XDoclet是EJBDoclet的后继者,而EJBDoclet是由Rickard Oberg发起的。它允许您使用象 JavaDoc 标记之类的东西来向诸如类、方法和字段之类的语言特征添加元数据。随后,它利用这些额外的元数据来生成诸如部署描述符和源代码之类的相关文件。可以让你创建自己的javadoc @tags进而利用XDoclet中的Templet enging基于这些@tags生成源代码或其他文件。
3、MDA(Model Driven Architecture模型驱动架构)
MDA能够将特定的模型转换为特定平台的代码。AndraMDA就是其中的代表者。在具体实现上,AndraMDA主要采用了模板技术,同时,它也利用了xDoclet技术。所以,AndraMDA是在前两项技术的基础上实现CodeGeneration的。
-------------
其他还有一些,但是不常用。模板技术无疑是用的最广泛的,比如说IDE中就有大量的模板。
1、模板技术:代码生成通常意味着创建具有复杂结构文本类型的文件。为了维护生成器的简单性和完整性,你可以使用文本模板工具,这样你可以把逻辑的定义和逻辑的代码格式相分离,这是最理想的情况。
模板一直以来都是CodeGeneration的主要实现手段。C++使用模板来实现泛型机制。而众多的建模工具和IDE工具都使用模板来重用代码。在Apache组织的旗下,有一个名为Velocity的项目,它的目的就是提供一种易用的模板技术。Velocity使用了一种脚本语言,叫做Velocity Template Language (VTL)。目前,Velocity主要用于生成Web站点的动态内容。此外,还有更出色的FreeMaker,它比Velocity更全面,可以说Velocity是轻量级的模板技术,而Freemaker是一个强大重量的模板引擎,相比velocity而言,其强大的过程调用、递归和闭包回调功能让freemaker可以完成几乎所有我们所想的功能。此外还有很多的模板技术,这里就不一一介绍了。
2、面向属性编程
英文缩写虽然同样都是AOP,但面向属性编程(Attribute-Oriented Programming )和面向切面编程(Aspect-Oriented Programming )可不是一回事。面向属性编程是通过在代码中添加元数据(属性)的方式来自动产生代码,添加功能。而这方面最优秀的软件莫过于xDoclet。
XDoclet 是一个通用的代码生成实用程序,是一个扩展的Javadoc Doclet引擎(现已与Javadoc Doclet独立),XDoclet是EJBDoclet的后继者,而EJBDoclet是由Rickard Oberg发起的。它允许您使用象 JavaDoc 标记之类的东西来向诸如类、方法和字段之类的语言特征添加元数据。随后,它利用这些额外的元数据来生成诸如部署描述符和源代码之类的相关文件。可以让你创建自己的javadoc @tags进而利用XDoclet中的Templet enging基于这些@tags生成源代码或其他文件。
3、MDA(Model Driven Architecture模型驱动架构)
MDA能够将特定的模型转换为特定平台的代码。AndraMDA就是其中的代表者。在具体实现上,AndraMDA主要采用了模板技术,同时,它也利用了xDoclet技术。所以,AndraMDA是在前两项技术的基础上实现CodeGeneration的。
-------------
其他还有一些,但是不常用。模板技术无疑是用的最广泛的,比如说IDE中就有大量的模板。
5 楼
pedestrian_I
2006-10-28
complystill 写道
生成java代码的话用Java5的APT机制比较正统一些, 是和编译结合在一起的, APT会自动调用Annotation Processor, 对生成的新的Java代码会自动编译, 如果还有Annotation就在再迭代, 最后所有的原始代码和生成的代码都编译好以后才结束.
不过ANT目前还不官方支持APT, 结合有点烦琐.
不过ANT目前还不官方支持APT, 结合有点烦琐.
java5 的APT机制,没有了解过。搜索过也是很少资料,看你的描述它的编译和迭代功能还是比较吸引的。能不能给点资料来参考一下呢。^^
4 楼
歆渊
2006-10-27
生成java代码的话用Java5的APT机制比较正统一些, 是和编译结合在一起的, APT会自动调用Annotation Processor, 对生成的新的Java代码会自动编译, 如果还有Annotation就在再迭代, 最后所有的原始代码和生成的代码都编译好以后才结束.
不过ANT目前还不官方支持APT, 结合有点烦琐.
不过ANT目前还不官方支持APT, 结合有点烦琐.
3 楼
pedestrian_I
2006-10-27
没人做过类似的东西吗?想把这个工具升级一下,讨论一下希望能得到新的思路。
2 楼
pedestrian_I
2006-10-27
核心代码部分,contentEngine文件。
至此,这个简单的代码生成器的代码就结束了。很显然它还很弱小,充其量也只是半自动。离完善的代码生成器还差很远。拿出来希望对大家有点用处,另外也希望得到各位的指导,大家讨论一下代码生成器的话题。
package com.bnu.tools; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity; import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.exception.ResourceNotFoundException; import com.bnu.exception.AppException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Iterator; import java.util.Properties; /** * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public class ContentEngine { private VelocityContext context = null; private Template template = null; // private String properties = null ; /** * * @param properties * @throws Exception */ public void init(String properties) throws Exception { if (properties != null && properties.trim().length() > 0) { Velocity.init(properties); } else { Velocity.init(); } context = new VelocityContext(); } public void init(Properties properties) throws Exception { Velocity.init(properties); context = new VelocityContext(); } /** * * @param key * @param value */ public void put(String key, Object value) { context.put(key, value); } /** * 设置模版 * * @param templateFile * 模版文件 * @throws AppException */ public void setTemplate(String templateFile) throws AppException { try { template = Velocity.getTemplate(templateFile); } catch (ResourceNotFoundException rnfe) { rnfe.printStackTrace(); throw new AppException(" error : cannot find template " + templateFile); } catch (ParseErrorException pee) { throw new AppException(" Syntax error in template " + templateFile + ":" + pee); } catch (Exception e) { throw new AppException(e.toString()); } } /** * 设置模版 * * @param templateFile * 模版文件 * @throws AppException */ public void setTemplate(String templateFile, String characterSet) throws AppException { try { template = Velocity.getTemplate(templateFile, characterSet); } catch (ResourceNotFoundException rnfe) { rnfe.printStackTrace(); throw new AppException(" error : cannot find template " + templateFile); } catch (ParseErrorException pee) { throw new AppException(" Syntax error in template " + templateFile + ":" + pee); } catch (Exception e) { throw new AppException(e.toString()); } } /** * 转换为文本文件 */ public String toText() throws AppException { StringWriter sw = new StringWriter(); try { template.merge(context, sw); } catch (Exception e) { throw new AppException(e.toString()); } return sw.toString(); } /** * * @param fileName */ public void toFile(String fileName) throws AppException { try { StringWriter sw = new StringWriter(); template.merge(context, sw); PrintWriter filewriter = new PrintWriter(new FileOutputStream( fileName), true); filewriter.println(sw.toString()); filewriter.close(); } catch (Exception e) { throw new AppException(e.toString()); } } public static void main(String[] args) { ContentEngine content = new ContentEngine(); try { Properties p = new Properties(); Properties varp = new Properties(); String path = args[1]; p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, path); p.setProperty(Velocity.RUNTIME_LOG, path + "velocity.log"); content.init(p); FileInputStream in = new FileInputStream(args[2]); varp.load(in); content.setTemplate(args[3], "gb2312"); Iterator it = varp.keySet().iterator(); String key = ""; String value = ""; while (it.hasNext()) { key = (String) it.next(); value = varp.getProperty(key); content.put(key, value); } if (args[0].equals("DaoImpl")) { content.put("package_Hibernate", args[4]); content.put("import_ObjectNameDao", args[5]); content.put("import_ObjectName", args[6]); content.put("objectname", args[7]); content.put("ObjectName", args[8]); content.toFile(args[9] + '/' + args[10]);//导出的路径,由参数传递。 } //else 其他情况处理部分,这里省略。 } catch (AppException ae) { ae.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }
至此,这个简单的代码生成器的代码就结束了。很显然它还很弱小,充其量也只是半自动。离完善的代码生成器还差很远。拿出来希望对大家有点用处,另外也希望得到各位的指导,大家讨论一下代码生成器的话题。
1 楼
pedestrian_I
2006-10-27
接下来是ant部分,我们编写build.xml
build.xml
这里摘取了daoImpl的声明段,重要部分已经做了注释。
build.xml
<?xml version="1.0" encoding="UTF-8"?> <project name="cmas" basedir="../" default="all"> <!-- Project settings --> <property name="project.distname" value="cmas" /><!-- 设定项目名 --> <property name="project/operationName" value="course/table" /><!-- 设定模块名,如果有多层以“/”方式扩充,此为目录结构变量设定 --> <property name="project.operationName" value="course.table" /><!-- 设定模块名,如果有多层以“.”方式扩充,此为包结构变量设定 --> <property name="ObjectName" value="CourseMember" /><!-- 模块名类名,大写 --> <property name="objectName" value="courseMember" /><!-- 模块名变量名,小写 --> <!-- Local system paths --> <property file="${basedir}/ant/build.properties" /><!-- 设定ant的一些属性,这里我们没有额外的设置,使用默认 --> <property file="${basedir}/${webroot.dir}/template/build.properties" /> <!--Save_path--> <!-- 建立目录结构 --> <mkdir dir="${basedir}/JavaSource/com/bnu/${project.distname}/${project/operationName}/model" /> <mkdir dir="${basedir}/JavaSource/com/bnu/${project.distname}/${project/operationName}/service" /> <mkdir dir="${basedir}/JavaSource/com/bnu/${project.distname}/${project/operationName}/view" /> <!-- 声明目录结构变量 --> <property name="model.src.dir" location="${basedir}/JavaSource/com/bnu/${project.distname}/${project/operationName}/model" /> <property name="service.src.dir" location="${basedir}/JavaSource/com/bnu/${project.distname}/${project/operationName}/service" /> <property name="view.src.dir" location="${basedir}/JavaSource/com/bnu/${project.distname}/${project/operationName}/view" /> <property name="overwrite" value="false" /> <property name="debug" value="true" /> <property name="webroot.dir" value="${basedir}/WebContent" /> <property name="webinf.dir" value="${webroot.dir}/WEB-INF" /> <property name="build.dir" value="build" /> <!-- 模板文件的声明,这里暂时只写ObjectDaoHibernateImpl --> <property name="template.dir" value="${webroot.dir}/template" /> <property name="ObjectDaoHibernateImpl.template" value="./ObjectDaoHibernateImpl.vm" /> <property name="template.properties" value="${template.dir}/template.properties" /> <!--设定classpath,这些包不能少--> <property name="classpath" value="${webinf.dir}/classes/" /> <!-- classpath for JSF 1.1.01 --> <path id="compile.classpath"> <pathelement path="${webinf.dir}/lib/hibernate3.jar" /> <pathelement path="${webinf.dir}/lib/log4j-1.2.9.jar" /> <pathelement path="${webinf.dir}/lib/commons-beanutils.jar" /> <pathelement path="${webinf.dir}/lib/commons-collections.jar" /> <pathelement path="${webinf.dir}/lib/commons-digester.jar" /> <pathelement path="${webinf.dir}/lib/commons-logging.jar" /> <pathelement path="${webinf.dir}/lib/jsf-api.jar" /> <pathelement path="${webinf.dir}/lib/jsf-impl.jar" /> <pathelement path="${webinf.dir}/lib/jstl.jar" /> <pathelement path="${webinf.dir}/lib/standard.jar" /> <pathelement path="${webinf.dir}/lib/log4j.jar" /> <pathelement path="${webinf.dir}/lib/velocity-1.4.jar" /> <pathelement path="${webinf.dir}/lib/velocity-1.4-dev.jar" /> <pathelement path="${webinf.dir}/classes" /> <pathelement path="${classpath.external}" /> <pathelement path="${classpath}" /> </path> <!--*****************Build_Dao_Hibernate_Impl*开始创建daoImpl**********************--> <!-- define your folder for deployment --> <property name="build_daoimpl.dir" value="build_daoimpl" /> <!-- Check timestamp on files --> <target name="build_daoimpl_prepare"> <tstamp /> </target> <!-- Copy any resource or configuration files --> <target name="build_daoimpl_resources"> <copy todir="${webinf.dir}/classes" includeEmptyDirs="no"> <fileset dir="JavaSource"> <patternset> <include name="**/*.conf" /> <include name="**/*.properties" /> <include name="**/*.xml" /> </patternset> </fileset> </copy> </target> <target name="build_daoimpl_init"> <!-- Create the time stamp --> <tstamp /> <!-- Create the build directory structure used by compile --> <mkdir dir="${model.src.dir}/dao/hibernate" /> </target> <!-- Normal build of application --> <target name="build_daoimpl_compile" depends="build_daoimpl_prepare,build_daoimpl_resources,build_daoimpl_init"> <javac srcdir="${basedir}/JavaSource/com/bnu/exception/" destdir="${webinf.dir}/classes/"> <classpath refid="compile.classpath" /> </javac> <!--编译核心java文件contentEngine,这个路径根据具体情况设定,也可以在前面对其进行统一声明--> <javac srcdir="${basedir}/JavaSource/com/bnu/tools" destdir="${webinf.dir}/classes/"> <classpath refid="compile.classpath" /> </javac> <!--运行contentEngine,参数设定--> <java classname="com.bnu.tools.ContentEngine"> <classpath refid="compile.classpath" /> <arg value="DaoImpl" /> <arg value="${template.dir}" /> <arg value="${template.properties}" /> <arg value="${ObjectDaoHibernateImpl.template}" /> <arg value="package com.bnu.${project.distname}.${project.operationName}.model.dao.hibernate;" /> <arg value="import com.bnu.${project.distname}.${project.operationName}.model.dao.${ObjectName}Dao;" /> <arg value="import com.bnu.${project.distname}.${project.operationName}.model.businessobject.${ObjectName};" /> <arg value="${objectName}" /> <arg value="${ObjectName}" /> <arg value="${model.src.dir}/dao/hibernate" /> <arg value="${ObjectName}DaoHibernateImpl.java" /> </java> </target> <!-- Remove classes directory for clean build --> <target name="build_daoimpl_clean" description="Prepare for clean build"> <delete dir="${webinf.dir}/classes" /> <mkdir dir="${webinf.dir}/classes" /> </target> <!-- Build entire project --> <target name="build_daoimpl_build" depends="build_daoimpl_prepare,build_daoimpl_compile" /> <target name="build_daoimpl_rebuild" depends="build_daoimpl_clean,build_daoimpl_prepare,build_daoimpl_compile" /> <target name="build_daoimpl" depends="build_daoimpl_build"> <delete file="${build_daoimpl.dir}/${project.distname}.war" /> <delete dir="${build_daoimpl.dir}/${project.distname}" /> </target> <target name="clean" description="clean"> <delete dir="${build.dir}" /> <delete dir="${webinf.dir}/classes" /> <delete dir="${dist.dir}" /> </target> <target name="all" description="build all" depends="clean,build_daoimpl"> </target> </project>
这里摘取了daoImpl的声明段,重要部分已经做了注释。
相关推荐
3. **基于Ant+Velocity的简单代码生成器的思路与实现 - - Java - JavaEye论坛.mht**:这个文件可能是一个论坛帖子的存档,展示了使用Ant和Velocity构建代码生成器的具体步骤和案例讨论。 4. **velocity(1).rar** 和 ...
所以准确的讲:FCG不是个代码生成器,而是用来开发代码生成器的基础平台. <br/> FCG相比其他生成器,有很多不一样的东西.下面列出FCG几点特性. <br/>1. FCG采用plugin设计体系,一个具体软件架构的生成...
### 知识点一:Apache Velocity 概述与发展历程 - **Apache Velocity**是一种用于Java应用程序的模板引擎,它能够使Web开发人员高效地创建动态HTML网页和其他类型的文档。 - **版本**: Apache Velocity 1.3.x是该书...
对于不满足现成工具的特定需求,开发者也可以编写自己的代码生成器。使用JDBC API获取数据库表信息,结合模板引擎(如FreeMarker或Velocity),生成定制化的Java类。这种方式虽然复杂,但具有更高的灵活性。 4. **...
这个框架提供了项目生成器,使用Maven的archetype插件来创建符合特定规范的项目结构。SpringSide3.0使用Velocity语法的项目模板,生成的项目包括运行所需的配置文件和示例代码。 在开始使用SpringSide3之前,需要...
- `antlr-2.7.6.jar`是ANTLR,一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。 - `velocity-1.4.jar`是Velocity模板引擎,它可以用来生成HTML、XML等格式的输出,与Spring的视图层...
站点生成和报告 (Site Generation and Reporting) 3.6. 小结 4. 定制一个Maven项目 4.1. 介绍 4.1.1. 下载本章样例 4.2. 定义Simple Weather项目 4.2.1. Yahoo! Weather RSS 4.3. 创建Simple Weather...
13. **Implementors**:在追踪代码时,可以直接跳转到方法的具体实现,而非接口。 14. **Call Hierarchy**:展示方法的调用层次结构,便于理解代码间的依赖关系。 15. **EclipseTidy**:基于HTML Tidy,提供HTML和...
在Spring MVC项目中,Ant主要用来编译源代码、生成WAR文件等。 - **配置build.xml**:Ant的工作基于一个XML文件——build.xml,其中定义了各种任务(target)及其依赖关系。 - **编译源码**:使用`<javac>`任务...
10. JSP与Velocity模板:JSP(Java Server Pages)是用于创建动态网页的技术,而Velocity是一个模板引擎,可以用于生成动态内容。 11. 校验机制:本教程介绍使用CommonsValidator来对用户输入进行校验,以确保数据...
2. **创建项目目录和Ant Build文件**:使用Equinox提供的脚本工具创建项目的基本目录结构,并生成Ant Build文件,简化构建过程。 - **项目目录结构**:Equinox为项目提供了基本的目录结构,包括源码、测试代码、...
12. **使用逻辑标签**:Struts提供的逻辑标签(如`<logic:iterate>`、`<logic:equal>`等)可以方便地在JSP页面中实现逻辑控制,避免过多的脚本语言代码。 通过以上步骤的学习,开发者可以掌握基本的Struts应用开发...
_velocity是一种模板引擎,可以用于生成Web页面的动态内容。 最后,我们会添加验证功能,使用CommonsValidator来确保用户输入的数据是有效且安全的。通过这些步骤,我们将完成一个基本的Spring应用程序的开发,并...
16. **Jelly**: Jelly是一个基于XML的脚本和处理引擎,可以用于命令行、Ant或Servlet环境,类似于JSP和Velocity的结合。 17. **Jexl**: Jexl是一个表达式语言,扩展了JSTL,并借鉴了Velocity的经验,可以用于Java...
基于Velocity的渲染器/生成器(Velocity based renderer/generator) 15.3. 映射文件生成器(Mapping File Generation) 15.3.1. 运行此工具 16. 示例:父子关系(Parent Child Relationships) 16.1. 关于...
基于Velocity的渲染器/生成器(Velocity based renderer/generator) 15.3. 映射文件生成器(Mapping File Generation) 15.3.1. 运行此工具 16. 示例:父子关系(Parent Child Relationships) 16.1. 关于...
Spring MVC是Spring框架的一部分,它是一种成熟的、功能丰富的基于动作-响应模型的Web框架,广泛用于处理各种与用户界面(UI)相关和与用户界面无关的Web层用例。Spring MVC以其灵活性、易用性和高度的可配置性而...