博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
解析SpringMVC 前端控制器(Dispatcherservlet)
阅读量:6907 次
发布时间:2019-06-27

本文共 7514 字,大约阅读时间需要 25 分钟。

hot3.png

一 SpringMVC 流程图

170203_EVYw_3218528.png

 

DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。

自己实现了一个dispatcherServlet,希望帮助大家理解DispatcherServlet的实现原理。目录如下(后面会重构,结构会有所变化)

构)224534_dsZz_3218528.png

二 注解 

   模仿SpringMVC ,自定义 ,,@AutoWired,@RequestMapping

   

        225041_9L7d_3218528.png

    @Service

       225059_4uju_3218528.png

    @RequestMapping

      225117_DdBy_3218528.png

    @AutoWired

      225133_dvQO_3218528.png

三 DispatcherServlet

  SpringMVC 同样要遵循JAVA EE 规范。所以DispatcherServlet 要继承HttpServlet。

  实现代码如下

 

package servlet;import com.dsk.annotation.Autowired;import com.dsk.annotation.Controller;import com.dsk.annotation.RequestMapping;import com.dsk.annotation.Service;import com.dsk.controller.ControllerTest;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 java.io.File;import java.io.IOException;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;/** * Created by dingshuangkun on 2018/1/29. */public class Dispatcherservlet extends HttpServlet {    private volatile List
classNameList = new ArrayList<>(); private volatile Map
instanceMap = new HashMap<>(); /** * @throws ServletException 1 扫描基包 */ @Override public void init() throws ServletException { String baseScan = "com.dsk.controller,com.dsk.service"; // 扫描基包 获取包名加类名 Map
> packageMap = scanFile(baseScan); try { for(Map.Entry
> entry : packageMap.entrySet()){ String packageName = entry.getKey(); List
classNames = entry.getValue(); // 4 实例化(包名+类名) Class.forName() newInstance(packageName,classNames); } // 实现IOC 注入 Ioc(instanceMap); }catch (Exception e){ throw new RuntimeException(e.getMessage()); } } private Map
> scanFile(String baseScan) { Map
> packageMap = new HashMap<>(); // 分割 com.dsk.controller 和 com.dsk.service String[] paths = baseScan.split(","); // 替换为 com/dsk/controller for (String path : paths) { String filePath = "/" + path.replaceAll("\\.", "\\/"); // 1 加载资源 URL url = this.getClass().getClassLoader().getResource(filePath); // 2 获取全路径名 String urlPath = url.getFile(); // 3 处理路径 得到包下面的类 List
classNames = handleFile(urlPath); // 4 分组 根据包名分组 for(String className : classNames){ packageMap.putIfAbsent(path,new ArrayList<>()); packageMap.get(path).add(className); } classNameList.clear(); } return packageMap; } /** * 处理路径 * * @param urlPath */ private List
handleFile(String urlPath) { File file = new File(urlPath); if (file.isDirectory()) { String[] paths = file.list(); for (String path : paths) { // 可能是文件也可能是文件夹 递归处理 handleFile(urlPath + path); } } else { classNameList.add(file.getName().replace(".class", "")); } return classNameList; } /** * 实例化 * 1 通过包名+类名 获取Class 对象 * 2 获取注解信息@Controller 和 @Service * 3 实例化 放入容器Map中 */ private void newInstance(String packageName, List
classNames) throws Exception { if (classNames != null && classNames.size() != 0) { for (String className : classNames) { String name = packageName + "." + className; Class cc = Class.forName(packageName + "." + className); // 判断类上是否有@Controller if (cc.isAnnotationPresent(Controller.class)) { Controller controller = (Controller) cc.getAnnotation(Controller.class); // 获取注解的值 String value = controller.value(); if (value != null && value.length() > 0) { // 把实例存放到容器中 instanceMap.put(value, cc.newInstance()); } else { // 第一个字母转小写(还没实现) instanceMap.put(className, cc.newInstance()); } } else if (cc.isAnnotationPresent(Service.class)) { Service service = (Service) cc.getAnnotation(Service.class); String value = service.value(); if (value != null && value.length() > 0) { // 把实例存放到容器中 instanceMap.put(value, cc.newInstance()); } else { // 第一个字母转小写(还没实现) instanceMap.put(className, cc.newInstance()); } } } } } /** * IOC 注入 * 1 遍历 Map 获取对象 * 2 反射 获取字段 * 3 给带有@Autowired 注解的字段实例化 */ private void Ioc(Map
instanceMap) throws IllegalAccessException { if (instanceMap == null || instanceMap.size() == 0) { return; } for (Map.Entry
entry : instanceMap.entrySet()) { Object obj = entry.getValue(); // 获取Class 对象 Class cc = obj.getClass(); // 获取声明的字段 Field[] fields = cc.getDeclaredFields(); if (fields != null && fields.length > 0) { for (Field field : fields) { // 判读是否带有注解 Autowired if (field.isAnnotationPresent(Autowired.class)) { field.setAccessible(true); Autowired autowired = field.getAnnotation(Autowired.class); // 从容器中获取对象 Object instance = instanceMap.get(autowired.value()); field.set(obj, instance); } } } } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String url = req.getServletPath(); try { parseUrl(url); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("-----doPost------"); } private void parseUrl(String url) throws Exception { String path = url.subSequence(1, url.length()).toString(); String[] params = path.split("/"); if (params.length != 2) { return; } for (Map.Entry
entry : instanceMap.entrySet()) { Class cc = entry.getValue().getClass(); // 判读类上是否有@Controller 和 @RequestMapping 注解 if (cc.isAnnotationPresent(Controller.class) && cc.isAnnotationPresent(RequestMapping.class)) { RequestMapping requestMapping = (RequestMapping) cc.getAnnotation(RequestMapping.class); // 获取@RequestMapping 的值 String paramValue = requestMapping.value(); if (paramValue != null && paramValue.length() > 0) { // localhost:8080/test/test params=test,test // 判读 类上 @RequestMapping的值是否和 params[0] 相等 if (paramValue.equals(params[0])) { // 获取该类的方法 Method[] methods = cc.getMethods(); if (methods != null && methods.length > 0) { for (Method method : methods) { // 判读方法上是否有@RequestMapping 注解 if (method.isAnnotationPresent(RequestMapping.class)) { RequestMapping rem = method.getAnnotation(RequestMapping.class); // 获取方法上@RequestMapping 的值 String methodParam = rem.value(); if (methodParam != null && methodParam.length() > 0) { // 方法上@RequestMapping 的值methodParam 和 params[1] 是否相等 if (methodParam.equals(params[1])) { method.invoke(entry.getValue(), null); } } } } } } } } } }}

 

测试类

package com.dsk.controller;import com.dsk.annotation.Autowired;import com.dsk.annotation.Controller;import com.dsk.annotation.RequestMapping;import com.dsk.service.MyService;/** * Created by dingshuangkun on 2018/1/29. */@Controller("controllerTest")@RequestMapping("test")public class ControllerTest {    @Autowired("myService")    private MyService myService;    @RequestMapping("test")    public void test(){        System.out.println("--------------");        System.out.println("---- ******  ---");        System.out.println("---*********----");        System.out.println("-----------------");    }}
package com.dsk.service;import com.dsk.annotation.Service;/** * Created by dingshuangkun on 2018/1/29. */@Service("myService")public class MyService {    public void  test(){        System.out.println("----serviceTest----");    }}

 

配置文件

myservlet
servlet.Dispatcherservlet
myservlet
/

 

浏览器输入

http://localhost:8080/test/test

输出

--------------

---- ******  ---
---*********----
-----------------

转载于:https://my.oschina.net/u/3218528/blog/1615081

你可能感兴趣的文章
新手学习oracle之迁移数据表空间
查看>>
java-第十四章-代参的方法(二)-查找会员积分
查看>>
检查HP服务器内存状态脚本
查看>>
string.punctuation
查看>>
实验一 分治与递归—用分治法实现元素选择 java算法
查看>>
HMGET key field [field ...]
查看>>
.NET简谈自定义事务资源管理器
查看>>
进一步理解VC中的句柄
查看>>
物联网医疗来了:让患者获得一站式医疗服务
查看>>
2015.08.26枚举
查看>>
张伯旭:北京亦庄着力打造中国云产业园
查看>>
《精通Linux设备驱动程序开发》——第1章 引言 1.1演进
查看>>
Objective-C精选字符串处理方法
查看>>
【PM&数据】如何正确地利用产品数据【上】
查看>>
JS是世界上最好的语言—— J.A.R.V.I.S诞生记
查看>>
小哥哥要了解一下图片懒加载吗?
查看>>
SQL Server性能调优之执行计划深度剖析 第一节 浅析SQL执行的过程
查看>>
我的友情链接
查看>>
出来了
查看>>
我的友情链接
查看>>