当前位置: 首页 > news >正文

手写模拟SpringMvc源码

MVC框架

MVC是一种设计模式(设计模式就是日常开发中编写代码的一种好的方法和经验的总结)。模型(model)-视图(view)-控制器(controller),三层架构的设计模式。用于实现前端页面的展现与后端业务数据处理的分离。

Spring MVC的主要组件

前端控制器 DispatcherServlet
Spring的MVC框架是围绕DispatcherServlet来设计的,它用来处理所有的HTTP请求和响应。此模块不需要程序员开发。
作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。
处理器映射器HandlerMapping
此功能不需要程序员开发。
作用:根据请求的URL来查找Handler
处理器适配器HandlerAdapter
作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view)
视图View
需要程序员开发jsp。View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)
用户发送请求至前端控制器DispatcherServlet;
DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
DispatcherServlet 调用 HandlerAdapter处理器适配器;
HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
Handler执行完成返回ModelAndView;
HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
ViewResolver解析后返回具体View;
DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
DispatcherServlet响应用户。

手写模拟SpringMvc源码

spring mvc调用到Controller执行的原理

通过加载配置文件web.xml进而加载spring-mvc.xml。
根据配置文件给定的目录来扫描整个项目。
扫描所有加了@Controller注解的类。
当扫描到加了@Controller注解的类之后遍历里面所有的方法。
拿到方法对象之后 解析方法上面是否加了@RequestMapping注解。
定义一个Map集合把@RequstMapping的value 与方法对象绑定起来,即Map<String,Method>。
定义一个Map把声名该方法的类的对象绑定起来,即Map<String,Object>。
拦截到请求之后拿到请求的URI。
处理请求,例如执行指定方法,返回字符串或跳转到相应视图。

目录

导入依赖

 <dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version></dependency><!--       解析xml文件--><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.9</version></dependency>

代码

DispatcherServlet类

