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

简化版SpringMVC

简化版SpringMVC

web.xml

xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <display-name>Web Application</display-name>

    <servlet>

       <servlet-name>mvc</servlet-name>

       <servlet-class>com.aop.mvc.action.DispatcherServlet</servlet-class>

       <init-param>

           <param-name>contextConfigLocation</param-name>

           <param-value>application.properties</param-value>

       </init-param>

       <load-on-startup>1</load-on-startup>

    </servlet>

    <servlet-mapping>

       <servlet-name>mvc</servlet-name>

       <url-pattern>/*</url-pattern>

    </servlet-mapping>

</web-app>

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.aop.demo</groupId>

    <artifactId>SpringAop-Demo</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <packaging>jar</packaging>

    <name>SpringAop-Demo</name>

    <url>http://maven.apache.org</url>

    <properties>

       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    </properties>

    <dependencies>

       <dependency>

           <groupId>junit</groupId>

           <artifactId>junit</artifactId>

           <version>3.8.1</version>

           <scope>test</scope>

       </dependency>

       <dependency>

           <groupId>javax.servlet</groupId>

           <artifactId>servlet-api</artifactId>

           <version>2.4</version>

           <scope>provided</scope>

       </dependency>

    </dependencies>

    <build>

       <finalName>${artifactId}</finalName>

       <resources>

           <resource>

              <directory>${basedir}/src/main/resources</directory>

              <includes>

                  <include>**/*</include>

              </includes>

           </resource>

           <resource>

              <directory>${basedir}/src/main/java</directory>

              <excludes>

                  <exclude>**/*.java</exclude>

                  <exclude>**/*.class</exclude>

              </excludes>

           </resource>

       </resources>

    </build>

</project>

application.properties

scanPackage=com.aop.mvc

com.aop.mvc.annotaion

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target({ ElementType.FIELD })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface AutoWirted {

String value() default "";

}

@Target({ ElementType.TYPE })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Controller {

String value() default "";

}

@Target({ ElementType.TYPE, ElementType.METHOD })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface RequestMapping {

String value() default "";

}

@Target({ ElementType.PARAMETER })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface RequestParam {

String value() default "";

}

@Target({ ElementType.TYPE })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Service {

String value() default "";

}

DemoService.java

package com.aop.mvc.servlet.impl;

import com.aop.mvc.annotaion.Service;

import com.aop.mvc.servlet.IDemoService;

@Service

public class DemoService implements IDemoService {

    public String get(String name) {

       return "My name is " + name;

    }

}

package com.aop.mvc.servlet;

public interface IDemoService {

String get(String name);

}

DispatcherServlet.java

package com.aop.mvc.action;

import java.io.File;

import java.io.IOException;

import java.io.InputStream;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.net.URL;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.Map.Entry;

import java.util.Properties;

import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.aop.mvc.annotaion.AutoWirted;

import com.aop.mvc.annotaion.Controller;

import com.aop.mvc.annotaion.RequestMapping;

import com.aop.mvc.annotaion.Service;

