Java Web:我对架构中分层的理解暨 Bigfoot Web 框架简介

本文涉及的产品
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
数据传输服务 DTS,数据同步 small 3个月
推荐场景:
数据库上云
数据传输服务 DTS,数据同步 1个月
简介: J2EE 世界充斥着许多概念,如 MVC、Service、DAO 等等,而且这些许多都是“似是而非”的名词。如果不对这些概念进行厘清,恐怕不能全然贯通、明晰整个框架。这就体现了概念其重要性。鄙人希望:一、概念虽然会比较”笼统“,——这是因为概念处于较高层的位置,有涵盖的作用,但应该尽量明晰和收窄定义的范围;二、从概念到某件事物,是”抽象“到”具象“的过程,会形成某个特定”名词“,既然”名词“是特指的,那么应该没有二义性,即没有歧义;三、概念最后能找到真正所对应的具体事物,可以在代码中反映出来的。

J2EE 世界充斥着许多概念,如 MVC、Service、DAO 等等,而且这些许多都是“似是而非”的名词。如果不对这些概念进行厘清,恐怕不能全然贯通、明晰整个框架。这就体现了概念其重要性。鄙人希望:一、概念虽然会比较”笼统“,——这是因为概念处于较高层的位置,有涵盖的作用,但应该尽量明晰和收窄定义的范围;二、从概念到某件事物,是”抽象“到”具象“的过程,会形成某个特定”名词“,既然”名词“是特指的,那么应该没有二义性,即没有歧义;三、概念最后能找到真正所对应的具体事物,可以在代码中反映出来的。凡事须顾名思义,有其名就当有其实;四、理想情况下,一个系统不应存在重复的代码或模块。如果赋予一个事物有一个概念或名词 A,A 具有排他性,不能再使用,但可以包含其所属的 B 事物。即,A 是 A,B 是 B。如果 A 包含 B,那么 A ≠ B。

需要指出的是,本文所讨论的定义对其他框架不一定适用,请不要周延,当前仅限于 Bigfoot 界定概念所用——这也是为了避免争议的提前声明,同时这样也比较简单,点到即止。

基础概念

分层是应对复杂性的必然手段。解决一个个各自的小问题,最终来解决大问题,“分而治之”。

程序三层结构,毋庸置疑。


与数据库打交道的三个方法

以上脑图参考自《三层究竟如何?》

我们比较推崇“半自动 SQL”的方法,既非直接写 SQL,也不是 ORM(也不熟悉 存储过程)。此方面的具体内容,参见前篇文章《浅浅地封装一层 JDBC》

一般 SSH 结构

虽然有经典 SSH 架构摆在面前,但我们并不拘泥于此,同样积极寻找适应项目变化,可重用,方便程序员的架构方法,以适应于“互联网程序架构”而非单单“企业级开发”的架构。

JavaEE 体系架构

JavaEE 体系架构采用传统的 MVC 设计模式,分为 Model、View、Controller 三层,其中:Model 即模型层,定义数据模型和业务逻辑。

为了将数据访问与业务逻辑分离,提高业务精度,降低代码之间的耦合,模型层又细分为 DAO 层与 Service 业务层,DAO 全称为 Data Access Object(数据访问对象),将数据库访问代码封闭起来,MyBatis API 也在此封装,不再出现在其他层或向其他层暴露;业务层是整个系统最核心也最具价值的一层,该层对应用程序的业务逻辑进行封装,务求关注客户需求,在业务处理过程中会访问原始数据或产生新数据,或者需要持久化数据,DAO 层提供的 DAO 类能很好地帮助业务层完成数据处理,业务层本身则侧重于对客户需求的理解和业务规则的适应,自然也包括大部分的计算。

总体说来,DAO 不处理业务逻辑,只做与存取数据有关的获取原始数据或持久化数据等操作,为业务层提供辅助。

View 即视图层,为最终用户提供一个友好的交互界面,用户可以查看请求结果,也可以通过表单等交互手段实现数据录入。

