JFinal 中使用 Dubbo —— 2 部署及运行

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 () :

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@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 集群

代码交流 2021