public class DispatcherServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    /** 资源文件 */

    private Properties contextConfig = new Properties();

    /** 扫描到的所有类 */

    private List<String> classNames = new ArrayList<String>();

    /** 实例化类集合 */

    private Map<String, Object> ioc = new HashMap<String, Object>();

    /** url ==> 优化:List handlerMapping */

    private Map<String, Method> handlerMapping = new HashMap<String, Method>();

    @Override

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

       this.doPost(req, resp);

    }

    @Override

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

       try {

           // 6.等待请求

           doDispatch(req, resp);

       } catch (Exception e) {

           e.printStackTrace();

       }

    }

    private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {

       String url = req.getRequestURI();

       String contextPath = req.getContextPath();

       url = url.replace(contextPath, "").replaceAll("/+", "/");

       // 判读HandlerMapping中有返回调用, 没有就404

       if (!handlerMapping.containsKey(url)) {

           resp.getWriter().write("404 Not Found!");

           return;

       }

       Method me = handlerMapping.get(url);

       // me.invoke(req.getParameterMap(), ???);

       System.out.println(me);

    }

    @Override

    public void init(ServletConfig config) throws ServletException {

    System.out.println("======================Begin========================");

       // 1.加载配置文件

       doLoadConfig(config.getInitParameter("contextConfigLocation"));

       // 2.扫描到所有的相关类

       doScanner(contextConfig.getProperty("scanPackage"));

       // 3.初始化刚刚扫描到的类

       doInstance();

       // 4.实现依赖注入

       doAutowired();

       // 5.初始化HadlerMapping

       initHandlerMapping();

       System.out.println("=============== Spring is init OK!");

    }

    private void initHandlerMapping() {

       if (ioc.isEmpty())

           return;

       // 对Controller进行处理

       for (Entry<String, Object> entry : ioc.entrySet()) {

           Class clazz = entry.getValue().getClass();

           // 判断有没有加@Controller注解的

           if (!clazz.isAnnotationPresent(Controller.class))

              continue;

           String baseUtl = "";

           if (clazz.isAnnotationPresent(RequestMapping.class)) {

              RequestMapping requestParam = clazz.getAnnotation(RequestMapping.class);

              baseUtl = requestParam.value();

           }

           Method[] method = clazz.getMethods();

           for (Method meth : method) {

              if (meth.isAnnotationPresent(RequestMapping.class)) {

                  RequestMapping requestParam = meth.getAnnotation(RequestMapping.class);

                  String url = requestParam.value();

                  url = (baseUtl + url);

                  handlerMapping.put(url, meth);

                  System.out.println("Mapped:" + url + "," + method);

              }

           }

       }

    }

    private void doAutowired() {

       if (ioc.isEmpty())

           return;

       for (Entry<String, Object> entry : ioc.entrySet()) {

           Field[] fields = entry.getValue().getClass().getDeclaredFields();

           for (Field field : fields) {

              // 授权, 只要加了Autowired的

              if (!field.isAnnotationPresent(AutoWirted.class))

                  continue;

              AutoWirted autoWirted = field.getAnnotation(AutoWirted.class);

              String beanName = autoWirted.value().trim();

              if ("".equals(beanName)) {

                  beanName = field.getType().getName();

              }

              // 执行强制授权

              field.setAccessible(true);

              // 进行赋值操作

              try {

                  field.set(entry.getValue(), ioc.get(beanName));

              } catch (Exception e) {

                  e.printStackTrace();

                  continue;

              }

           }

       }

    }

    private void doInstance() {

       // 将扫描到的类初始化

       if (classNames.isEmpty())

           return;

       // 通过反射初始化

       try {

           for (String className : classNames) {

              Class clazz = Class.forName(className);

              // 有注解的类初始化

              if (clazz.isAnnotationPresent(Controller.class)) {

                  Object obj = clazz.newInstance();

                  // 初始化后放入ioc容器中

                  // 默认是类名的首字母小写

                  String beanName = lowerFirstCase(clazz.getSimpleName());

                  ioc.put(beanName, obj);

              } else if (clazz.isAnnotationPresent(Service.class)) {

                  // 1.默认首字母小写

                  // 2.如果是接口, 要把他的实现类赋值给它

                  // 3.如果自定义,就优先用自定义的名字

                  Service service = clazz.getAnnotation(Service.class);

                  String beanName = service.value();

                  if ("".equals(beanName.trim())) {

                     // 如果自定义名字为空,取默认值

                     beanName = lowerFirstCase(clazz.getSimpleName());

                  }

                  Object instance = clazz.newInstance();

                  ioc.put(beanName, instance);

                  // 解决子类引用赋值父类的问题

                  Class[] interfaces = clazz.getInterfaces();

                  for (Class i : interfaces) {

                     ioc.put(i.getName(), instance);

                  }

              } else {

                  continue;

              }

           }

       } catch (Exception e) {

           e.printStackTrace();

       }

    }

    private void doScanner(String scanPackage) {

       URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));

       File classDir = new File(url.getFile());

       // 递归扫描指定文件下的类

       for (File file : classDir.listFiles()) {

           if (file.isDirectory()) {// 判断是否文件夹

              doScanner(scanPackage + "." + file.getName());

           } else {// 如果不是文件夹

              String className = scanPackage + "." + file.getName().replace(".class", "");

              classNames.add(className);

           }

       }

    }

    private void doLoadConfig(String contextConfigLocation) {

       InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);

       try {

           contextConfig.load(is);

       } catch (IOException e) {

           e.printStackTrace();

       } finally {

           if (null != is) {

              try {

                  is.close();

              } catch (IOException e) {

                  e.printStackTrace();

              }

           }

       }

    }

    /** 自定义首字母小写 */

    private String lowerFirstCase(String str) {

       char[] chars = str.toCharArray();

       chars[0] += 32;

       return String.valueOf(chars);

    }

}

