您的位置:首页 > 编程语言 > Java开发

使用Spring Roo构建项目

2015-11-22 19:23 441 查看
使用Spring Roo构建项目
结构概述 Architectural Overview

关键技术 Critical Technologies

实体层 Entity Layer
1 初始化项目

2 安装持久化工具

3 创建实体

4 创建字段

网络层 Web Layer
1 建立Web层

2 创建控制器

服务层 Services Layer

库层 Repository Layer

Maven

JSON Add-On

使用Spring Roo构建项目

1. 结构概述 Architectural Overview

Spring Roo
专注于
Java
企业应用的开发。在当前的应用版本
2.0.0.M1
中,构建的应用将以关系数据库为基础,采用
JPA
标准对数据持久化,并大量使用了
Spring
框架中的依赖注入和事务管理,以及
JUnit
测试,利用
Maven
进行项目的配置,以
Spring MVC
为基础将
JSP
作为视图。

使用
Roo
创建的项目和传统项目相比,
Roo
创建的项目去掉了一些不必要的的抽象层。大多数的
Java
企业应用都包含
DAO
层、
domain
层和
controller
层。而在一个使用
Roo
构建的典型项目中,你将只会用到
entity
层(这有点类似于
domain
层,但似乎又结合了
DAO
层和
Services
层)和
web
。当然,如果你的应用的确需要,你可以添加一个
services
层,但是,几乎是不会添加
DAO
层的。

2. 关键技术 Critical Technologies

2.1.
AscpectJ


2.2.
Spring


3. 实体层 Entity Layer

大家在使用
Roo
时,都应该遵循如下的几个步骤:

3.1. 初始化项目

3.2. 安装持久化工具

3.3. 创建实体和字段

3.1. 初始化项目

> mkdir demo
> cd demo
roo> project setup --topLevelPackage cn.edu.cqupt.demo


3.2. 安装持久化工具

roo> jpa setup --database MYSQL --provider HIBERNATE
roo> database properties set --key database.url --value jdbc:mysql://localhost:3306/cblog?useUnicode=true&characterEncoding=utf-8
roo> database properties set --key database.username --value root
roo> database properties set --key database.password --value root


打印信息(仅列出一部分信息)

Updated SPRING_CONFIG_ROOT\applicationContext.xml
Created SRC_MAIN_RESOURCES\META-INF\persistence.xml
Updated SPRING_CONFIG_ROOT\database.properties


路径常量:

SPRING_CONFIG_ROOT
->
src\main\resources\META-INF\spring


SRC_MAIN_RESOURCES
->
src\main\resources\META-INF


jpa setup
命令指定了使用
MYSQL
数据库、
HIBERNATE
映射工具。
database properties
命令修改的是
database.properties
文件中的信息。数据源的相关配置是在
applicationContext.xml
文件中,使用的是
dbcp
HIBERNATE
的配置是在
persistence.xml
文件中。

3.3. 创建实体

entity jpa --class ~.domain.Admin


打印信息(部分)

Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\domain\Admin.java
Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\domain\Admin_Roo_Configurable.aj
Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\domain\Admin_Roo_Jpa_Entity.aj
Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\domain\Admin_Roo_Jpa_ActiveRecord.aj
Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\domain\Admin_Roo_ToString.aj


路径常量:

SRC_MAIN_JAVA\cn
->
src\main\java


从打印的信息中可以看出,有创建如下几个文件:

-
Admin.java
基础类文件

-
Admin_Roo_Configurable.aj
不知道干嘛用的

-
Admin_Roo_Jpa_Entity.aj
包含实体的
version
id
属性,注意,
version
id
属性是和
@RooJpaActiveRecord
有关,而不是
@RooJavaBean


-
Admin_Roo_Jpa_ActiveRecord.aj
主要是实体的
CRUD
操作,对应实体中
@RooJpaActiveRecord
注解

-
Admin_Roo_ToString.aj
实体的
toString()
方法,对应实体类中
@RooToString
注解

The generated method takes care to avoid circular references that are commonly seen in bidirectional relationships involving collections

这个方法(toString)需要注意避免循环引用,尤其是在涉及集合的双向关系时。

3.4. 创建字段

roo> field string --fieldName username --class ~.domain.Admin --notNull --sizeMax 30 --unique
roo> field string --fieldName passwd --class ~.domain.Admin --notNull --sizeMax 60 --sizeMin 6


打印信息

Updated SRC_MAIN_JAVA\cn\edu\cqupt\demo\domain\Admin.java
Updated SRC_MAIN_JAVA\cn\edu\cqupt\demo\domain\Admin_Roo_Jpa_ActiveRecord.aj
Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\domain\Admin_Roo_JavaBean.aj


