Latke在设计上原理类似与Spring,可以理解为是Spring的极简版。
本文章是对 https://hacpai.com/article/1466870492857 的补充
概述
Latke是一个简单易用的Java Web应用开发框架,包含IOC容器、事件通知、持久化、插件等组件,也包含一些应用开发时需要的基本服务(例如缓存、定时任务、邮件、HTTP客户端等)
整个框架采取MVC架构思想,常用的几个注解是
@RequestProcessor //请求处理 控制器
@Inject //服务调用
@Service //服务实现 服务
@Repository //持久层注解 DAO层
引擎
所使用的引擎为FreeMarker
主要使用的元素有:
${...} 这个表达式被称为interpolation(插值)。正如其名字所说,FreeMarker将其数据模型上的值取出替换表达式。
注释 <#-- something -->
FTL标签(FreeMarker模版的语言标签)
<#if condition> ... <#elseif condition2> ... <#elseif condition3> ... <#else> ... </#if>
引擎实例
如:
1 <html> 2 <head> 3 <title>Welcome!</title> 4 </head> 5 <body> 6 <h1>Welcome ${user}!</h1> 7 <p>Our latest product: 8 <a href="${latestProduct.url}">${latestProduct.name}</a>! 9 </body> 10 </html>
在FreeMarker引擎上工作时,上面的${user} 就是取出数据模型中的数据,而整个HTML就是一个静态的模版。用户访问时,引擎会根据用户访问的内容,更新数据。
如:
1 <html> 2 <head> 3 <title>Welcome!</title> 4 </head> 5 <body> 6 <h1>Welcome Abel Keith!</h1> 7 <p>Our latest product: 8 <a href="products/greenmouse.html">green mouse</a>! 9 </body> 10 </html>
数据模型
这里的数据模型是树形结构,图形化可以是这样。这只是个形象化的解释,数据模型不是文本格式,它来自于Java对象:
(root)
|
+- user = "Big Joe"
|
+- latestProduct
|
+- url = "products/greenmouse.html"
|
+- name = "green mouse"
用一句话概括我们将会使用的这个引擎:模版 + 数据模型 = 输出
其它关于引擎就不详述,如有兴趣,就去搜索相关文件
IOC 容器
实现 JSR-330 规范 又称 Java 依赖注入标准(JSR-330, Dependency Injection for Java)
详情链接:https://blog.csdn.net/dl88250/article/details/4838803
这里使用的javax.inject的注入为依赖注入
不使用依赖注入,使用构造方法获取对象的方法:
1 class Stopwatch { 2 final TimeSource timeSource; 3 Stopwatch () { 4 timeSource = new AtomicClock(...); 5 } 6 void start() { ... } 7 long stop() { ... } 8 }
通过工厂或者定位器实现
1 class Stopwatch { 2 final TimeSource timeSource; 3 Stopwatch () { 4 timeSource = DefaultTimeSource.getInstance(); 5 } 6 void start() { ... } 7 long stop() { ... } 8 }
添加清理方式的对象创建
1 void testStopwatch() { 2 TimeSource original = DefaultTimeSource.getInstance(); 3 DefaultTimeSource.setInstance(new MockTimeSource()); 4 try { 5 // Now, we can actually test Stopwatch. 6 Stopwatch sw = new Stopwatch(); 7 ... 8 } finally { 9 DefaultTimeSource.setInstance(original); 10 } 11 }
以上这些代码在应用过程中可能会引起各种不必要的复杂度,以及各种潜在的问题。
而依赖注入则可以解决这些问题,提供了很高的弹性。它替程序员调用构造器或者工厂,一个称作依赖注入器的工具将把依赖传递给对象:
1 class Stopwatch { 2 final TimeSource timeSource; 3 @Inject Stopwatch(TimeSource timeSource) { 4 this.TimeSource = timeSource; 5 } 6 void start() { ... } 7 long stop() { ... } 8 }
注入器会进一步地传递依赖给其他的依赖,直到它构造出整个对象图。当一个程序员创建一个StopwatchWidget实例:
1 /** GUI for a Stopwatch */ 2 class StopwatchWidget { 3 @Inject StopwatchWidget(Stopwatch sw) { ... } 4 ... 5 }
注入器可能会做这些工作:
1. 查找一个 TimeSource 实例
2. 使用找到的 TimeSource 实例构造一个 Stopwatch
3. 使用构造的 Stopwatch 实例构造一个 StopwatchWidget
这时候我们简单了解了,@Inject 可能会做那些事了,以及它在 Latke框架中IOC的作用
事件通知
通过事件管理器接口可进行时间监听器注册、事件发布、实现发布/订阅模式
ORM
主要提供了对JSON对象的增删改查功能,可以支持关系型数据库(MySQL、H2、SQLServer) 以及 Redis 的数据存取。
插件
插件包含完整的前端与后端功能,可以在不修改已有代码的前提下扩展应用功能,并支持运行时的拔插。
国际化
在模版中可以直接使用 ${xxxx} 的形式读取语言配置,后端提供了语言服务来获取不同 Locale 的语言配置
服务
框架内置应用开发时需要的一些基本的常用服务:
- 缓存(CacheFactory,Cache)
- 图片处理(ImageServiceFactory,ImageService)
- 邮件(MailServiceFactory,MailService)
- HTTP 客户端(URLFetchServiceFactory,URLFetchService)
- 用户管理(UserServiceFactory,UserService)
- 日志(Logger)
- 任务队列(TaskQueueServiceFactory,TaskQueueService)
- 多语言(LangPropsService)
小结
大体上需要补充的一些个性化内容就这些了。