- 浏览: 19516 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
fjjiaboming:
很强大.思想啊.
使用Spring Roo ,感受ROR式的开发 -
Angel_Night:
herowzz 写道其实东西还是spring的那套东西,引擎就 ...
使用Spring Roo ,感受ROR式的开发 -
binarier:
这里有一点刚接触时都会忽略的,就是加字段不需要一个个地add ...
使用Spring Roo ,感受ROR式的开发 -
xuyangcn:
刚刚试了一下,发现对于基本的CRUD确实不错,但是我试图整合J ...
使用Spring Roo ,感受ROR式的开发 -
herowzz:
Kymair 写道liujunsong 写道批评两句.雕虫小极 ...
使用Spring Roo ,感受ROR式的开发
Roo是一种 Spring 开发的辅助工具,使用命令行操作来生成自动化项目,操作非常类似于rails
我这里使用spring tool suit来开发一个demo项目
首先新建个spring template project,然后选择template类型为Roo Wep App (based on Roo 1.0.0.RC1)
这样,便会通过roo的命令自动生成一个标准的maven web项目,里面含有最基本的Spring 配置
建好项目后,我们可以在project上运行roo shell
通过hint命令,我们可以很快的了解各种操作提示
首先,设置数据库
roo会帮你在配置文件applicationContext.xml中配置好了相应的数据源配置,并且在 pom.xml中已经添加jpa和数据库驱动等相关的依赖。
然后新建一个domain
这时roo会帮我们生成Employee类,这时Employee类还没有任何字段,我们可以通过roo shell往里面加入一些字段
最终生成的Employee如下:
你会发现,怎么没有get set呢?我们反编译看下编译后的class代码
经过反编译生成的class发现,通过domain类上面的roo注释,自动在类编译时加入get set,甚至我们发现了findAllEmployees,persist,remove,哈,这不是我们梦寐以求的充血模型吗?
原来,roo在为我们创建domain的时候自动为同一个domain创建了4个aspect(.aj files),并在编译期动态为domain切入代码.
4个aspect分别是:
domainName_Roo_Configurable.aj(配置)
domainName_Roo_Entity.aj(加入orm持久)
domainName_Roo_JavaBean.aj(为字段生成get set)
domainName_Roo_ToString.aj(重写toString)
可见,使用roo我们彻底摆脱了在daomain里对各个属性写get set,并且使domain摇身一变为充血。
下一步,就是建Controller了,同样是一条语句
你会发现,EmployeeController,spring mvc的配置以及curd的jsp页面全部生成了
EmployeeController代码如下:
在这里出现了一行@RooWebScaffold注解,做过rails的人会想,这不是rails里面的scaffold吗?没错,通过@RooWebScaffold注解,EmployeeController自动获得了curd的所有功能。
同样是生成controllerName_Roo_Controller.aj在编译期织入代码
我们来看看生成的EmployeeController_Roo_Controller.aj:
这样,Controller里不用写一行代码,就自动拥有了curd,而且,最新的roo使用了spring3.0,还支持了rest
好了,就这么简单,一个domain,一个Controller,我们就可以发布到tomcat中运行了。
不到5分钟,我们就可以生成了一个可运行的项目,是不是很有ror式的感觉啊?赶快来试试吧!
我这里使用spring tool suit来开发一个demo项目
首先新建个spring template project,然后选择template类型为Roo Wep App (based on Roo 1.0.0.RC1)
这样,便会通过roo的命令自动生成一个标准的maven web项目,里面含有最基本的Spring 配置
建好项目后,我们可以在project上运行roo shell
通过hint命令,我们可以很快的了解各种操作提示
首先,设置数据库
install jpa -provider HIBERNATE -database MYSQL
roo会帮你在配置文件applicationContext.xml中配置好了相应的数据源配置,并且在 pom.xml中已经添加jpa和数据库驱动等相关的依赖。
然后新建一个domain
new persistent class jpa -name ~.domain.Employee -testAutomatically
这时roo会帮我们生成Employee类,这时Employee类还没有任何字段,我们可以通过roo shell往里面加入一些字段
add field string -fieldName name -notNull -sizeMax 200 add field date jpa -fieldName birth -type java.util.Date ......
最终生成的Employee如下:
@Entity @RooEntity @RooJavaBean @RooToString public class Employee { @NotNull @Size(max = 200) private String name; @Temporal(TemporalType.TIMESTAMP) private Date birth; }
你会发现,怎么没有get set呢?我们反编译看下编译后的class代码
// Decompiled by DJ v3.5.5.77 Copyright 2003 Atanas Neshkov Date: 2009-8-8 21:37:43 // Home Page : http://members.fortunecity.com/neshkov/dj.html - Check often for new version! // Decompiler options: packimports(3) // Source File Name: Employee.java package com.javaeye.domain; import java.util.Date; import java.util.List; import javax.persistence.EntityManager; import org.aspectj.runtime.reflect.Factory; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.beans.factory.aspectj.*; // Referenced classes of package com.javaeye.domain: // Employee_Roo_ToString, Employee_Roo_Entity, Employee_Roo_JavaBean public class Employee implements ConfigurableObject { public Employee() { org.aspectj.lang.JoinPoint joinpoint1 = Factory.makeJP(ajc$tjp_1, this, this); org.aspectj.lang.JoinPoint joinpoint = Factory.makeJP(ajc$tjp_0, this, this); if(this != null && getClass().isAnnotationPresent(org/springframework/beans/factory/annotation/Configurable) && AnnotationBeanConfigurerAspect.ajc$if_1((Configurable)getClass().getAnnotation(org/springframework/beans/factory/annotation/Configurable))) AnnotationBeanConfigurerAspect.aspectOf().ajc$before$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$1$e854fa65(this); if(this != null && getClass().isAnnotationPresent(org/springframework/beans/factory/annotation/Configurable) && (this == null || !getClass().isAnnotationPresent(org/springframework/beans/factory/annotation/Configurable) || !AnnotationBeanConfigurerAspect.ajc$if_1((Configurable)getClass().getAnnotation(org/springframework/beans/factory/annotation/Configurable))) && AbstractDependencyInjectionAspect.ajc$if_0(joinpoint)) AnnotationBeanConfigurerAspect.aspectOf().ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(this); Employee_Roo_Entity.ajc$interFieldInit$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$entityManager(this); Employee_Roo_Entity.ajc$interFieldInit$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$id(this); Employee_Roo_Entity.ajc$interFieldInit$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$version(this); if(!AnnotationBeanConfigurerAspect.ajc$if_1((Configurable)getClass().getAnnotation(org/springframework/beans/factory/annotation/Configurable)) && AbstractDependencyInjectionAspect.ajc$if_0(joinpoint1)) AnnotationBeanConfigurerAspect.aspectOf().ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(this); } public static String ajc$privFieldGet$com_javaeye_domain_Employee_Roo_JavaBean$com_javaeye_domain_Employee$name(Employee employee) { return employee.name; } public static void ajc$privFieldSet$com_javaeye_domain_Employee_Roo_JavaBean$com_javaeye_domain_Employee$name(Employee employee, String s) { employee.name = s; } public static Date ajc$privFieldGet$com_javaeye_domain_Employee_Roo_JavaBean$com_javaeye_domain_Employee$birth(Employee employee) { return employee.birth; } public static void ajc$privFieldSet$com_javaeye_domain_Employee_Roo_JavaBean$com_javaeye_domain_Employee$birth(Employee employee, Date date) { employee.birth = date; } public static long countEmployees() { return Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$countEmployees(); } public static EntityManager entityManager() { return Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$entityManager(); } public static List findAllEmployees() { return Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$findAllEmployees(); } public static Employee findEmployee(Long long1) { return Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$findEmployee(long1); } public static List findEmployeeEntries(int i, int j) { return Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$findEmployeeEntries(i, j); } public void flush() { Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$flush(this); } public Date getBirth() { return Employee_Roo_JavaBean.ajc$interMethod$com_javaeye_domain_Employee_Roo_JavaBean$com_javaeye_domain_Employee$getBirth(this); } public Long getId() { return Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$getId(this); } public String getName() { return Employee_Roo_JavaBean.ajc$interMethod$com_javaeye_domain_Employee_Roo_JavaBean$com_javaeye_domain_Employee$getName(this); } public Integer getVersion() { return Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$getVersion(this); } public void merge() { Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$merge(this); } public void persist() { Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$persist(this); } public void remove() { Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$remove(this); } public void setBirth(Date date) { Employee_Roo_JavaBean.ajc$interMethod$com_javaeye_domain_Employee_Roo_JavaBean$com_javaeye_domain_Employee$setBirth(this, date); } public void setId(Long long1) { Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$setId(this, long1); } public void setName(String s) { Employee_Roo_JavaBean.ajc$interMethod$com_javaeye_domain_Employee_Roo_JavaBean$com_javaeye_domain_Employee$setName(this, s); } public void setVersion(Integer integer) { Employee_Roo_Entity.ajc$interMethod$com_javaeye_domain_Employee_Roo_Entity$com_javaeye_domain_Employee$setVersion(this, integer); } public String toString() { return Employee_Roo_ToString.ajc$interMethod$com_javaeye_domain_Employee_Roo_ToString$com_javaeye_domain_Employee$toString(this); } private String name; private Date birth; public transient EntityManager ajc$interField$com_javaeye_domain$entityManager; public Long ajc$interField$com_javaeye_domain_Employee_Roo_Entity$id; public Integer ajc$interField$com_javaeye_domain_Employee_Roo_Entity$version; private static final org.aspectj.lang.JoinPoint.StaticPart ajc$tjp_0; /* synthetic field */ private static final org.aspectj.lang.JoinPoint.StaticPart ajc$tjp_1; /* synthetic field */ static { Factory factory = new Factory("Employee.java", Class.forName("com.javaeye.domain.Employee")); ajc$tjp_0 = factory.makeSJP("initialization", factory.makeConstructorSig("1", "org.springframework.beans.factory.aspectj.ConfigurableObject", "", "", ""), 17); ajc$tjp_1 = factory.makeSJP("initialization", factory.makeConstructorSig("1", "com.javaeye.domain.Employee", "", "", ""), 17); } }
经过反编译生成的class发现,通过domain类上面的roo注释,自动在类编译时加入get set,甚至我们发现了findAllEmployees,persist,remove,哈,这不是我们梦寐以求的充血模型吗?
原来,roo在为我们创建domain的时候自动为同一个domain创建了4个aspect(.aj files),并在编译期动态为domain切入代码.
4个aspect分别是:
domainName_Roo_Configurable.aj(配置)
domainName_Roo_Entity.aj(加入orm持久)
domainName_Roo_JavaBean.aj(为字段生成get set)
domainName_Roo_ToString.aj(重写toString)
可见,使用roo我们彻底摆脱了在daomain里对各个属性写get set,并且使domain摇身一变为充血。
下一步,就是建Controller了,同样是一条语句
new controller automatic -formBackingObject ~.domain.Employee -name ~.web.CommentController
你会发现,EmployeeController,spring mvc的配置以及curd的jsp页面全部生成了
EmployeeController代码如下:
@RooWebScaffold(automaticallyMaintainView = true, formBackingObject = Employee.class) @RequestMapping("/employee/**") @Controller public class EmployeeController { }
在这里出现了一行@RooWebScaffold注解,做过rails的人会想,这不是rails里面的scaffold吗?没错,通过@RooWebScaffold注解,EmployeeController自动获得了curd的所有功能。
同样是生成controllerName_Roo_Controller.aj在编译期织入代码
我们来看看生成的EmployeeController_Roo_Controller.aj:
package com.javaeye.web; privileged aspect EmployeeController_Roo_Controller { @org.springframework.web.bind.annotation.RequestMapping(value = "/employee", method = org.springframework.web.bind.annotation.RequestMethod.POST) public java.lang.String EmployeeController.create(@org.springframework.web.bind.annotation.ModelAttribute("employee") com.javaeye.domain.Employee employee, org.springframework.validation.BindingResult result) { if (employee == null) throw new IllegalArgumentException("A employee is required"); for(javax.validation.ConstraintViolation<com.javaeye.domain.Employee> constraint : javax.validation.Validation.buildDefaultValidatorFactory().getValidator().validate(employee)) { result.rejectValue(constraint.getPropertyPath(), null, constraint.getMessage()); } if (result.hasErrors()) { return "employee/create"; } employee.persist(); return "redirect:/employee/" + employee.getId(); } @org.springframework.web.bind.annotation.RequestMapping(value = "/employee/form", method = org.springframework.web.bind.annotation.RequestMethod.GET) public java.lang.String EmployeeController.createForm(org.springframework.ui.ModelMap modelMap) { modelMap.addAttribute("employee", new com.javaeye.domain.Employee()); return "employee/create"; } @org.springframework.web.bind.annotation.RequestMapping(value = "/employee/{id}", method = org.springframework.web.bind.annotation.RequestMethod.GET) public java.lang.String EmployeeController.show(@org.springframework.web.bind.annotation.PathVariable("id") java.lang.Long id, org.springframework.ui.ModelMap modelMap) { if (id == null) throw new IllegalArgumentException("An Identifier is required"); modelMap.addAttribute("employee", com.javaeye.domain.Employee.findEmployee(id)); return "employee/show"; } @org.springframework.web.bind.annotation.RequestMapping(value = "/employee", method = org.springframework.web.bind.annotation.RequestMethod.GET) public java.lang.String EmployeeController.list(org.springframework.ui.ModelMap modelMap) { modelMap.addAttribute("employees", com.javaeye.domain.Employee.findAllEmployees()); return "employee/list"; } @org.springframework.web.bind.annotation.RequestMapping(method = org.springframework.web.bind.annotation.RequestMethod.PUT) public java.lang.String EmployeeController.update(@org.springframework.web.bind.annotation.ModelAttribute("employee") com.javaeye.domain.Employee employee, org.springframework.validation.BindingResult result) { if (employee == null) throw new IllegalArgumentException("A employee is required"); for(javax.validation.ConstraintViolation<com.javaeye.domain.Employee> constraint : javax.validation.Validation.buildDefaultValidatorFactory().getValidator().validate(employee)) { result.rejectValue(constraint.getPropertyPath(), null, constraint.getMessage()); } if (result.hasErrors()) { return "employee/update"; } employee.merge(); return "redirect:/employee/" + employee.getId(); } @org.springframework.web.bind.annotation.RequestMapping(value = "/employee/{id}/form", method = org.springframework.web.bind.annotation.RequestMethod.GET) public java.lang.String EmployeeController.updateForm(@org.springframework.web.bind.annotation.PathVariable("id") java.lang.Long id, org.springframework.ui.ModelMap modelMap) { if (id == null) throw new IllegalArgumentException("An Identifier is required"); modelMap.addAttribute("employee", com.javaeye.domain.Employee.findEmployee(id)); return "employee/update"; } @org.springframework.web.bind.annotation.RequestMapping(value = "/employee/{id}", method = org.springframework.web.bind.annotation.RequestMethod.DELETE) public java.lang.String EmployeeController.delete(@org.springframework.web.bind.annotation.PathVariable("id") java.lang.Long id) { if (id == null) throw new IllegalArgumentException("An Identifier is required"); com.javaeye.domain.Employee.findEmployee(id).remove(); return "redirect:/employee"; } @org.springframework.web.bind.annotation.InitBinder public void EmployeeController.initBinder(org.springframework.web.bind.WebDataBinder binder) { binder.registerCustomEditor(java.util.Date.class, new org.springframework.beans.propertyeditors.CustomDateEditor(new java.text.SimpleDateFormat("yyyy-M-d"), false)); } }
这样,Controller里不用写一行代码,就自动拥有了curd,而且,最新的roo使用了spring3.0,还支持了rest
好了,就这么简单,一个domain,一个Controller,我们就可以发布到tomcat中运行了。
不到5分钟,我们就可以生成了一个可运行的项目,是不是很有ror式的感觉啊?赶快来试试吧!
评论
2 楼
helian
2009-11-06
Roo对于了解Spring的新动向很有帮助。不过这东西理念上跟grail很重合,springsource居心叵测啊
1 楼
slaser
2009-08-09
SpringSource 在简化java开发方向上做的努力让人敬佩。
不过不知道在通过annotation简化java语言和直接采用groovy这类动态语言方面,SpringSource是如何选择这个方向的。
这也可能是java社区所面临的选择。
不过不知道在通过annotation简化java语言和直接采用groovy这类动态语言方面,SpringSource是如何选择这个方向的。
这也可能是java社区所面临的选择。
相关推荐
在本篇文章中,我们将深入探讨 Spring Roo 的使用,以及如何结合 Cloud Foundry 进行云端应用开发。Spring Roo 是一个基于 Java 的开源工具,它简化了 Spring 应用程序的构建过程,通过自动化任务和代码生成,让...
- **IDE 集成**:将 Spring Roo 与 IDE 结合使用以提升开发体验。 - **创建 Web 层**:为应用添加前端交互能力。 - **部署与安全**:介绍如何部署应用并实现基本的安全措施。 #### 六、应用架构概述 - **整体...
标题《Spring Roo In Action》意味着这本书是一本实用指南,旨在向读者展示如何使用Spring Roo来开发实际的Java应用程序。从描述中可以得知,本书是Manning出版社出版的完整版,它可能包含了Spring Roo的基本概念、...
书中还涉及了Web开发部分,探讨了如何使用Spring Roo快速搭建Web应用程序,包括使用Spring MVC进行控制器和视图层的快速开发。Spring Roo的Web开发支持包括了多种Web层技术,方便开发者根据项目需求选择合适的技术...
在开始使用Spring ROO之前,你需要确保你的开发环境已经准备就绪。首先,你需要安装Java Development Kit (JDK)。JDK是Java编程的基础,它包含了编译器、Java运行时环境以及其他必要的工具。确保你的JDK版本与Spring...
Spring Roo是Spring框架的一部分,它提供了一种快速开发工具,帮助开发者在Java应用中创建和管理代码。Roo通过自动化过程,简化了常见的开发任务,如设置项目结构、创建实体类、生成数据库表映射以及创建CRUD操作。...
Spring Roo是Spring框架家族中的一个创新工具,旨在简化Java应用程序的开发过程,特别是企业级应用。它基于Spring的模块化架构,提供了一种快速开发、自动化代码生成和最佳实践集成的解决方案。Spring Roo 1.1.3是该...
SpringRoo是Spring框架的扩展,它使用命令行界面(CLI)或集成开发环境(IDE)插件来提供代码生成和自动化功能。它的目标是简化Java应用程序的构建过程,特别适合于Spring Boot应用的早期开发阶段。 二、安装与设置...
Spring Roo是Spring框架家族中的一个开发工具,它旨在加速Java应用程序的开发过程,特别是通过提供命令行接口和集成开发环境(IDE)插件来简化常见的编程任务。标题"spring-roo-1.1.5.RELEASE"指的是Spring Roo的一...
Spring Roo是Spring框架家族中的一个工具,用于加速Java开发,特别是企业级应用的构建。它通过命令行界面或集成开发环境(IDE)插件提供了一种快速开发的方式,可以帮助开发者生成代码、设置依赖和配置,使得开发...
SpringRoo 是一款由 Pivotal Software(现为 VMware 的一部分)开发的快速应用开发工具。它旨在帮助开发者简化基于Spring框架的应用程序构建过程。SpringRoo 通过提供一系列自动化代码生成功能,允许开发者在几分钟...
Spring Roo是Spring框架家族中的一个开发工具,它旨在加速Java应用程序的开发过程,特别是通过自动化常见任务和提供代码生成功能。Spring Roo 1.3.2是该工具的一个版本,其发布版本为RELEASE,意味着它是稳定且可供...
Spring Roo是Spring框架家族中的一个开源工具,旨在简化Java应用程序的开发过程,特别是Spring MVC和Spring Data应用。这个"spring-roo-2.0.0.RC1.zip"压缩包包含的是Spring Roo的2.0.0 Release Candidate 1版本,这...
【os-springroo2-sample_code】项目是一个关于Spring Roo的示例代码库,它展示了如何使用Spring Roo框架来快速开发应用程序。Spring Roo是Spring框架的一部分,它提供了一种简化和加速Java应用开发的方式,通过自动...
- **更高生产力:** 使用SpringRoo可以显著减少开发时间,因为它提供了一系列自动化工具来生成代码模板。 - **标准Java实践:** SpringRoo遵循Java的最佳实践,这意味着生成的应用程序符合行业标准。 - **易于学习和...
本文将深入剖析Spring Roo的关键特性和使用流程,帮助读者理解如何利用这一工具提高开发速度,同时确保代码质量和可维护性。 #### 1.1 Spring Roo的核心价值:更高生产力 Spring Roo通过其独特的命令行接口(CLI)...
使用 Spring Roo 开发应用程序涉及以下几个步骤: 1. **初始化项目**:使用 `roo new` 命令创建一个新的 Spring Roo 项目。 2. **添加实体**:使用 `entity` 命令创建数据库实体。 3. **定义字段**:使用 `field` ...
Spring Roo是Spring Framework的一个附加工具,它为Java开发者提供了一个快速开发平台,旨在简化和加速应用程序的构建过程。"spring-roo-1.1.0.M1.zip_54587.m1_M1 ssh_Spring Roo download_spri"这个标题暗示了这是...
### Spring Roo Action: 加速开发流程的利器 #### 引言 随着软件开发技术的不断发展,开发者们一直在寻求更高效、更便捷的方式来构建高质量的应用程序。Spring Roo 正是为了解决这一需求而诞生的。它是一种快速应用...