Web框架实战

架构探险——从零开始写Java Web框架

需求来源

web框架全盘掌控

实践代码地址:

业务模块

解决问题

控制层、业务层、持久层分层,利于模块解耦和复用。

使用方法

引入DHMap的jar包,控制层继承BasicController,业务层继承BasicServiceImpl,且都通过注解声明为spring组件,视图Bean继承VO,持久Bean继承PO,持久Bean上通过@Table对应数据库表名,域上@Column对应字段,@ID对应id,还可用@OneToOne,@OneToMany等实现表关联关系。

实现原理:
  • 泛型控制层类,实现符合REST的CRUD方法,用于被继承使用
  • 泛型业务层类,实现了CRUD方法,将VO转化为PO ,用于被继承使用
  • 提供SQL的CRUD模板,只需拼入表的名、字段、值等信息
  • 泛型持久层类,实现了CRUD方法,分析PO的注解,提取表信息
  • 将表信息拼入SQL模板,形成SQL语句,调用mybatis实现结果返回
  • 对返回结果解析,并反射实例化PO以及PO的域赋值
代码分析:
  • 定义一系列注解
    对带Blob,Clob注解等域需cast (XXX as CHAR) as XXX取出,Ignore表示该域不对应库字段
  • BasicController.java为控制层基类
    提供了CRUD以及分页查询等方法,返回结果格式统一为Result
  • BasicServiceImpl.java为业务层基类
    • 接口方法实现于BasicService,提供了基本和批量的CRUD方法
    • 初始化方法内通过反射获取类的泛型类型
    • 单例化BasicMapperImpl时传过去
    • 接受来自Controller的VO,反射创建PO并赋值,调用BasicMapperImpl方法
  • BasicMapperImpl.java为持久层封装类
    • 接口方法实现于BasicMapper,提供了基本和批量的CRUD方法,其中selectList用于字段匹配查询,接受Condition参数,可定义分页参数和基于WhereOperator比较符的where子句拼接
    • 根据PO信息分析,转为对应sql语句
    • 调用到SQL模板拼接中
    • 调用mybatis实现结果返回
    • 根据PO信息分析,反射到PO中,返回
  • SqlMapper.java为SQL模板
    之前使用BasicMapper.xml实现模板,但后续mybatis更新版本,可以通过@Insert等注解在接口使用
  • Entity.java为PO信息分析类
    • 获取PO所有域,分析@Table@@Column@ID等注解,对域重封装
    • 记录域名和域对应库字段名
    • 根据是否有@OneToOne,@OneToMany等注解的域,延伸到下一个PO,递归记录关联关系
    • 记录每个PO的父PO,并取别名备用
  • SqlUtil.java将PO信息转化为sql语句和将jdbc返回结果转为PO
    其中getJoinPart方法将表关系转为ONE_A a left join ONE_B b on a.id=b.a_id等
    handleResult方法将map转为list

IOC

概念

依赖注入,也叫控制反转,通过屏蔽接口的实现方法,实现对象的不同行为。

解决问题

项目越大,对象的实例化和相互引用关系关联等动作占据时间增多,spring框架的自动装配简化了该步骤。

使用方法

类上注解@Componet声明为组件,类域上注解@Autowired或@Resource声明为需注入的域。

实现原理
  • 新建类加载器,扫描指定包下所有类
  • 所有类中分析出组件类(带有或注解于@Componet的注解,如@Controller)
  • 反射实例化组件类
  • 找出组件类中需注入的域(带有注解@Autowired或@Resource)
  • 对需注入的域,进行反射赋值
代码分析
  • 定义组件注解
    Component注解关系图为,@Controller,@Service,@Repository注解上注着@Componet,而@RestController上注着@Controller
  • ClassUtil.java实现获取包名下所有类
    • 根据当前线程的类加载器,取到编译后文件根路径,如D:\DSS\DHMap\Trunk\target\classes
    • 将制定包名转为文件路径,结合根路径,如com.dahua,结合为D:\DSS\DHMap\Trunk\target\classes\com\dahua
    • 递归记录文件下后缀为.class的文件
    • 若发现jar包则遍历jar内部文件,记录后缀为.class的文件
    • 将.class文件路径转为类全限定名,如D:\DSS\DHMap\Trunk\target\classes\com\dahua\frame\ioc\annotatio\Component.class,转为com.dahua.frame.ioc.annotatio.Component
    • 调用Class.forName载入字节,加载并记录该类
  • ClassHelper.java实现获取组件类
    • 递归获取@Componet的子注解
    • 遍历所有类,判断是否带有@Componet或其子注解
  • BeanHelper.java实现组件实例化、
    遍历组件类
    调用class的newInstance方法,调用类的无参构造区 //todo 可先判断有哪些构造器,再调用
  • IOCHelper.java实现域相互注入
    遍历组件类的域组,判断是否带有@Autowired或@Resource注解,通过类获取工厂中实例,调用field的set赋值
  • ApplicationHelper.java实现以上诸类的静态代码块加载

MVC

概念

Model(模型)、View(视图)、Controller(控制器)分离。

解决问题

对Servlet解耦,解析URL分发到对应控制层。

使用方法

web.xml添加DispatcherServlet,URL匹配为/。

实现原理
  • 获取带有@Controller或@RestController的类
  • 解析并缓存类的每个方法对应的URL和Method
  • servlet解析URL,并封装参数
  • servlet分发到对应方法
  • servlet对方法返回值进行分析,判断是页面跳转还是数据返回

AOP

概念
解决问题
使用方法
实现原理

Transaction

概念

事物的ACID,分别为原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

解决问题
使用方法
实现原理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值