使用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命令,我们可以很快的了解各种操作提示

首先,设置数据库

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式的感觉啊?赶快来试试吧! :D
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值