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. Caffe2源码解析

    写在前面 上一篇文章对Caffe2中的core模块进行了简单拆解Caffe2源码解析之core,本篇给出其它模块的拆解,目的是大致了解每个模块的内容和目标,进一步理解Caffe2的整体框架.内容不多, ...

  2. Spring-MyBatis的配置文件

    <?xml version="1.0" encoding="UTF8"?> <beans xmlns="http://www.spr ...

  3. CacheManager Net Core Redis 缓存

    using CacheManager.Core; using System; using System.Collections.Generic; using System.Text; namespac ...

  4. github:git clone下载加速以及vim-plug下载插件加速

    git clone 下载加速 1. 先在github将仓库地址复制下来 2. git clone时将https://github.com/* 改为https://gitclone.com/github ...

  5. VuePress 博客之 SEO 优化(六)站长工具

    前言 在 <一篇带你用 VuePress + Github Pages 搭建博客>中,我们使用 VuePress 搭建了一个博客,最终的效果查看:TypeScript 中文文档. 本篇接着 ...

  6. Java基础——StringBuilder的添加与反转方法

    StringBuilder添加与反转方法 方法 返回对象 public StringBuilder append(任意类型) 添加任意参数数据,并返回对象本身,注意:返回的是对象本身,则调用过appe ...

  7. Java基础—构造方法

    1.构造方法概述 构造方法是一种特殊的方法,用来创建对象,当我们不定义时,系统会默认给出一个无参构造方法:一旦我们定义了任意的构造方法,系统就不会给出默认的无参构造方法 格式如下: public ca ...

  8. 使用数据库连接工具DBeaver连接H2数据库

    H2数据库第一次听说,学习了. H2数据库自带了一个浏览器web操作,但是非常的不好用,用DBeaver看着好用多了. 1.点击带+的连接图标 2.选择ALL点击H2 Embedded.(如果本地没有 ...

  9. Windows 如何打开 .md 文件

    •问题 最近在学习[C++|黑马程序员],对于课堂笔记中的 .md 文档无从下手,要是直接通过 Chrome 打开排版又很乱,且不能正常显示URL中的内容: 这可如何是好??? •解决方案 1. 打开 ...

  10. Redis快速入门:初识Redis

    [IT168 专稿]在之前的文章中介绍了<Redis快速入门:选择Key-Value Store>,今天给大家介绍Redis的入门知识.Redis是一个开源的使用ANSI C语言编写.支持 ...