Controller 层即控制器,他是 Model 与 View的桥梁,将二者很好的衔接,通过 View 接收用户数据,Controller 将数据传输给Model,Model 对数据进行处理;或者 Model 读取数据后,Controller 将数据传递给 View,View 向用户展示数据。一来一往,Controller 成了 Model 与 View 之间的快乐使者。具体来说,Controller 负责数据验证,跳转逻辑,赋值/取值。这里会出现 Request/Response 对象——但将 Request/Response 对象放到其他层就不合适了,举个反例,如果在 Service 层出现 Request/Response 对象那么有必要进行重构修正了。

  • 从调用关系上看,左为高层,右为低层,下为高层,上为低层,高层可以调用低层,但低层不能调用高层,层与层之间的调用是单向的。
  • 从数据传输上看,数据可以从视图层传输到 DAO 进而保存到数据库,也可以从数据库中读取数据进行处理或者显示,所以数据的传输是双向的。
  • 从技术实现上看,视图层使用 HTML/JSP 组件实现,控制器使用 Servlet 或 Action 组件实现,模型层使用 JavaBean 组件或 EJB 技术实现。

MyBatis 封装在 DAO 层,负责数据访问操作;Spring MVC 充当控制器角色,对用户数据进行合法性检验和类型转换,为视图层提供标签简化页面显示,提供国际化支持等等;Spring是应用程序的管家,DAO、Service(业务)、Action 等对象由 Spring 创建并维护各对象之间关系,同时提供声明式事务管理,简化事务编程。

MVC 结构

可维护的结构



MVC 是个大领纲,不同的框架对 MVC 的理解和实践都不尽相同,有时候甚至很难一一对号入座,也有许多衍生分支的版本。实际上,MVC 是一种模式,模式不是公式,所以除了必要的条件限定之外,就没有一定的条条框框。

注意,前面说到的三层架构 ≠ MVC。

除了经典的 JSP + Bean + Servlet 架构外,还有一种更为简单的 JSP + Bean 模式。两者区别在于处理的主控部分不同。前者利用 Servlet 作为主控部分;后者利用 JSP 作为主控部分,将用户的请求、Bean 和事件响应有效的连接起来。

我比较倾向于 JSP + Bean 模式。该模式工作原理是:当 HTTP 发出请求时,JSP 接收请求并访问 Bean,当需要访问数据库或者服务器时,则通过  Bean 做相应处理。Bean 将处理的结果返回 JSP,JSP 生成动态 html 将结果传送到浏览器并显示,用户得到交互结果。JSP 作为视图,同时也有部分控制器的功能, Bean 组件作为模型和控制器组件。

这样的好处是首先不用配置 Servlet,一个 JSP 即是 Servlet(请求路径多起来维护麻烦),其次是 JSP 以显示为中心,它为 Web 前端开发提供了更方便的开发。再者是仍然可以做到显示和内容分离,显示和业务逻辑开发可以分开同时进行,实际上并不会在 JSP 嵌入大量 Java 代码,而且显得更简单。

必须提出的是,纯 service 接口的话应该使用 Bean + Servlet 的模式,那是完全排除表示层的考虑。


前端分层,围绕 HTML、CSS、JS 三大模块来处理。


模板技术我主张使用 Tag Files。有关 Tag Files 的更多教程,参见本博客《JSP Tag Files 技术总结》

项目选型

经过反复使用和衡量,决定采用下面的组件。分有前端和后端的(点击图片放大)。


前端堆栈我的方案如下:



Bigfoot 简介

“大脚 Bigfoot”是一款基于 JEE 平台研发的 Web 框架,继承了 Java 平台的高效、安全、稳定、跨平台等诸多优势,但却摒弃了传统 SSH 企业级架构所带来的庞大和臃肿,汲取了 PHP 的简洁和方便,非常适合互联网中小型网站的应用。

Bigfoot 是真正的开源、真正的免费,其代码直观、简洁,功能方面简单实用。该系统没有去做审核流程、复杂权限和日志等企业级的功能。对于这些功能,中小型互联网项目或许不是首要考虑;当前版本力求简单和通俗易懂的代码,也就是作为基础框架而考虑的。同时大脚也注重扩展性——更复杂的功能,可以留待二次开发。

个人认为 Java 在互联网应用之所以不及 PHP 那么受欢迎,其中一个主要是因为技术人员过分追求复杂的技术架构和为概念应用而应用(怕别人说技术不专业);搞得草根都不敢去用 Java 去了;于是这样的结果是严重阻碍了 Java 在互联网的应用和推广——而 PHP 在互联网的成功在于:简单和务实(PHP 的织梦成功正是这个原因)。我们的理念:Keep it simple, stupid,做一款简单实用的开源 Web。