DemoAction.java

package com.aop.mvc.action;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.aop.mvc.annotaion.AutoWirted;

import com.aop.mvc.annotaion.Controller;

import com.aop.mvc.annotaion.RequestMapping;

import com.aop.mvc.annotaion.RequestParam;

import com.aop.mvc.servlet.IDemoService;

/**

 * @Theme 纯手写实现SpringMVC

 * @author http://localhost:8080/SpringAop-Demo/demo/query.json

 */

@Controller

@RequestMapping("/demo")

public class DemoAction {

    @AutoWirted

    private IDemoService demoService;

    @RequestMapping("/query.json")

    public void query(HttpServletRequest req, HttpServletResponse resp, @RequestParam("name") String name) {

       String result = demoService.get(name);

       try {

           resp.getWriter().write(result);

       } catch (Exception e) {

           // TODO: handle exception

       }

    }

    @RequestMapping("/add.json")

    public void add(HttpServletRequest req, HttpServletResponse resp, @RequestParam("a") Integer a, @RequestParam("b") Integer b) {

       try {

           resp.getWriter().write(a + "+" + b + "=" + (a + b));

       } catch (Exception e) {

           // TODO: handle exception

       }

    }

    @RequestMapping("/remove.json")

    public void remove(HttpServletRequest req, HttpServletResponse resp, @RequestParam("id") Integer id) {

       try {

       } catch (Exception e) {

           // TODO: handle exception

       }

    }

}

相关文章:

简化版SpringMVC

简化版SpringMVC web.xml xml version"1.0" encoding"UTF-8"?> <web-app version"2.5" xmlns"http://java.sun.com/xml/ns/javaee" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation&quo…...

Java密码校验(正则表达式):密码由这四种元素组成(数字、大写字母、小写字母、特殊字符),且必须包含全部四种元素;密码长度大于等于8个字符。

1. 需求 对用户密码的强度进行校验&#xff0c;要求用户密码达到一定的强度&#xff0c;符合安全性要求。 1.1. 基础版需求 密码必须由字母和数字组成&#xff08;同时包括数字和数字&#xff09;&#xff1b;密码长度大于等于8个字符。 1.2. 进阶版需求 密码由这四种元素…...

【AMI】2400 环境安装步骤

2400 环境安装步骤 ----------Ubuntu14.4 MDS4.0 加载代码需要勾上Update Installing SPX related packages sudo apt install gcc-multilib mtd-utils:i386 subversion patch patchutils bison sudo apt install libc6-dev libxml-dom-perl zlib1g zlib1g-dev libcurl4-ope…...

AI:124-基于深度学习的人体遮挡物体重建技术

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…...

23种设计模式之单例模式

目录 什么是单例模式 单例模式的优点 创建单例模式的三大要点 单例模式的实现方式 饿汉模式 懒汉模式 使用场景 什么是单例模式 单例模式是一种创建型设计模式&#xff0c;它的核心思想是保证一个类只有一个实例&#xff0c;并提供一个全局访问点来访问这个实例。 什…...

leetCode 30天

题太难了&#xff0c;就来一个N皇后吧 51. N 皇后 class Solution { private:vector<vector<string>> res;void backtracking(int n, int row, vector<string>& chessboard){if (row n){res.push_back(chessboard);return;}for (int col 0; col<n;…...

vue3+vite+ts 配置commit强制码提交规范配置 commitlint

配置 git 提交时的 commit 信息&#xff0c;统一提交 git 提交规范 安装命令: npm install -g commitizen npm i cz-customizable npm i commitlint/config-conventional commitlint/cli -D 文件配置 根路径创建文件 commitlint.config.js module.exports {// 继承的规…...

PlateUML绘制UML图教程

UML&#xff08;Unified Modeling Language&#xff09;是一种通用的建模语言&#xff0c;广泛用于软件开发中对系统进行可视化建模。PlantUML是一款强大的工具&#xff0c;通过简单的文本描述&#xff0c;能够生成UML图&#xff0c;包括类图、时序图、用例图等。PlantUML是一款…...

自然语言处理(NLP)——使用Rasa创建聊天机器人

