码迷,mamicode.com
首页 > 编程语言 > 详细

源码学习(一)——模拟Spring MVC

时间:2017-12-26 23:12:21      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:static   coding   mode   classes   str   调用   打印   dog   not   

1.准备

1.1创建项maven项目,目录如下

技术分享图片

1.2 导包

servlet-api: 模拟springmvc采用的是对同一个servlet进行处理

fastjson: JSONObject 是阿里自己封装的一个map,本人习惯使用,非必需

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation
="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.rrg</groupId> <artifactId>learning-framework</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency>

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.8</version>
    </dependency>

  </dependencies>
</project>

2.自定义SpringMVC注解

技术分享图片

2.1 MyMapper

package com.rrg.ssm.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)    //作用目标 所有对象
@Retention(RetentionPolicy.RUNTIME)    //保留策略    运行期
@Documented
public @interface MyMapper {

    String value() default "";
    
}

2.2MyService.java

package com.rrg.ssm.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE) //作用目标 所有对象
@Retention(RetentionPolicy.RUNTIME) //保留策略 运行期
@Documented
public @interface MyService {

String value() default "";

}

2.2

package com.rrg.ssm.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)    //作用目标 所有对象
@Retention(RetentionPolicy.RUNTIME)    //保留策略    运行期
@Documented
public @interface MyController {

    String value() default "";
    
}

 

2.3MyController.java

package com.rrg.ssm.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)    //作用目标 所有对象
@Retention(RetentionPolicy.RUNTIME)    //保留策略    运行期
@Documented
public @interface MyController {

    String value() default "";
    
}

 

2.4  MyQulifier.java

package com.rrg.ssm.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)    //作用目标 字段 即 成员变量
@Retention(RetentionPolicy.RUNTIME)    //保留策略    运行期
@Documented
public @interface MyQulifier {

    String value() default "";
    
}

2.5 RequestMapping.java

package com.rrg.ssm.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE,ElementType.METHOD})    //作用目标 所有对象 和 方法
@Retention(RetentionPolicy.RUNTIME)    //保留策略    运行期
@Documented
public @interface MyRequestMapping {

    String value() default "";
    
}

3.模拟业务逻辑

3.1 entity

User.java

package com.rrg.ssm.entity;

public class User {

    private String name;
    private Integer age;
    
    public User() {
    }
    
    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }
}

 

3.2 mapper层

UserMapper.java

package com.rrg.ssm.mapper;

import com.rrg.ssm.annotation.MyMapper;
import com.rrg.ssm.entity.User;
/**
 * 用户Mapper
 * @author JIE
 */
@MyMapper("userMapper")
public class UserMapper {

    public User selectById(Integer id){
        System.out.println("【UserMapper】执行查询操作");
        User user = new User("JIE",    22);
        return user;
    }
}

 

3.3 service层

UserSservice.java

package com.rrg.ssm.service;

import com.rrg.ssm.entity.User;
/**
 * 用户服务接口
 * @author JIE
 */
public interface UserService {

    /**
     * 根据id查找用户
     */
    public User selectById(Integer id);
}

 

UserServiceImpl.java

package com.rrg.ssm.service.impl;

import com.rrg.ssm.annotation.MyQulifier;
import com.rrg.ssm.annotation.MyService;
import com.rrg.ssm.entity.User;
import com.rrg.ssm.mapper.UserMapper;
import com.rrg.ssm.service.UserService;
/**
 * 用户服务实现类
 * @author JIE
 */
@MyService("userService")
public class UserServiceImpl implements UserService {

    @MyQulifier("userMapper")
    private UserMapper userMapper;
    
    public User selectById(Integer id) {
        System.out.println("【UserService】执行业务操作");
        return userMapper.selectById(id);
    }

}

 

3.4 UserController.java

 

package com.rrg.ssm.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.rrg.ssm.annotation.MyController;
import com.rrg.ssm.annotation.MyQulifier;
import com.rrg.ssm.annotation.MyRequestMapping;
import com.rrg.ssm.entity.User;
import com.rrg.ssm.service.UserService;
/**
 * 
 * @author JIE
 *
 */
@MyController("userController")
@MyRequestMapping("/user")
public class UserController {

    @MyQulifier("userService")
    private UserService userService;
    
    @MyRequestMapping("/get")
    public void getUser(HttpServletRequest request, HttpServletResponse response) {
        User user = userService.selectById(2);
        System.out.println("【UserController】:" + user);
    }
}

 

4.spring mvc核心

思路:  ①扫描包,将所有文件放到package的一个list里面;

     ②扫描①中的包,找到三层架构的controller,service,mapper并实例化放到map,key为注解上的值就变量名,例如@MyController("userController")                                         map("userController",userController实例化的对象);

     ③建立映射关系,实现@RequestMapping功能,根据类前的注解和方法前的注解,保存到map,key是拦截的地址,value是对应的方法,为后面提供调                                        用method.invoke(userController, req, resp);

     ④注入依赖,DI,根据MyQulifier注解到②的map中找到实体,注入到成员变量 field(obj,obj)

4.1 核心MyDispatcherServlet.java

 

package com.rrg.ssm.core;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSONObject;
import com.rrg.ssm.annotation.MyController;
import com.rrg.ssm.annotation.MyMapper;
import com.rrg.ssm.annotation.MyQulifier;
import com.rrg.ssm.annotation.MyRequestMapping;
import com.rrg.ssm.annotation.MyService;
import com.rrg.ssm.controller.UserController;
/**
 * Spring MVC核心
 * @author JIE
 */