创建文件
Admin_Roo_JavaBean.aj
,包含实体的
setter
getter
,对应实体类中
@RooJavaBean
注解。

创建的这些实体将会采用
JPA
注解的标准一一映射到数据库中的表,而你无需关心具体使用了哪些注解。

The first time you use one of these Roo field commands, Roo will add required JavaBean Validation API libraries to your project (i.e. these libraries will not be in your project until you decide to first use JavaBean Validation).

尚未读到
JavaBean Validation


这些
AscpectJ ITDs
中声明的方法将会添加到
Admin.class
内。

所以,总结一下

注解名称作用
@RooJpaActiveRecord
实体的
version
id
属性、
CRUD
操作
@RooToString
实体的
toString()
方法
@RooJavaBean
实体的
setter
getter
Admin_Roo_Jpa_ActiveRecord.aj中方法概览:

方法名称描述
entityManager()
获取
entityManager
countAdmins()
获取
admin
的记录总数
findAllAdmins()
查询所有的
admin
记录
findAllAdmins(String sortFieldName, String sortOrder)
查询
admin
记录,
sortFieldName
为排序属性,
sortOrder
为升序或降序
findAdmin(Long id)
通过
id
查找
admin
findAdminEntries(int firstResult, int maxResults)
firstResult
指定查找的第一个记录,
maxResult
指定查找的最大记录
findAdminEntries(int firstResult, int maxResults, String sortFieldName, String sortOrder)
同上,分页并排序
persist()
持久化某实体
remove()
移除某实体
flush()
将持久化的上下文内容同步到底层数据库
clear()
清除持久化上下文内容,是所有管理的实体都处于游离状态
merge()
合并给定的实体的状态到当前的持久化上下文

4. 网络层
Web Layer

Scaffolded web controllers always delegate directly to methods provided on an @RooJpaActiveRecord class.

网络层的控制器总是直接将操作委派给
@RooJpaActiveRecord
标注的类。接下来生成的
AdminController
内部的方法都是直接调用
Admin
中持久化的方法。

If you write a web controller by hand (perhaps with the assistance of the web mvc controller command), it is recommended you also use the methods directly exposed on entities.

所以当你自己需要定义一个controller时,也建议直接使用实体中持久化的方法。

Most Roo applications will place their business logic between the entities and web controllers, with only occasional use of services layers.

大多数的
Roo
应用将他们的业务逻辑放在
Entity
层和
Controller
层之间,因此偶尔会使用到
Service
层。

4.1. 建立
Web

命令:

roo> web mvc setup


打印信息(部分):

Created ROOT\src\main\webapp\WEB-INF\spring\webmvc-config.xml
Created ROOT\src\main\webapp\WEB-INF\web.xml
Created ROOT\src\main\webapp\WEB-INF\i18n\messages.properties


这个命令将一个普通的
Java
项目转变成了一个
Web
项目,同时为项目添加了必要的依赖。

4.2. 创建控制器

命令:

roo> web mvc all --package ~.web


打印信息(部分):

Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\web\AdminController.java
Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\web\ApplicationConversionServiceFactoryBean.java
Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\web\AdminController_Roo_Controller.aj
Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\web\ApplicationConversionServiceFactoryBean_Roo_ConversionService.aj


这个命令会自动检测项目中的实体,为每个实体创建控制器。
ApplicationConversionServiceFactoryBean
是定义的各种转换器。

AdminController_Roo_Controller.aj
中定义的请求映射:

方法名URL参数参数说明请求方式返回的视图
create
/admins
admin
待创建实体的属性
POST
参数错误:admins/create
创建成功:redirect:/admins/{id}
createForm
/admins?form
GET
admins/create
show
/admins/{id}
GET
admins/show
list
/admins
page
size
sortFieldName
sortOrder
roo
自动生成分页参数
均非必需
GET
admins/list
update
/admins
admin
待修改实体的属性
PUT
参数错误:admin/update
修改成功:redirect:/admins/{id}
updateForm
admin/{id}?form
GET
admins/update
delete
/admins/{id}
page
size
需删除的页数和页宽
均非必需
DELETE
redirect:/admins

5. 服务层 Services Layer

大多数
Roo
构建的应用很少需要
Services
层的,因为大多数的逻辑都可以放在
web
层或实体的方法中。但像如下的几种情况可能会用到
services
层:

- 业务逻辑跨越了多个实体

- 你需要调用
web
请求之外的业务逻辑,如定时器任务

