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

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

Golang——9、反射和文件操作

反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一&#xff1a;使用Read()读取文件2.3、方式二&#xff1a;bufio读取文件2.4、方式三&#xff1a;os.ReadFile读取2.5、写…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...

comfyui 工作流中 图生视频 如何增加视频的长度到5秒

comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗&#xff1f; 在ComfyUI中实现图生视频并延长到5秒&#xff0c;需要结合多个扩展和技巧。以下是完整解决方案&#xff1a; 核心工作流配置&#xff08;24fps下5秒120帧&#xff09; #mermaid-svg-yP…...

Linux操作系统共享Windows操作系统的文件

目录 一、共享文件 二、挂载 一、共享文件 点击虚拟机选项-设置 点击选项&#xff0c;设置文件夹共享为总是启用&#xff0c;点击添加&#xff0c;可添加需要共享的文件夹 查询是否共享成功 ls /mnt/hgfs 如果显示Download&#xff08;这是我共享的文件夹&#xff09;&…...