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. linux php 环境word转pdf、excel转pdf、office转pdf

    最近项目中遇到一个需求,将word.excel文件转换成pdf,并且打上水印,我利用的是libreoffice,这个需要Java 的jdk环境.废话不多说,开撸 1.在linux上搭建jdk环境 文章 ...

  2. k8s命令行web代理神器gotty

    目录 介绍 安装 使用示例 -p 指定端口 -c 指定账号密码 -w 支持tty交互 --permit-arguments 支持get参数传参 --random-url 生成随机地址 --reconn ...

  3. MySQL between and 边界测试

    看到有一些博客说 between and 有不含边界的情况,于是测试了一把,记录如下.先说结论:between and 不存在不含边界的情况 1. between and 是包含边界的 id betw ...

  4. springcloud报错-Ribbon整合Eureka,出现 No instances available for XXX 异常

    RestTemplate注入有问题 新版的需要这样注入: @Bean @LoadBalanced RestOperations restTemplate(RestTemplateBuilder bui ...

  5. 使用阿里巴巴开源镜像站镜像——Kubernetes 镜像

    镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 Kubernetes 镜像简介 Kubernetes 是一个开源系统,用于容器化应用的自动部署.扩缩和管理.它将构成应用的容器按逻辑单位进行分组以 ...

  6. Linux移植到自己的开发板(一)环境搭建

    环境搭建 vmware:VMware Workstation 15 Pro Linux系统:Ubuntu16.04 x64 1. 在Windows系统安装VMware15软件: 2. 网上下载并解压u ...

  7. Java反射详解篇--一篇入魂

    1.反射概述 Java程序在运行时操作类中的属性和方法的机制,称为反射机制. 一个关键点:运行时 一般我们在开发程序时,都知道自己具体用了什么类,直接创建使用即可.但当你写一些通用的功能时没办法在编写 ...

  8. 12.16 JAVA swing

    ------------恢复内容开始------------ 12.16JAVA swing 1.框架 JFrame>JPanel>组件JButton JTestfilled JTable ...

  9. java 学习笔记(一)

    书 head first java 1. 2.加强版的FOR循环 3. 通过super引用父类 4.多态 5.接口和抽象类 接口 6.多线程锁 7.JDBC

  10. Java代码查错部分?

    1. abstract class Name { private String name; public abstract boolean isStupidName(String name) {} } ...