迈普 CMS(MyPro Content Manage System)是以 Bigfoot 基础框架为依托的网站管理系统,具有懂 HTML 就能建站的优点,提供最便利、合理的使用方式。前端模板完全开放,可让用户随心所欲的自定义显示内容和显示方式。

“大脚 Bigfoot”整体特性:

  1. 免费、简单、开源
  2. 代码行数少,概念清晰,避免过渡设计
  3. 力求高聚合、低耦合
  4. 全栈式方案,包括前端控件和服务端接口,无缝对接
  5. 基于 JVM 的混合语言编程 = Java + JavaScript(服务端 Rhino)
  6. 基于 Java 1.7,积极采用 1.7 新语法,如 autoClose、多项异常抛出
  7. 特别适合从前端过来的开发人员,提供服务端 JS 环境
  8. 完备的文档、代码注释,并提供 JUnit 单元测试
  9. 谨慎采用第三方库,当前免 JAR 依赖(除数据库驱动外)。提倡“够用就好、就地取材”,例如,日志采用 JDK 自带的 Logger、JSON 转换让 JDK 自带的 Rhino 转换、数据连接池采用 Tomcat 自带的 Pool、页面标签就用 TagFiles/SimpleTag 甚至就是连 <%=……Java Code %> 都可以、使用 JSON 或 Map 作为通用的、交换的数据结构。

控制层特性:

  1. 回归简单性,结合灵活的 MVC 思想,强调前端、后端相分离,前端 = JavaBean + JSP;后端 JavaBean + Servlet。
  2. 基于 JSONTree 无序树的无限极分类,结构清晰,可维护性强。
  3. 提倡面向接口编程,实现了一个小型的 IOC 依赖注射和 AOP。
  4. 支持 JSON API 输出纯数据,与安卓、iOS、AJAX 甚至广义的客户端等等的无缝对接。

表示层特性:

  1. JSP 实际很强大完全可以做到类似 PHP 的页面优先的理念(互联网项目 UI 开发占了大量时间)——因此我们的数据绑定方式是 JSP 引入 JavaBean,而非 Servlet 控制。
  2. 有自己的前端库 Bigfoot.js(HTML5/CSS3/JavaScript),基于 LESS.js 预编译 CSS 器和 Node.js 的构建系统。
  3. 基于 JSP Tag Files 的模板继承机制,可复用性强。
  4. 模板语言基于 EL 表达式 和 SimpleTag。
  5. 后端管理界面可选使用 Ext JS。

数据层特性:

  1. 没有使用 ORM,提倡使用带变量的 SQL,提供简单的 SQL 封装手段和 DAO。
  2. 采用 Map 为输入、输出载体,如表单转换为 Map 再生成 SQL 语句;JDBC 返回数据采用 Map 为记录载体。
  3. 与 JS 引擎 Rhino 无缝对接,用 JS 定义一些方法,脚本语言 JS 在处理 JSON、字符串和正则表达式有极大的便利性和优势。
  4. 抛弃 Java POJO,改用 JS 定义实体,目的是为适合前后台所使用
  5. 使用 Tomcat 自带的数据库连接池 JDBC Pool。

最后,欢迎各位使用 Bigfoot!

Bigfoot 源码在

第一版,已废弃:http://code.taobao.org/p/bigfoot/src/

第二版,已废弃:http://code.taobao.org/p/bigfoot_v2/src/,请用 SVN 检出:http://code.taobao.org/svn/bigfoot_v2/。

第三版,基于 Spring + Spring MVC + MyBatis:http://code.taobao.org/p/bigfoot_v2/src/java_v3/

那些年我看过的 Servlet + JSP 开源框架:

EWeb4J 1.9.1 新版本发布 基于Servlet/JDBC的轻量级web开发框架

PandaJS: Rhino + MongoDB + Server-side JQuery Template

HashMap关系数据映射技术 

Eternal 框架

Nutz

Jfinal

Smart Framework

Tiny Framework

Firefly Framework

Solo

转:VO 与 PO 辨析

下面内容转载自 http://www.blogjava.net/lzhidj/archive/2011/02/21/344754.html