- 远程客户端访问,通过一个远程协议直接提供方法(这个我还没读到)

- 降低
web
层的耦合,使
web
层只用于
HTTP
相关的管理,而
services
层只处理业务逻辑

- 需将事务边界和安全认证的元数据放在
services


命令:

roo> service all --interfacePackage cn.edu.cqupt.demo.service


打印信息(部分):

Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\service\AdminService.java
Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\service\AdminServiceImpl.java
Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\service\AdminService_Roo_Service.aj
Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\service\AdminServiceImpl_Roo_Service.aj


AdminService_Roo_Service.aj
中定义了接口,
AdminServiceImpl_Roo_Service.aj
是接口中方法的实现。

方法概览:

Services
层中的方法
调用了实体层的方法
countAllAdmins()
Admin.countAdmins()
deleteAdmin(Admin admin)
admin.remove()
findAdmin(Long id)
Admin.findAdmin(id)
findAllAdmins()
Admin.findAllAdmins()
findAdminEntries(int firstResult, int maxResults)
Admin.findAdminEntries(firstResult, maxResults)
saveAdmin(Admin admin)
admin.persist()
updateAdmin(Admin admin)
admin.merge()

6. 库层 Repository Layer

在当前版本,
Roo
暂不支持不同的库层。

7. Maven

这一层的东东也不太会使。还是用工具导吧,
shell
容易报错。

8. JSON Add-On

命令:

> json all


打印信息:

Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\domain\Admin_Roo_Json.aj


Roo
是使用
FlexJSON
实现实体与
JSON
格式的数据之间的转换的。

Admin_Roo_Json.aj
中方法概览:

方法名称描述
toJson()
admin
转为
JSON
字符串,去除
*.class
属性
toJson(String[] fields)
同上,包含属性
fields
,去除
*.class
属性
fromJsonToAdmin(String json)
JSON
字符串转为
admin
toJsonArray(Collection<Admin> collection)
admin
集合转为
JSON
字符串,去除
*.class
属性
toJsonArray(Collection<Admin> collection, String[] fields)
同上,包含属性
fields
,去除
*.class
属性
fromJsonArrayToAdmins(String json)
JSON
格式字符串转为
admin
集合
命令:

> web mvc json all


打印信息:

> Created SRC_MAIN_JAVA\cn\edu\cqupt\demo\web\AdminController_Roo_Controller_Json.aj


AdminController_Roo_Controller_Json.aj
中定义的请求映射,请求头均包含
Accept=application/json


方法名URL参数参数说明请求方式返回的结果
showJson
/admins/{id}
GET
ResponseEntity<String>
listJson
/admins
GET
ResponseEntity<String>
createFromJson
/admins
admin
JSON格式的admin
POST
ResponseEntity<String>
createFromJsonArray
/admins/jsonArray
admins
JSON格式的admin数组
POST
ResponseEntity<String>
updateFromJson
/admins/{id}
admin
JSON格式的admin
PUT
ResponseEntity<String>
deleteFromJson
/admins/{id}
DELETE
ResponseEntity<String>
对第三个新建
admin
的这个接口我测试了一下,不返回任何结果表示成功创建了:

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://localhost:8080/cblog/admins");
httpPost.addHeader("Accept", "application/json");

try {
StringEntity entityParam=new StringEntity("{\"passwd\":\"123456\",\"username\":\"xiaofeig\"}");
httpPost.setEntity(entityParam);
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}

CloseableHttpResponse response=null;
InputStream instream=null;
try {
response = httpclient.execute(httpPost);
HttpEntity entity = response.getEntity();
if (entity != null) {
instream = entity.getContent();
byte[] b = new byte[200];
int len = -1;
StringBuilder strBuilder = new StringBuilder();
while ((len = instream.read(b)) > 0) {
strBuilder.append(new String(b, 0, len));
}
System.out.println(strBuilder.toString());
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{

if(instream!=null){
try {
instream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(response!=null){
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(httpclient!=null){
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}


由于
admin
username
属性是
unique
,所以当我再次运行上面的代码时,返回了如下的结果:

{"ERROR":org.hibernate.exception.ConstraintViolationException: could not execute statement; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement"}


大家仔细看,就会发现上面的信息
JSON
格式有点不标准,
value
部分左边少了个引号,回到
Roo
自动生成的代码部分,的确是少写了一个引号。

return new ResponseEntity<String>("{\"ERROR\":"+e.getMessage()+"\"}", headers, HttpStatus.INTERNAL_SERVER_ERROR);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring spring-roo