一、前端视角理解 Java Framework 核心
作为前端开发者,可先类比前端框架(如 Vue/React)的核心设计思路:
- 前端框架:封装 DOM 操作、提供组件化 / 响应式、统一生命周期 → 简化页面开发
- Java 后端框架:封装 HTTP 处理、路由映射、依赖管理、生命周期 → 简化接口开发
本文将实现一个极简版 Java Web 框架(命名为MiniJavaWeb),核心覆盖:
- 路由映射(前端
router对应后端接口路由) - 请求 / 响应封装(前端
Request/Response对应后端HttpServletRequest/Response) - 控制器管理(前端
组件对应后端Controller) - 核心流程驱动(类比前端框架的初始化 / 渲染流程)
二、技术准备
- JDK 8+
- 基础 Servlet(Java Web 核心,类比前端
XMLHttpRequest/Fetch) - 反射(实现框架的动态化,类比前端
Vue的模板编译) - Maven(依赖管理,类比前端
npm)
三、MiniJavaWeb 框架实现(核心代码)
1. 框架核心结构
plaintext
minijavaweb/
├── src/main/java/com/miniframework/
│ ├── annotation/ // 自定义注解(类比前端装饰器)
│ │ ├── Controller.java // 标记控制器
│ │ └── RequestMapping.java // 标记路由
│ ├── core/ // 框架核心逻辑
│ │ ├── DispatcherServlet.java // 核心调度器(类比Vue的$mount)
│ │ └── HandlerMapping.java // 路由映射器
│ └── demo/ // 业务示例(类比前端业务组件)
│ └── UserController.java
└── web.xml // Servlet配置(类比前端入口配置)
2. 自定义注解(类比前端@Component)
java
运行
// Controller.java:标记控制器类
package com.miniframework.annotation;
import java.lang.annotation.*;
@Target(ElementType.TYPE) // 作用于类
@Retention(RetentionPolicy.RUNTIME) // 运行时保留
public @interface Controller {
}
// RequestMapping.java:标记路由
package com.miniframework.annotation;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD}) // 作用于类/方法
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
String value() default ""; // 路由路径
}
3. 路由映射器(HandlerMapping)
负责扫描所有控制器,建立「URL 路径 → 控制器方法」的映射关系(类比前端router.getRoutes()):
java
运行
package com.miniframework.core;
import com.miniframework.annotation.Controller;
import com.miniframework.annotation.RequestMapping;
import javax.servlet.ServletContext;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class HandlerMapping {
// 核心映射表:URL路径 → 控制器方法
private Map<String, Method> handlerMap = new HashMap<>();
// 控制器实例缓存
private Map<String, Object> controllerMap = new HashMap<>();
// 初始化:扫描指定包下的所有控制器
public void init(ServletContext servletContext) {
String basePackage = "com.miniframework.demo"; // 业务代码包
String packagePath = basePackage.replace(".", "/");
URL resource = this.getClass().getClassLoader().getResource(packagePath);
if (resource == null) return;
File packageDir = new File(resource.getFile());
for (File file : packageDir.listFiles()) {
if (file.isFile() && file.getName().endsWith(".class")) {
String className = basePackage + "." + file.getName().replace(".class", "");
try {
Class<?> clazz = Class.forName(className);
// 扫描@Controller注解的类
if (clazz.isAnnotationPresent(Controller.class)) {
String classPath = "";
// 获取类级别的@RequestMapping
if (clazz.isAnnotationPresent(RequestMapping.class)) {
classPath = clazz.getAnnotation(RequestMapping.class).value();
}
// 扫描方法级别的@RequestMapping
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(RequestMapping.class)) {
String methodPath = method.getAnnotation(RequestMapping.class).value();
String fullPath = classPath + methodPath;
// 建立URL→方法的映射
handlerMap.put(fullPath, method);
// 缓存控制器实例
controllerMap.put(fullPath, clazz.newInstance());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
// 根据URL获取对应的控制器方法
public Method getHandler(String url) {
return handlerMap.get(url);
}
// 根据URL获取控制器实例
public Object getController(String url) {
return controllerMap.get(url);
}
}
4. 核心调度器(DispatcherServlet)
框架的「大脑」,类比前端ReactDOM.render/Vue.createApp,负责:
- 初始化框架(扫描控制器、建立路由)
- 接收 HTTP 请求 → 匹配路由 → 执行控制器方法 → 返回响应
java
运行
package com.miniframework.core;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public class DispatcherServlet extends HttpServlet {
private HandlerMapping handlerMapping;
// 框架初始化(类比前端框架的created钩子)
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
// 初始化路由映射
handlerMapping = new HandlerMapping();
handlerMapping.init(getServletContext());
System.out.println("MiniJavaWeb框架初始化完成!");
}
// 处理所有HTTP请求(类比前端的请求拦截器)
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取请求路径(类比前端router.resolve)
String requestURI = req.getRequestURI();
String contextPath = req.getContextPath();
String url = requestURI.replace(contextPath, "");
// 2. 匹配路由(获取对应的控制器方法)
Method handlerMethod = handlerMapping.getHandler(url);
if (handlerMethod == null) {
resp.getWriter().write("404 Not Found");
return;
}
// 3. 执行控制器方法(反射调用)
try {
Object controller = handlerMapping.getController(url);
// 执行方法(简化版:无参数、返回字符串)
String result = (String) handlerMethod.invoke(controller);
// 4. 返回响应(类比前端res.send)
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write(result);
} catch (Exception e) {
resp.getWriter().write("500 Server Error: " + e.getMessage());
e.printStackTrace();
}
}
}
5. 配置 web.xml(框架入口)
类比前端index.html引入框架脚本,配置 Servlet 容器(Tomcat)加载框架核心:
xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 配置核心调度器Servlet -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>com.miniframework.core.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup> <!-- 容器启动时立即加载 -->
</servlet>
<!-- 拦截所有请求 -->
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
四、业务示例(使用框架)
类比前端编写业务组件,编写控制器:
java
运行
package com.miniframework.demo;
import com.miniframework.annotation.Controller;
import com.miniframework.annotation.RequestMapping;
// 标记为控制器
@Controller
@RequestMapping("/user") // 类级别路由
public class UserController {
// 方法级别路由
@RequestMapping("/list")
public String getUserList() {
// 模拟业务逻辑(类比前端组件的methods)
return "用户列表:<br>1. 张三<br>2. 李四";
}
@RequestMapping("/detail")
public String getUserDetail() {
return "用户详情:<br>姓名:张三<br>年龄:25";
}
}
五、框架工作流程(前端视角解读)
1. 初始化阶段(类比 Vue 初始化)
plaintext
Tomcat启动 → 加载web.xml → 初始化DispatcherServlet → 调用HandlerMapping.init() → 扫描指定包下的类 →
识别@Controller注解的类 → 解析类/方法上的@RequestMapping → 建立「URL→控制器方法」的映射表 → 框架就绪
👉 类比前端:Vue.createApp() → 解析路由配置 → 注册组件 → 框架就绪
2. 请求处理阶段(类比前端路由匹配)
plaintext
用户发起请求(如http://localhost:8080/user/list) → Tomcat将请求转发给DispatcherServlet →
1. 解析请求URL(/user/list) → 2. 从映射表中匹配对应的控制器方法(UserController.getUserList()) →
3. 通过反射调用该方法 → 4. 获取方法返回值 → 5. 将返回值写入HttpServletResponse → 返回给浏览器
👉 类比前端:用户点击链接 → 前端路由匹配对应组件 → 执行组件生命周期 → 渲染DOM → 展示页面
六、框架核心设计思想(前端对比)
| Java 框架特性 | 前端框架对应特性 | 核心目的 |
|---|---|---|
| 注解(@Controller) | 装饰器(@Component)/ 注解 | 标记特殊类 / 方法,简化配置 |
| 反射 | 模板编译 / 动态组件 | 实现动态化,减少硬编码 |
| DispatcherServlet | 前端路由核心(vue-router) | 统一请求 / 路由入口,解耦逻辑 |
| HandlerMapping | 路由映射表(router.getRoutes ()) | 建立路径与处理逻辑的关联 |
| 控制器(Controller) | 业务组件(Vue 组件 / React 组件) | 封装业务逻辑 |
七、扩展方向(类比前端框架进阶)
- 参数解析 :扩展框架支持获取请求参数(类比前端
$route.query/$route.params) - 响应式返回 JSON :支持返回 JSON 数据(类比前端
res.json()) - 拦截器 :添加请求 / 响应拦截器(类比前端
axios.interceptors) - 依赖注入 :实现简单的 IOC 容器(类比前端
provide/inject)
八、运行验证
- 将项目打包为 WAR 包,部署到 Tomcat
- 启动 Tomcat,访问
http://localhost:8080/user/list,即可看到用户列表响应 - 访问
http://localhost:8080/user/detail,即可看到用户详情响应
总结
从前端视角学习 Java 框架,核心是类比熟悉的前端框架逻辑:
- Java 框架的核心是「封装 HTTP 处理流程,通过注解 / 反射实现配置化、动态化」
- 其工作流程可拆解为「初始化(建立映射)→ 请求处理(匹配映射→执行逻辑→返回响应)」
- 本 Demo 仅实现核心骨架,真实的 Spring MVC 在此基础上扩展了参数解析、视图解析、异常处理、IOC/DI 等能力,但核心流程一致。