二. 手写SpringMVC框架
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框架的更多相关文章
- (二)springMvc原理和手写springMvc框架
		
我们从两个方面了解springmvc执行原理,首先我们去熟悉springmvc执行的过程,然后知道原理后通过手写springmvc去深入了解代码中执行过程. (一)SpringMVC流程图 (二)Sp ...
 - 手写SpringMVC框架(二)-------结构开发设计
		
续接前文, 手写SpringMVC框架(一)项目搭建 本节我们来开始手写SpringMVC框架的第二阶段:结构开发设计. 新建一个空的springmvc.properties, 里面写我们要扫描的包名 ...
 - 手写SpringMVC 框架
		
手写SpringMVC框架 细嗅蔷薇 心有猛虎 背景:Spring 想必大家都听说过,可能现在更多流行的是Spring Boot 和Spring Cloud 框架:但是SpringMVC 作为一款实现 ...
 - 手写SpringMVC框架(三)-------具体方法的实现
		
续接前文 手写SpringMVC框架(二)结构开发设计 本节我们来开始具体方法的代码实现. doLoadConfig()方法的开发 思路:我们需要将contextConfigLocation路径读取过 ...
 - 手写SpringMVC框架(一)-------项目搭建
		
SpringMVC处理请求的大致流程: 我们来开始着手手写一个SpringMVC框架. 新建一个springMVC项目,流程参见 SpringMVC框架搭建流程 引入servlet相关的jar包: & ...
 - 纯手写SpringMVC框架,用注解实现springmvc过程
		
闲话不多说,直接上代码! 1.第一步,首先搭建如下架构,其中,annotation中放置自己编写的注解,主要包括service controller qualifier RequestMapping ...
 - 五,手写SpringMVC框架,过滤器的使用
		
8. 过滤器 8.1 编写字符过滤器 CharacterEncodingFilter 复制项目mymvc4,新建项目mymvc5 package com.hy.filter; import java. ...
 - 深度解析SpringMvc实现原理手写SpringMvc框架
		
http://www.toutiao.com/a6340568603607171329/?tt_from=mobile_qq&utm_campaign=client_share&app ...
 - 《四 spring源码》手写springmvc
		
手写SpringMVC思路 1.web.xml加载 为了读取web.xml中的配置,我们用到ServletConfig这个类,它代表当前Servlet在web.xml中的配置信息.通过web.xml ...
 
随机推荐
- CF1601C题解
			
赛时一小时,赛后十分钟. 题意:给定一个序列 \(a\) 和一个集合 \(b\),问将 \(b\) 中所有元素插入 \(a\) 后逆序对最少是多少. 观察样例解释,发现 \(b\) 已经被排序过了,于 ...
 - CVE-2018-12613phpMyAdmin 后台文件包含漏洞分析
			
一. 漏洞背景 phpMyAdmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库.借由此Web接口可以成 ...
 - 2022年官网下安装Elasticsearch最全版与官网查阅方法(8.1.0最新安装)
			
目录 一.环境整合(需要提前装好) 构建工具(参考工具部署方式) 二.官方下载Elasticsearch部署安装 1.百度搜索"Elasticsearch",或者访问官网https ...
 - 使用SymPy
			
最近工作的原因,需要进行一些积分运算,通过一些搜索得知了SymPy,记录一下使用历程. 1. SymPy介绍 SymPy是关于Symbolic Mathematics的Python库,它旨在成为一个功 ...
 - ZYNQ 驱动初始化套路--UART串口
			
@ 目录 UART 串口 GPIO之 MIO控制 LED 套路如下: 1.定义硬件信息结构体 namePs_Config *Config; 2.定义驱动信息结构体 namePs name_Ps; 3. ...
 - python练习册 每天一个小程序 第0006题
			
1 # -*-coding:utf-8-*- 2 __author__ = 'Deen' 3 ''' 4 题目描述: 5 你有一个目录,放了你一个月的日记,都是 txt,为了避免分词的问题,假设内容都 ...
 - 摆烂期的Android学习笔记一
			
Android大致分为四层架构1.Linux内核层:提供各种硬件驱动,如显示驱动,音频驱动,相机驱 动,蓝牙驱动.... 2.系统运行库层:通过C/c++库为android地图提供支持 3.应用框架层 ...
 - svn 清理报错
			
Can't install '*' from pristine store, because no checksum is recorded for this file svn同步时,提示clean ...
 - Java使用多线程异步执行批量更新操作
			
import com.google.common.collect.Lists; import org.apache.commons.collections.CollectionUtils; impor ...
 - RocketMQ下载安装
			
windows下RocketMQ下载安装教程 一.下载 1.官网下载:http://rocketmq.apache.org/dowloading/releases/ 2.百度网盘下载:https: ...