当前位置: 首页 > 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; “在每个决策点上都选择当下看似最好的选项…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

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

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

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...