1.1 新建DispatcherServlet

1.2 在src目录下,新建applicationContext.xml

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

<beans id="b1">
<bean id="emp" class="xxx.controller.EmpController"/>
<bean id="dept" class="xxx.controller.DeptController"/>
</beans>

1.3 在DispatcherServlet的构造方法中解析applicationContext.xml配置文件

import java.io.IOException;

import java.io.InputStream;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

import org.xml.sax.SAXException;

@WebServlet("*.do")

public class DispatcherServlet extends HttpServlet {

private Map<String, Object> map = new ConcurrentHashMap<>();

public DispatcherServlet() {

try {

InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("applicationContext.xml");

// 1,通过工厂模式,创建documentBuilderFactory工厂对象

DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

// 2,创建DocumentBuilder对象

DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

// 3,得到Document对象( 注意导入org.w3c.dom包中的)

Document document = documentBuilder.parse(inputStream);

// 4,获得所有的bean标签

NodeList nodeList = document.getElementsByTagName("bean");

for (int i = 0; i < nodeList.getLength(); i++) {

Node node = nodeList.item(i);

if(node.getNodeType() == Node.ELEMENT_NODE) {

//(注意导入org.w3c.dom包中的)

//强转成Element类的对象,里面有比Node类更方便的方法

Element element = (Element)node;

String id = element.getAttribute("id");

String className = element.getAttribute("class");

boolean flag = map.containsKey(id);

if(flag == true)

return;

Object o = Class.forName(className).newInstance();

map.put(id, o);

}

}

} catch (ParserConfigurationException | SAXException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {

e.printStackTrace();

}

}

@Override

protected void service(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

// 设置编码

request.setCharacterEncoding("UTF-8");

response.setCharacterEncoding("UTF-8");

response.setContentType("text/html;charset=UTF-8");

// 假设url是: http://localhost:8080/mymvc2/hello.do

// ServletPath是Servlet的访问路径: /hello.do

// 思路是:

// 第1步: /hello.do -> hello 或者 /book.do -> book

// 第2步: hello -> HelloController 或者 book -> BookController

String servletPath = request.getServletPath(); // /hello.do

int lastDotIndex = servletPath.lastIndexOf(".do");

servletPath = servletPath.substring(1, lastDotIndex); // hello

}

}

1.4 在DispatcherServlet的service方法中,通过ServletPath获取对应的Controller对象,优化反射的代码

@Override

protected void service(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

// 设置编码

request.setCharacterEncoding("UTF-8");

response.setCharacterEncoding("UTF-8");

response.setContentType("text/html;charset=UTF-8");

// 假设url是: http://localhost:8080/mymvc2/hello.do

// ServletPath是Servlet的访问路径: /hello.do

// 思路是:

// 第1步: /hello.do -> hello 或者 /book.do -> book

// 第2步: hello -> HelloController 或者 book -> BookController

String servletPath = request.getServletPath(); // /hello.do

int lastDotIndex = servletPath.lastIndexOf(".do");

servletPath = servletPath.substring(1, lastDotIndex); // hello

// 通过ServletPath获取对应的Controller对象

Object xxxController = map.get(servletPath);

String ac = request.getParameter("ac");

System.out.println("=======" + ac + "======");

if (StringUtil.isEmpty(ac))

ac = "index";

try {

// 这里只能try...catch异常,因为在重写的方法里,不能抛出比父类更大的异常

Method method = xxxController.getClass().getDeclaredMethod(ac, HttpServletRequest.class,HttpServletResponse.class);

if (method != null) {

method.invoke(xxxController, request, response);

} else {

throw new RuntimeException("ac值违法");

}

} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException

| InvocationTargetException e) {

e.printStackTrace();

}

}

1.5 写一个简单的EmpController

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class EmpController {

public void index(HttpServletRequest request,HttpServletResponse response) {

System.out.println("EmpController...index");

}

}

2. 第二次改进,每一个方法中都有获取参数的代码, 或者都有请求转发或是重定向的代码。解决跳转问题

(代码格式问题各位大佬别吐槽,复制过来的有时间改)