public class MyDispatcherServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;
    
    private List<String> packageList = new ArrayList<String>();
    private JSONObject instanceJSON = new JSONObject();
    private JSONObject mappingJSON = new JSONObject();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //requestURl=>    http://localhost:8180/learning-again/user/get
        //StringBuffer requestURl = req.getRequestURL();
        //requestURI=>    /learning-again/user/get
        String requestURI = req.getRequestURI();
        //contextPath=>    /learning-again
        String contextPath = req.getContextPath();
        //reqpath=>        /user/get    
        String reqpath = requestURI.replace(contextPath, "");
        UserController userController = (UserController) instanceJSON.get("userController");
        Method method = (Method) mappingJSON.get(reqpath);
        try {//拦截请求找到实例对象的方法,并调用
            method.invoke(userController, req, resp);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
         // 包扫描,获取包中的文件
        scanPackage("com.rrg");
        System.out.println("【init】扫描包完成");
        try {
            filterAndInstance();
            System.out.println("【init】实例化(注解)完成");
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 建立映射关系
        handerMap();
        System.out.println("【init】映射完成");
        // 实现注入
        DI();
        System.out.println("【init】属性注入完成");
    }

    /**
     * 扫描字段注解
     */
    private void DI() {
        if(instanceJSON.size() <= 0) {
            return ;
        }
        for (Map.Entry<String, Object> entry : instanceJSON.entrySet()) {
            Field[] fields = entry.getValue().getClass().getDeclaredFields();
            for (Field field : fields) {
                if(field.isAnnotationPresent(MyQulifier.class)) {
                    MyQulifier myQulifier = field.getAnnotation(MyQulifier.class);
                    String key = myQulifier.value();
                    field.setAccessible(true);
                    try {
                        field.set(entry.getValue(), instanceJSON.get(key));
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * requestMapping
     */
    private void handerMap() {
        for (Map.Entry<String, Object> entry : instanceJSON.entrySet()) {
            if(entry.getValue().getClass().isAnnotationPresent(MyController.class)) {
                MyRequestMapping myRequestMapping = entry.getValue().getClass().getAnnotation(MyRequestMapping.class);
                String classMapping = myRequestMapping.value();
                //取得所有在
                Method[] methods = entry.getValue().getClass().getDeclaredMethods();
                for (Method method : methods) {
                    if(method.isAnnotationPresent(MyRequestMapping.class)) {
                        MyRequestMapping methodRequestMapping = method.getAnnotation(MyRequestMapping.class);
                        String methodMapping = methodRequestMapping.value();
                        mappingJSON.put(classMapping + methodMapping , method);
                    }else {
                        continue;
                    }
                }
            }
        }
    }

    /**
     * 实例化三层架构的实例化
     */
    private void filterAndInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //instanceJSON
        if(packageList.size()<=0) {
            return ;
        }
        for (String filePackage : packageList) {
            
            Class<?> fileClass = Class.forName(filePackage.replace(".class", "").trim());
            //判断类是否存在注释
            if(fileClass.isAnnotationPresent(MyController.class)) {
                Object newInstance = fileClass.newInstance();
                MyController myController = newInstance.getClass().getAnnotation(MyController.class);
                String key = myController.value();
                instanceJSON.put(key,newInstance);
            }else if(fileClass.isAnnotationPresent(MyService.class)) {
                Object newInstance = fileClass.newInstance();
                MyService myService = newInstance.getClass().getAnnotation(MyService.class);
                String key = myService.value();
                instanceJSON.put(key,newInstance);
            }else if(fileClass.isAnnotationPresent(MyMapper.class)) {
                Object newInstance = fileClass.newInstance();
                MyMapper myMapper = newInstance.getClass().getAnnotation(MyMapper.class);
                String key = myMapper.value();
                instanceJSON.put(key,newInstance);
            }else {
                continue;
            }
        }
    }

    private void scanPackage(String PACKAGE) {
        //    file:/C:/Users/abc/eclipse_0821/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/learning-again/WEB-INF/classes/com/rrg/
        URL url=this.getClass().getClassLoader().getResource("/" + replaceTo(PACKAGE));
        //    /C:/Users/abc/eclipse_0821/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/learning-again/WEB-INF/classes/com/rrg/
        String fileName = url.getFile();
        
        File file = new File(fileName);
        String[] list = file.list();
        for (String path : list) {
            File eachFile = new File(fileName + path);
            if(eachFile.isDirectory()) {
                scanPackage(PACKAGE + "." + eachFile.getName());
            }else {
                packageList.add(PACKAGE + "." + eachFile.getName());
            }
        }
    }

    /**
     * path中‘.‘转成‘/‘
     */
    private String replaceTo(String path) {
        return path.replaceAll("\\.", "/");
    }
}

 

4.2  统一处理请求

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>aaaa</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>MyDispatcherServlet</servlet-name> <servlet-class>com.rrg.ssm.core.MyDispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyDispatcherServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>

5 测试

DEBUG AS=》 SERVER 访问 http://localhost:8080/user/get,

控制台打印

技术分享图片

SUCCESS!

以上的源码借鉴博客  https://www.cnblogs.com/Shock-W/p/6617068.html

源码学习(一)——模拟Spring MVC

标签:static   coding   mode   classes   str   调用   打印   dog   not   

原文地址:https://www.cnblogs.com/cookwithme/p/8120448.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!