1.
部署及运行
1.1.
部署
请参见“
JFinal
教程
1部署应用到Tomcat的步骤讲得比较详细。部署后结构如下图:
可以看到,
Consumer
和
Provider
都依赖
Api
项目。
1.2.
运行
Consumer
和
Provider
无论谁先启动都可以,输入
URL
后,可以看到
JFinal Demo
原装页面了:
查看管制台,
Provider
输出了数据操作的
SQL
(
ActiveRecordPlugin.setShowSql(true)
),
页面和
Provider
都做出了期望的响应,整个
Demo
就此结束了吗!实际却不是,笔者在此处遇到好几个问题,后面将这些问题和解决方案一一道来。
1.3.
Druid
监控
通过
Provider
服务的“
/druid
”
action
可打开
Druid
监控页面:
即使可以通过启动类将
Provider
做为一般
Java
应用启动,但还是将其建成
Web
项目,原因就在于只有
Web
项目可以打开
Druid
监控。对于开发者来说,
Sql
的执行效率数据很有用。
1.4.
问题及解决方案
1.4.1.
Controller.getModel(class)
问题
在
Demo
运行起来后,对
Blog
进行创建和修改操作时出现了“
Html 500
”的错误,
Consumer
中报错如下:
Blog
列表功、创建和修改都没有问题,唯独保存功能出现异常。
通过调试,查到了问题的根源。在
TableMapping
中,与
Blog
表对应的
Table
数据中没有字段信息。因为字段信息是在
ActiveRecordPlugin
启动时通过
TableBuilder
从数据库中获取的。
解决方案有
3
种:
1.
写个
API
给
Blog
表手动添加字段信息,也就说
Consumer
和
Provider
全部采用
Model
交互。
2.
创建与
Model
对应的
Java Bean
,在
Provider
与数据库打交道时通过反射在
Model
和
Java Bean
之间转换,即采用
Java Bean
交互,但数据库操作还是使用
ActiveRecordPlugin
。
3.
放弃
ActiveRecordPlugin
,
Consumer
和
Provider
全部采用
Java Bean
交互。数据库操作采用
Hibernate
或
Ibatis
等
ORM
。
以上方案各有利弊,笔者为了修改量小,采用了第一种方案,即写了个
API
手动添加
Blog
表的字段信息。
- 创建“
com.jfinal.plugin.activerecord.TableInitKit.java
”,名称空间是“
com.jfinal.plugin.activerecord
”,便于访问
JFinal
中
TableMapping
的保护方法
putTable
()
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 1public final class TableInitKit {
2
3 /**
4 * 手动初始化Model对就的Table字段数据
5 *
6 * @param tableName
7 * 表名
8 * @param modelClass
9 * model的Class
10 * @param attrTypeMap
11 * 字段类型Map
12 */
13 public static void init(String tableName, Class<? extends Model<?>> modelClass,
14 Map<String, Class<?>> attrTypeMap) {
15 init(tableName, "id", modelClass, attrTypeMap);
16 }
17
18 /**
19 * 手动初始化Model对就的Table字段数据
20 *
21 * @param tableName
22 * 表名
23 * @param primaryKey
24 * 主键名
25 * @param modelClass
26 * model的Class
27 * @param attrTypeMap
28 * 字段类型Map
29 */
30 public static void init(String tableName, String primaryKey,
31 Class<? extends Model<?>> modelClass, Map<String, Class<?>> attrTypeMapTypeMap) {
32 Table blogTable = new Table(tableName, primaryKey, modelClass);
33 blogTable.setColumnTypeMap(attrTypeMapTypeMap);
34
35 TableMapping.me().putTable(blogTable);
36 }
37}
38
- 在
Config
的
DemoConsumerConfig.afterJFinalStart()
方法中添加如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 1@Override
2 public void afterJFinalStart() {
3 Map<String, Class<?>> blogColumnMap = new HashMap<String, Class<?>>();
4 blogColumnMap.put("id", Integer.class);
5 blogColumnMap.put("title", String.class);
6 blogColumnMap.put("content", String.class);
7
8 TableInitKit.init("blog", Blog.class, blogColumnMap);
9
10 System.out.println("Blog表字段模拟完成。");
11
12 System.out.println("Demo consumer for Dubbo启动完成。");
13 }
14
重启
Consumer
之后,保存功能正常。至此,初步功能和架构已经完全能正常工作。
源码地址:
JFinalDubboDemoApi.zip
JFinalDubboDemoConsumer.zip
JFinalDubboDemoProvider.zip
Dubbo文档:
Dubbo 的文档镜像
系列文章:
JFinal 中使用 Dubbo —— 1 改造JFinal Demo
JFinal 中使用 Dubbo —— 3 集群