数据传输是程序员实现各种功能时刻需要考虑的问题,从数据模型的建立,到数据模型的转换,从数据的合法性验证,到数据类型的转化,我们要时刻小心,精心设计与组织。数据模型与数据传输可简单可复杂,完全取决于设计者的经验与意图,当然,项目的规模也是我们应该考虑的因素,一个小型项目实在没必要将问题复杂化。我们首先考虑数据从视图(View)传输到数据库(DB)的数据模型变化过程。用户从界面输入数据,此时,数据毫无结构可言,是零散的、无组织的,数据提交到控制器后,一方面考虑到 OOP 的严谨性,另一方面考虑到数据的封装,会将零散的无组织的数据封装成 Value Object(简称VO)对象,VO 就是 JavaBean,并传送到业务类中,在数据模型比较复杂的情况下,业务类的方法参数和返回值都应该是 VO 或 VO 的集合,VO 转换成 PO(Persistence Object)后传送到DAO,DAO 调用 Hibernate API 持久化数据。简单来说,业务类对外暴露的数据模型是 VO,DAO 对外暴露的数据模型是 PO。

数据从数据库传递到视图层的数据模型变化恰恰相反,Hibernate将数据库中的记录转换成 PO,PO 传递给业务类后转换成 VO,VO 被传送到视图层进行显示处理。以上转换过程如下图:

为什么同时需要 PO 和 VO?前面说过,这不是必须的,如果项目比较小,直接使用 PO 就行了。但 PO 有如下缺点:PO 反应了数据库的物理模型,向外暴露 PO 存在一定的风险;

  • PO过于僵化,无法适应变化莫测的业务需求;
  • PO在持久化状态下与数据库同步,可能导致数据意外修改;
  • PO将导致程序缺乏健壮性。

而VO没有PO的缺点,相对而言,VO更加灵活,能适应各种需求的变化,下面是 PO 和 VO 的区别:

  • VO 是用 new 关键字创建,由 GC 回收的。PO 则是向数据库中添加新数据时创建,删除数据库中数据时削除的。并且它只能存活在一个数据库连接中,断开连接即被销毁;
  • VO 是值对象,精确点讲它是业务对象,是存活在业务层的,是业务逻辑使用的,它存活的目的就是为数据提供一个生存的地方。PO 则是有状态的,每个属性代表其当前的状态。它是物理数据的对象表示。使用它,可以使我们的程序与物理数据解耦,并且可以简化对象数据与物理数据之间的转换;
  • VO 的属性是根据当前业务的不同而不同的,也就是说,它的每一个属性都一一对应当前业务逻辑所需要的数据的名称。PO 的属性是跟数据库表的字段一一对应的;
  • PO 一般只有一个,但对应的 VO 可能有多个。

我们举一个简单的例子来说明 VO 与 PO 的区别:比如要实现用户注册与登陆的功能,在物理模型中创建一个用户表,字段分别为用户 ID(标识列)、用户名、密码、注册日期等等,定义 PO 时应该有这四个字段的映射属性。现在,我们来实现用户注册这一功能,为了接收用户输入的注册信息,必须定义 VO,注册用户需要输入的信息有:用户名、密码1、密码2,这正好是 VO 的属性。而实现用户登陆功能时,用户需要输入的信息只有用户名和密码,所以,该 VO 的属性只有两个:用户名、密码。可以看出,PO 侧重于物理模型,而 VO 则更关注用户的实际需求。如下图所示:

相关实践学习
自建数据库迁移到云数据库
本场景将引导您将网站的自建数据库平滑迁移至云数据库RDS。通过使用RDS,您可以获得稳定、可靠和安全的企业级数据库服务,可以更加专注于发展核心业务,无需过多担心数据库的管理和维护。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
目录
相关文章
|
3月前
|
自然语言处理 前端开发 Java
JBoltAI 框架完整实操案例 在 Java 生态中快速构建大模型应用全流程实战指南
本案例基于JBoltAI框架,展示如何快速构建Java生态中的大模型应用——智能客服系统。系统面向电商平台,具备自动回答常见问题、意图识别、多轮对话理解及复杂问题转接人工等功能。采用Spring Boot+JBoltAI架构,集成向量数据库与大模型(如文心一言或通义千问)。内容涵盖需求分析、环境搭建、代码实现(知识库管理、核心服务、REST API)、前端界面开发及部署测试全流程,助你高效掌握大模型应用开发。
373 5
|
3月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:路由、中间件、参数校验
Gin框架以其极简风格、强大路由管理、灵活中间件机制及参数绑定校验系统著称。本文详解其核心功能:1) 路由管理,支持分组与路径参数;2) 中间件机制,实现全局与局部控制;3) 参数绑定,涵盖多种来源;4) 结构体绑定与字段校验,确保数据合法性;5) 自定义校验器扩展功能;6) 统一错误处理提升用户体验。Gin以清晰模块化、流程可控及自动化校验等优势,成为开发者的优选工具。
|
5月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
376 70
|
3月前
|
Java 测试技术 API
现代化 java 分层开发实施策略与最佳实践指南
现代化Java分层开发采用清晰的多层架构,包括Controller、Service、Repository和DTO等核心层次。文章详细介绍了标准Maven/Gradle项目结构,各层职责与实现规范:实体层使用JPA注解,DTO层隔离数据传输,Repository继承JpaRepository,Service层处理业务逻辑,Controller层处理HTTP请求。推荐使用Spring Boot、Lombok、MapStruct等技术栈,并强调了单元测试和集成测试的重要性。这种分层设计提高了代码的可维护性、可测试
122 0
|
3月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:使用 Gin 快速构建 Web 服务
Gin 是一个高效、轻量级的 Go 语言 Web 框架,支持中间件机制,非常适合开发 RESTful API。本文从安装到进阶技巧全面解析 Gin 的使用:快速入门示例(Hello Gin)、定义 RESTful 用户服务(增删改查接口实现),以及推荐实践如参数校验、中间件和路由分组等。通过对比标准库 `net/http`,Gin 提供更简洁灵活的开发体验。此外,还推荐了 GORM、Viper、Zap 等配合使用的工具库,助力高效开发。
|
3月前
|
存储 安全 Java
现代应用场景中 Java 集合框架的核心技术与实践要点
本内容聚焦Java 17及最新技术趋势,通过实例解析Java集合框架的高级用法与性能优化。涵盖Record类简化数据模型、集合工厂方法创建不可变集合、HashMap初始容量调优、ConcurrentHashMap高效并发处理、Stream API复杂数据操作与并行流、TreeMap自定义排序等核心知识点。同时引入JMH微基准测试与VisualVM工具分析性能,总结现代集合框架最佳实践,如泛型使用、合适集合类型选择及线程安全策略。结合实际案例,助你深入掌握Java集合框架的高效应用与优化技巧。
127 4
|
5月前
|
人工智能 自然语言处理 JavaScript
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
Magnitude是一个基于视觉AI代理的开源端到端测试框架,通过自然语言构建测试用例,结合推理代理和视觉代理实现智能化的Web应用测试,支持本地运行和CI/CD集成。
712 15
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
|
6月前
|
机器学习/深度学习 人工智能 Java
Java机器学习实战:基于DJL框架的手写数字识别全解析
在人工智能蓬勃发展的今天,Python凭借丰富的生态库(如TensorFlow、PyTorch)成为AI开发的首选语言。但Java作为企业级应用的基石,其在生产环境部署、性能优化和工程化方面的优势不容忽视。DJL(Deep Java Library)的出现完美填补了Java在深度学习领域的空白,它提供了一套统一的API,允许开发者无缝对接主流深度学习框架,将AI模型高效部署到Java生态中。本文将通过手写数字识别的完整流程,深入解析DJL框架的核心机制与应用实践。
355 3
|
5月前
|
存储 安全 Java
Java 集合框架详解:系统化分析与高级应用
本文深入解析Java集合框架,涵盖List、Set、Map等核心接口及其常见实现类,如ArrayList、HashSet、HashMap等。通过对比不同集合类型的特性与应用场景,帮助开发者选择最优方案。同时介绍Iterator迭代机制、Collections工具类及Stream API等高级功能,提升代码效率与可维护性。适合初学者与进阶开发者系统学习与实践。
171 0
|
6月前
|
存储 并行计算 Java
java 中的fork join框架
Java中的Fork Join框架于Java 7引入,旨在提升并行计算能力。它通过“分而治之”的思想,将大任务拆分为多个小任务(fork),再将结果合并(join)。核心组件包括:ForkJoinPool(管理线程池和工作窃取机制)、ForkJoinWorkerThread(执行具体任务的工作线程)和ForkJoinTask(定义任务逻辑,常用子类为RecursiveAction和RecursiveTask)。框架支持通过invoke、fork/join等方式提交任务,广泛应用于高性能并发场景。

热门文章

最新文章