public class DispatcherServlet extends HttpServlet {private ApplicationContext applicationContext;private List<MyHandle> myHandleList=new ArrayList<>();@Overridepublic void init() throws ServletException {String contextConfigLocation = this.getServletConfig().getInitParameter("contextConfigLocation");System.out.println(contextConfigLocation);applicationContext = new ApplicationContext(contextConfigLocation);applicationContext.refresh();initHandleMappinng(applicationContext);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {excuteDispatch(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}public void initHandleMappinng(ApplicationContext applicationContext){if(applicationContext.beanDefinitionConcurrentHashMap.size()==0){throw new RuntimeException("Spring容器为空");}for (Map.Entry<String, BeanDefinition> stringBeanDefinitionEntry : applicationContext.beanDefinitionConcurrentHashMap.entrySet()) {Class clazz = stringBeanDefinitionEntry.getValue().getClazz();for (Method declaredMethod : clazz.getDeclaredMethods()) {boolean annotationPresent = declaredMethod.isAnnotationPresent(RequestMapping.class);if(annotationPresent==true){String value = declaredMethod.getAnnotation(RequestMapping.class).value();MyHandle myHandle=new MyHandle(value,declaredMethod,clazz);myHandleList.add(myHandle);}}}}public void excuteDispatch(HttpServletRequest request,HttpServletResponse response){MyHandle handle = getHandle(request);if(handle==null){try {response.getWriter().print("404");} catch (IOException e) {e.printStackTrace();}}else {Method method = handle.getMethod();Class<?>[] parameterTypes = method.getParameterTypes();Object[] params=new Object[parameterTypes.length];Map<String, String[]> parameterMap = request.getParameterMap();for (Map.Entry<String, String[]> stringEntry : parameterMap.entrySet()) {String key = stringEntry.getKey();String value = stringEntry.getValue()[0];int i = GetRequestParams(method, key);if(i>=0)params[i]=value;else {//反射获取的是arg0,官方这里用的不是反射机制}}try {Object invoke = method.invoke(handle.getClazz().newInstance(), params);PrintWriter writer = response.getWriter();writer.print(invoke);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}public MyHandle getHandle(HttpServletRequest request){String requestURI = request.getRequestURI();for (MyHandle myHandle : myHandleList) {if(myHandle.getUrl().equals(requestURI))return myHandle;}return null;}public int GetRequestParams(Method method,String name){Parameter[] parameters = method.getParameters();for (int i=0;i<parameters.length;i++) {boolean annotationPresent = parameters[i].isAnnotationPresent(RequestParam.class);if(annotationPresent){String value = parameters[i].getAnnotation(RequestParam.class).value();if(value.equals(name))return i;}}return -1;}}

XmlPaser类

public class XmlPaser {public static String getbasePackage(String xml){SAXReader saxReader=new SAXReader();InputStream inputStream = XmlPaser.class.getClassLoader().getResourceAsStream(xml);try {Document document = saxReader.read(inputStream);Element rootElement = document.getRootElement();Element componentScan = rootElement.element("component-scan");Attribute attribute = componentScan.attribute("base-package");String text = attribute.getText();return text;} catch (DocumentException e) {e.printStackTrace();}return "";}
}

web.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"><display-name>Application</display-name><servlet><servlet-name>DispatcherServlet</servlet-name><servlet-class>com.example.demo.springmvc.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>DispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
</web-app>

代码下载地址:https://download.csdn.net/download/qq_43649937/87558006

相关文章:

手写模拟SpringMvc源码

MVC框架MVC是一种设计模式&#xff08;设计模式就是日常开发中编写代码的一种好的方法和经验的总结&#xff09;。模型&#xff08;model&#xff09;-视图&#xff08;view&#xff09;-控制器&#xff08;controller&#xff09;&#xff0c;三层架构的设计模式。用于实现前端…...

五分钟了解JumpServer V2.* 与 v3 的区别

一、升级注意项 1、梳理数据。JumpServer V3 去除了系统用户功能&#xff0c;将资产与资产直接绑定。当一个资产名下有多个同名账号&#xff0c;例如两个root用户时&#xff0c;升级后会自动合并最后一个root&#xff0c;不会同步其他root用户。升级前需保证每一个资产只拥有一…...

用友开发者中心应用构建实践指引!

基于 iuap 技术底座&#xff0c;用友开发者中心致力于为企业和开发者提供一站式技术服务&#xff0c;让人人都能轻松构建企业级应用。 本文以人力资源领域常用的应聘人员信息登记与分析功能为例&#xff0c;详细介绍如何在用友开发者中心使用 YonBuilder 进行应用构建。 功能…...

snap使用interface:content的基础例子

snap做包还在学习阶段&#xff0c;官网文档可查看&#xff1a;The content interface | Snapcraft documentation该例子由publiser和consumer两部分组成&#xff0c;一个提供一个只读的数据区&#xff0c;一个来进行读取其中的信息&#xff0c;这样就完成了content的交互。publ…...

蓝桥杯刷题第七天

第一题&#xff1a;三角回文数问题描述对于正整数 n, 如果存在正整数 k 使得2n123⋯k2k(k1), 则 n 称为三角数。例如, 66066 是一个三角数, 因为 66066123⋯363。如果一个整数从左到右读出所有数位上的数字, 与从右到左读出所有数位 上的数字是一样的, 则称这个数为回文数。例如…...

FinOps首次超越安全成为企业头等大事|云计算趋势报告

随着云计算在过去十年中的广泛应用&#xff0c;云计算用户所面临的一个持续不变的趋势是&#xff1a;安全一直是用户面临的首要挑战。然而&#xff0c;这种情况正在发生转变。 知名IT软件企业 Flexera 对云计算决策者进行年度调研已经持续12年&#xff0c;而今年安全问题首次…...

【深度强化学习】(3) Policy Gradients 模型解析,附Pytorch完整代码

大家好&#xff0c;今天和各位分享一下基于策略的深度强化学习方法&#xff0c;策略梯度法是对策略进行建模&#xff0c;然后通过梯度上升更新策略网络的参数。我们使用了 OpenAI 的 gym 库&#xff0c;基于策略梯度法完成了一个小游戏。完整代码可以从我的 GitHub 中获得&…...

Windows基于Nginx搭建RTMP流媒体服务器(附带所有组件下载地址及验证方法)

RTMP服务时常用于直播时提供拉流推流传输数据的一种服务。前段时间由于朋友想搭建一套直播时提供稳定数据传输的服务器&#xff0c;所以就研究了一下如何搭建及使用。 1、下载nginx 首先我们要知道一般nginx不能直接配置rtmp服务&#xff0c;在Windows系统上需要特殊nginx版本…...

交流电机驱动器中的隔离电压感应

汽车和工业终端设备&#xff0c;如电机驱动器、串式逆变器和机载充电器&#xff0c;在高电压下运行&#xff0c;不能安全地与人直接互动。隔离电压测量通过保护人类免受高压电路执行一个功能的影响&#xff0c;有助于优化操作和确保使用的安全性。 设计用于高性能&#xff0c;隔…...

爬取知乎问题答案

参考博客&#xff1a;基于Python知乎回答爬虫 jieba关键字统计可视化_知乎爬虫搜索关键词_菠萝柚王子的博客-CSDN博客 1、安装依赖包 import numpy import requests import certifi from PIL import Image from lxml import etree import jieba from wordcloud import WordClo…...

通用智能理论

将智能定义为解决矛盾的能力&#xff0c;用解决矛盾的概率提升来评估智能程度&#xff0c;以此为基础推导智能原理&#xff0c;建立一种新的通用智能理论。 1 前言 通用人工智能&#xff08;Artificial General Intelligence&#xff09;是人类长久以来的梦想。经历了一次次挫败…...

保姆级使用PyTorch训练与评估自己的MixMIM网络教程

文章目录前言0. 环境搭建&快速开始1. 数据集制作1.1 标签文件制作1.2 数据集划分1.3 数据集信息文件制作2. 修改参数文件3. 训练4. 评估5. 其他教程前言 项目地址&#xff1a;https://github.com/Fafa-DL/Awesome-Backbones 操作教程&#xff1a;https://www.bilibili.co…...

《百万在线 大型游戏服务端开发》前两章概念笔记

第1章 从角色走路说起 游戏网络通信的流程则是服务端先开启监听&#xff0c;等待客户端的连接&#xff0c;然后交互操作&#xff0c;最后断开。 套接字 每个Socket都包含网络连接中一端的信息。每个客户端需要一个Socket结构&#xff0c;服务端则需要N1个Socket结构&#xff…...

3BHE029110R0111 ABB

3BHE029110R0111 ABB变频器控制方式低压通用变频输出电压为380&#xff5e;650V&#xff0c;输出功率为0.75&#xff5e;400kW&#xff0c;工作频率为0&#xff5e;400Hz&#xff0c;它的主电路都采用交—直—交电路。其控制方式经历了以下四代。1U/fC的正弦脉宽调制&#xff0…...

实现防重复操作(JS与CSS)

实现防重复操作&#xff08;JS与CSS&#xff09; 一、前言 日常开发中我们经常会对按钮进行一个防重复点击的校验&#xff0c;这个通常使用节流函数来实现。在规定时间内只允许提交一次&#xff0c;可以有效的避免事件过于频繁的执行和重复提交操作&#xff0c;以及为服务器考…...

怎么合并或注销重复LinkedIn领英帐号?

您可能会发现您拥有多个领英帐户。如果您收到消息&#xff0c;提示您尝试使用的邮箱与另一个帐户已绑定&#xff0c;就表明您可能存在重复的领英帐户。如果您使用许多不同的邮箱地址&#xff0c;也可能会收到这样的提示。 领英精灵温馨提示: 目前&#xff0c;仅支持在 PC 端合并…...

Redis高频面试题汇总(中)

目录 1.什么是redis事务&#xff1f; 2.如何使用 Redis 事务&#xff1f; 3.Redis 事务为什么不支持原子性 4.Redis 事务支持持久性吗 5.Redis事务基于lua脚本的实现 6.Redis集群的主从复制模型是怎样的&#xff1f; 7.Redis集群中&#xff0c;主从复制的数据同步的步骤 …...

【Flutter从入门到入坑之三】Flutter 是如何工作的

【Flutter从入门到入坑之一】Flutter 介绍及安装使用 【Flutter从入门到入坑之二】Dart语言基础概述 【Flutter从入门到入坑之三】Flutter 是如何工作的 本文章主要以界面渲染过程为例&#xff0c;介绍一下 Flutter 是如何工作的。 页面中的各界面元素&#xff08;Widget&…...

Web Components学习(2)-语法

一、Web Components 对 Vue 的影响 尤雨溪在创建 Vue 的时候大量参考了 Web Components 的语法&#xff0c;下面写个简单示例。 首先写个 Vue 组件 my-span.vue&#xff1a; <!-- my-span.vue --> <template><span>my-span</span> </template>…...

Lesson 9.2 随机森林回归器的参数

文章目录一、弱分类器的结构1. 分枝标准与特征重要性2. 调节树结构来控制过拟合二、弱分类器的数量三、弱分类器训练的数据1. 样本的随机抽样2. 特征的随机抽样3. 随机抽样的模式四、弱分类器的其他参数在开始学习之前&#xff0c;先导入我们需要的库。 import numpy as np im…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...