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

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

Python 高效图像帧提取与视频编码:实战指南

Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...