1 基本概念 1.1 自然语言处理的分类 IR-BOT&#xff1a;检索型问答系统 Task-bot&#xff1a;任务型对话系统 Chitchat-bot:闲聊系统 1.2 任务型对话Task-Bot:task-oriented bot 这张图展示了一个语音对话系统&#xff08;或聊天机器人&#xff09;的基本组成部分和它们之间的…...

使用虚拟主机部署多站点

网站目录权限的管理和虚拟主机的配置。 目录权限控制...

Openresty+Lua+Redis实现高性能缓存

一、背景 当我们的程序需要提供较高的并发访问时&#xff0c;往往需要在程序中引入缓存技术&#xff0c;通常都是使用Redis作为缓存&#xff0c;但是要再更进一步提升性能的话&#xff0c;就需要尽可能的减少请求的链路长度&#xff0c;比如可以将访问Redis缓存从Tomcat服务器…...

基于Vue2用keydown、keyup事件实现长按键盘任意键(或组合键)3秒触发自定义事件(以F1键为例)

核心代码 <template></template> <script> export default {created() {//监听长按快捷键addEventListener("keydown", this.keydown);addEventListener("keyup", this.keyup);},destroyed(d) {//移除长按快捷键removeEventListener(&…...

【C#】.net core 6.0 设置根目录下某个文件夹可访问,访问创建的图片等资源

欢迎来到《小5讲堂》 大家好&#xff0c;我是全栈小5。 这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识点的理解和掌握。…...

报错ValueError: Unknown CUDA arch (8.6) or GPU not supported

文章目录 问题描述解决方案参考文献 问题描述 报错 ValueError: Unknown CUDA arch (8.6) or GPU not supported 本人显卡为 RTX 3060&#xff0c;CUDA 为 10.2&#xff0c;PyTorch 为 1.5 解决方案 修改 C:\Users\Administrator\Envs\test\Lib\site-packages\torch\utils\c…...

Golang 并发 Cond条件变量

Golang 并发 Cond条件变量 背景 编写代码过程中&#xff0c; 通常有主协程和多个子协程进行协作的过程&#xff0c;比如通过 WaitGroup 可以实现当所有子协程完成之后&#xff0c; 主协程再继续执行。 如上的场景是主协程等待子协程达到某个状态再继续运行。 但是反过来怎么…...

linux 下 chrome 无法在设置里面配置代理的解决方法

文章目录 [toc]解决方法查找 chrome 命令路径查看 chrome 启动文件方式一方法二 在 linux 环境下&#xff0c;使用 chrome 没办法像 firefox 一样在设置里面配置代理&#xff0c;打开 chrome 的设置会有下面的内容显示 When running Google Chrome under a supported desktop e…...

C#上位机与三菱PLC的通信03--MC协议之A-1E报文解析

1、MC协议帧 MC协议可以在串口通信&#xff0c;也可以在以太网通信&#xff0c;有A-1E和Qna-3E两种模式&#xff0c;这两种都是三菱PLC通信协议中比较常用的两种&#xff0c;一般我们使用比较多的是以太网通信&#xff0c;对于FX5U系列/Q系列/Qna系列/L系列的PLC&#xff0c;…...

nodeJS 的 npm 设置国内高速镜像之淘宝镜像的方法

1、我们知道 nodeJS 是老外搞出来的&#xff0c;服务器放在了国外&#xff0c;国内的小朋友访问起来会比较慢&#xff0c;阿里巴巴的淘宝给出了有力支持&#xff0c;现在我们就将 nodeJS 的镜像地址切换为国内的淘宝镜像。 2、查看当前的镜像地址&#xff1a; npm get registr…...

Nginx方向代理和负载均衡配置

1. Nginx介绍 2.Nginx常用命令 cd /usr/local/nginx/sbin/ ./nginx 启动 ./nginx -s stop 停止 ./nginx -s quit 安全退出 ./nginx -s reload 重新加载配置文件 如果我们修改了配置文件&#xff0c;就需要重新加载。 ps aux|grep nginx 查看nginx进程3.nginx配置文件 …...

贪心算法篇

“靠漫步&#xff0c;将生趣填饱~” 贪心算法简介&#xff1f; 贪心算法&#xff08;Greedy Algorithm&#xff09;&#xff0c;也称为贪婪算法&#xff0c;是一种在解决问题时采取贪心策略的方法。其基本原理是很简单的&#xff1a; “在每个决策点上都选择当下看似最好的选项…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...