二. 手写SpringMVC框架的更多相关文章

  1. (二)springMvc原理和手写springMvc框架

    我们从两个方面了解springmvc执行原理,首先我们去熟悉springmvc执行的过程,然后知道原理后通过手写springmvc去深入了解代码中执行过程. (一)SpringMVC流程图 (二)Sp ...

  2. 手写SpringMVC框架(二)-------结构开发设计

    续接前文, 手写SpringMVC框架(一)项目搭建 本节我们来开始手写SpringMVC框架的第二阶段:结构开发设计. 新建一个空的springmvc.properties, 里面写我们要扫描的包名 ...

  3. 手写SpringMVC 框架

    手写SpringMVC框架 细嗅蔷薇 心有猛虎 背景:Spring 想必大家都听说过,可能现在更多流行的是Spring Boot 和Spring Cloud 框架:但是SpringMVC 作为一款实现 ...

  4. 手写SpringMVC框架(三)-------具体方法的实现

    续接前文 手写SpringMVC框架(二)结构开发设计 本节我们来开始具体方法的代码实现. doLoadConfig()方法的开发 思路:我们需要将contextConfigLocation路径读取过 ...

  5. 手写SpringMVC框架(一)-------项目搭建

    SpringMVC处理请求的大致流程: 我们来开始着手手写一个SpringMVC框架. 新建一个springMVC项目,流程参见 SpringMVC框架搭建流程 引入servlet相关的jar包: & ...

  6. 纯手写SpringMVC框架,用注解实现springmvc过程

    闲话不多说,直接上代码! 1.第一步,首先搭建如下架构,其中,annotation中放置自己编写的注解,主要包括service controller qualifier RequestMapping ...

  7. 五,手写SpringMVC框架,过滤器的使用

    8. 过滤器 8.1 编写字符过滤器 CharacterEncodingFilter 复制项目mymvc4,新建项目mymvc5 package com.hy.filter; import java. ...

  8. 深度解析SpringMvc实现原理手写SpringMvc框架

    http://www.toutiao.com/a6340568603607171329/?tt_from=mobile_qq&utm_campaign=client_share&app ...

  9. 《四 spring源码》手写springmvc

    手写SpringMVC思路 1.web.xml加载  为了读取web.xml中的配置,我们用到ServletConfig这个类,它代表当前Servlet在web.xml中的配置信息.通过web.xml ...

随机推荐

  1. C/C++语言读取SEGY文件(二)

    SEGY IO (2D) 本文档将介绍SEGY的读取与写入过程,即SEGY文件的复制,并且在实现过程采用采样点×道数二维数组的形式读写. 新建头文件SegyDataIO2D.h与C++文件SegyDa ...

  2. [递归回溯] LeetCode 504七进制数(摸鱼版)

    LeetCode 七进制数 前言: 这个就没什么好说的了 题目:略 步入正题 进位制转换 10 -n 余数加倒叙 没什么好讲的直接上七进制代码 偷个懒 10进位制转7 class Solution { ...

  3. hadoop学习笔记 一

    Hadoop 2.x * common * HDFS 存储数据 NameNode 主从结构 * 存储文件系统的元数据,命名空间namespace DataNode * 存储数据 SecondaryNa ...

  4. WOE(weight of evidence, 证据权重)

    1. WOE(weight of evidence, 证据权重) WOE是一种衡量正常样本( Good)和违约样本( Bad)分布的差异方法 WOE=ln(Distr Good/Distr Bad)例 ...

  5. vscode使用python虚拟环境

    vscode使用python虚拟环境 创建好虚拟环境之后,在vscode中配置使用python的虚拟环境. 首先打开设置,然后搜索python venv, 在python: Venv Path中设置为 ...

  6. 一键生成mapper、mapperxml等文件——MybatisX插件的使用

    本文首发于西二blogs:一键生成mapper.mapperxml等文件--MybatisX插件的使用 搬运请务必转载出处. MybatisX插件使用--为快速开发而生 前言:其实很久以前我就非常厌恶 ...

  7. unittest 测试用例实现

    unittest框架结构 test_case: 测试套件,每一个.py文件代表一个测试用例,测试用例以test开头,否则框架读取不到测试用例 __init__.py是做什么的? 要弄明白这个问题,首先 ...

  8. ::before和:after中的的双冒号和单冒号有什么区别及这两个伪元素的作用

    ::before和:after中的的双冒号和单冒号有什么区别及这两个伪元素的作用 单冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素(伪元素由双冒号和伪元素名称组成),为了兼容已有的伪元素 ...

  9. protocol 协议语言介绍

    Protocol Buffer是Google提供的一种数据序列化协议,是一种轻便高效的结构化数据存储格式,可以用于结构化数据序列化,很适合做数据存储或 RPC 数据交换格式.它可用于通讯协议.数据存储 ...

  10. Java LRU实现方式

    动画理解LRU算法:https://www.pianshen.com/article/8150146075/ Java实现LRU算法:https://www.pianshen.com/article/ ...