1. 框架概述
VRaptor 是一个简单直接的 Java MVC Web 框架,它基于 Java 上下文和依赖注入(CDI)技术构建,学习曲线平缓。和 Spring 类似,它重度依赖注解且与 Hibernate 配合默契。
框架还提供了一些实用插件,比如国际化支持和单元测试工具。接下来我们将深入探索 VRaptor 的核心组件并构建一个示例项目。
2. Maven 依赖与环境搭建
快速启动的最佳方式是从官方仓库下载 vraptor-blank-project-distribution。这个空白项目只是一个骨架,可以扩展为完整的 Web 应用。
下载解压后,将目录重命名为 vraptor(或其他名称)。目录应包含:
- src/
- pom.xml
- README.md
项目基于 Maven,内置了 tomcat7 Maven 插件作为 Servlet 容器。默认包含一个 IndexController,仅有一个 index() 方法。该方法渲染的视图默认位于 webapp/WEB-INF/jsp/index/index.jsp,遵循 WEB-INF/jsp/控制器名/方法名 的约定。
执行 mvn tomcat7:run
启动服务器。成功后访问 http://localhost:8080,浏览器会显示 "It works!! VRaptor!"。
⚠️ 踩坑提示:如果遇到 java.lang.LinkageError: loader constraint violation
错误,需修改 pom.xml 中的依赖:
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet-core</artifactId>
<version>2.1.2.Final</version>
<exclusions>
<exclusion>
<groupId>org.jboss.spec.javax.el</groupId>
<artifactId>jboss-el-api_3.0_spec</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core-impl</artifactId>
<version>2.1.2.Final</version>
<exclusions>
<exclusion>
<groupId>org.jboss.spec.javax.el</groupId>
<artifactId>jboss-el-api_3.0_spec</artifactId>
</exclusion>
</exclusions>
</dependency>
问题根源是 weld-servlet-core 和 weld-core-impl 中包含的 el-api 依赖冲突。后续需要添加以下依赖:
<dependency>
<groupId>br.com.caelum.vraptor</groupId>
<artifactId>vraptor-freemarker</artifactId>
<version>4.1.0-RC3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.8-dmr</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.27-incubating</version>
</dependency>
最新版本可在 Maven Central 查找。环境就绪后,我们开始构建一个简单的博客系统。
3. Hibernate 集成
VRaptor 提供多种数据库交互插件,其中 vraptor-hibernate 支持 Hibernate 4。该插件通过 CDI 在运行时提供 Hibernate 的 SessionFactory Bean。
配置插件后,需要标准的 Hibernate 配置文件(示例见仓库)。VRaptor 使用 Producer 技术将对象纳入 DI 管理,详见官方文档。
4. Web 路由定义
在 VRaptor 中,路由定义位于控制器(用 @Controller 注解的 Java 对象)中,类似 Spring:
- @Path 映射请求路径
- @Get/@Post/@Put/@Delete/@Patch 指定 HTTP 方法
路由配置类似 JAX-RS 但未实现其标准。定义路径时可用花括号指定路径变量:
@Get("/posts/{id}")
控制器方法可直接访问变量值:
@Get("/posts/{id}")
public void view(int id) {
// ...
}
表单提交时,VRaptor 能自动将表单数据填充到对象中,后续章节将演示具体用法。
5. 视图与模板引擎
默认使用 JSP 实现视图,但也可集成其他模板引擎(本文使用 Freemarker)。创建 index.ftl 并保存到默认视图目录(src/main/resources/templates):
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>VRaptor Blank Project</title>
</head>
<body>
It works!! ${variable}
</body>
</html>
通过 FreemarkerView 类渲染视图:
@Path("/")
public void index() {
result.include("variable", "VRaptor!");
result.use(FreemarkerView.class).withTemplate("index");
}
Result 对象管理模型状态,支持页面/URL/控制器方法重定向,可通过 CDI 注入。示例中 variable 被 Freemarker 解析,替换 index.ftl 中的占位符。高级用法见文档。
6. 表单提交处理示例
带验证的表单提交处理:
@Post("/post/add")
public void add(Post post) {
post.setAuthor(userInfo.getUser());
validator.validate(post);
if(validator.hasErrors()) {
result.include("errors", validator.getErrors());
}
validator.onErrorRedirectTo(this).addForm();
Object id = postDao.add(post);
if(Objects.nonNull(id)) {
result.include("status", "Post Added Successfully");
result.redirectTo(IndexController.class).index();
} else {
result.include(
"error", "There was an error creating the post. Try Again");
result.redirectTo(this).addForm();
}
}
Post 对象先通过 Java Bean Validation 验证,再通过 postDao.add() 持久化。对象字段由表单数据自动填充——注意输入字段名必须用小写对象名作为前缀。
例如添加文章的表单字段:
<input type="text" class="form-control" placeholder="Title"
id="title" name="post.title" required />
<textarea rows="10" class="form-control" placeholder="Post"
id="post" name="post.post" required></textarea>
完整 add.ftl 见源码。提交出错时:
if(validator.hasErrors()) {
result.include("errors", validator.getErrors());
}
validator.onErrorRedirectTo(this).addForm();
错误信息会被包含并重定向回表单页面。
7. 总结
本文概述了 VRaptor 的核心功能,展示了基本 MVC 实现方式。更多细节和插件请参考官方文档。
完整源码(含示例 database.sql)见 GitHub 仓库。