手写实现springMVC框架

 

项目目录结构:

maven引入servlet包

<dependency>
	    <groupId>javax.servlet</groupId>
	    <artifactId>javax.servlet-api</artifactId>
	    <version>3.0.1</version>
	    <scope>provided</scope>
	  </dependency>

1:编写自定义注解

MyAutowired

package com.zhjie.mySpring.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 MyAutowired {
	String value() default "";
}

 MyController

package com.zhjie.mySpring.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 "";
}

MyRequestMapping

package com.zhjie.mySpring.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 "";
}

MyRequestParam 

package com.zhjie.mySpring.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.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyRequestParam {
	String value() default "";
}

MyService

package com.zhjie.mySpring.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:定义service层

TestService

package com.zhjie.mySpring.service;

public interface TestService {
	String query(String name,String age);

}

TestServiceImpl

package com.zhjie.mySpring.service.impl;

import com.zhjie.mySpring.annotation.MyService;
import com.zhjie.mySpring.service.TestService;
@MyService("TestServiceImpl")
public class TestServiceImpl implements TestService{

	public String query(String name, String age) {
		return "name="+name+";age="+age;
	}

}

3:定义controller层

TestController

package com.zhjie.mySpring.controller;

import java.io.IOException;
import java.io.PrintWriter;

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

import com.zhjie.mySpring.annotation.MyAutowired;
import com.zhjie.mySpring.annotation.MyController;
import com.zhjie.mySpring.annotation.MyRequestMapping;
import com.zhjie.mySpring.annotation.MyRequestParam;
import com.zhjie.mySpring.service.TestService;

@MyController
@MyRequestMapping("/user")
public class TestController {
	
	@MyAutowired("TestServiceImpl")
	private TestService testService;
	/**
	 * 
	 * <p>Title: query</p>  
	 * <p>Description: 查询</p>  
	 * @param request
	 * @param response
	 * @param name
	 * @param age
	 */
	@MyRequestMapping("/query")
	public void query(HttpServletRequest request,HttpServletResponse response,@MyRequestParam("name") String name,@MyRequestParam("age") String age){
		PrintWriter writer;
		try {
			writer = response.getWriter();
			String result = testService.query(name, age);
			writer.write(result);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

4:定义DispatcherServlet

package com.zhjie.mySpring.servlet;

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.HashMap;
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.zhjie.mySpring.annotation.MyAutowired;
import com.zhjie.mySpring.annotation.MyController;
import com.zhjie.mySpring.annotation.MyRequestMapping;
import com.zhjie.mySpring.annotation.MyService;
import com.zhjie.mySpring.controller.TestController;
import com.zhjie.mySpring.handlerAdapter.HandlerAdapterService;
/**
 * 
 * <p>Title: DispatcherServlet</p>  
 * <p>Description: servlet核心处理类</p>  
 * @author zhjie  
 * @date 2020年2月23日
 */
public class DispatcherServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	// 存在当前加载的所有的类
	List<String> classNames = new ArrayList<String>();
	
	// 存放实例化对象
	Map<String,Object> beans = new HashMap<String, Object>();
	
	//存放controller里的方法和路径的映射
	Map<String,Object> methodMap = new HashMap<String, Object>();
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("init...............");
		//1:扫描所有的class获取需要实例化的类		
		doScanPackage("com.zhjie.mySpring");
		//2:获取需要实例化的类
		doInstance();
		//3:ioc 将有controller层有Autowired注解的对象注入到controller
		doIoc();
		//4:获取controller里的路径和方法的映射
		methodMapping();
	}
	
	/**
	 * 
	 * <p>Title: doScanPackage</p>  
	 * <p>Description: 扫描所有类</p>  
	 * @param basePackage
	 */
	private void doScanPackage(String basePackage) {
		//获取class文件路径  如:file:/E:/Eclipse_Maven/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/spring-mvc/WEB-INF/classes/com/zhjie/mySpring/
		URL resource = this.getClass().getClassLoader().getResource("/" + basePackage.replaceAll("\\.", "/"));
		String fileStr = resource.getFile();
		System.out.println(fileStr);
		File file = new File(fileStr);
		String[] listFiles = file.list();
		//从根路径开始递归查找出所有.class文件
		for(String path: listFiles){
			File filePath = new File(fileStr + path);
			if(filePath.isDirectory()){
				doScanPackage(basePackage+"."+path);
			}else{
				classNames.add(basePackage+"."+filePath.getName());
			}
		}
	}
	/**
	 * 
	 * <p>Title: doInstance</p>  
	 * <p>Description: 实例化</p>
	 */
	private void doInstance() {
		if(classNames.size()<=0){
			System.out.println("没有扫描到类。。。。。。");
			return;
		}
		//通过反射实例化对象
		for(String classPath: classNames){
			String className = classPath.replace(".class", "");
			try {
				Class<?> clazz = Class.forName(className);
				//判断这个类是否有MyController注解
				if(clazz.isAnnotationPresent(MyController.class)){
					//获取注解对象
					MyRequestMapping myRequestMapping = clazz.getAnnotation(MyRequestMapping.class);
					//实例化
					Object instance = clazz.newInstance();
					beans.put(myRequestMapping.value(), instance);
				}else if(clazz.isAnnotationPresent(MyService.class)){
					//获取注解对象
					MyService myService = clazz.getAnnotation(MyService.class);
					//实例化
					Object instance = clazz.newInstance();
					beans.put(myService.value(), instance);
				}else{
					continue;
				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 
	 * <p>Title: doIoc</p>  
	 * <p>Description: IOC </p>
	 */
	private void doIoc() {
		if(beans.size()<=0){
			System.out.println("没有实例化的对象。。。");
			return;
		}
		for(String key : beans.keySet()){
			// 获取实例
			Object instance = beans.get(key);
			//根据实例获取class对象
			Class<?> clazz = beans.get(key).getClass();
			if(clazz.isAnnotationPresent(MyController.class)){
				//获取该对象所有定义的成员变量
				Field[] fields = clazz.getDeclaredFields();
				if(fields.length>0){
					for(Field field: fields){
						if(field.isAnnotationPresent(MyAutowired.class)){
							//获取成员变量的注解对象
							MyAutowired myAutowired = field.getAnnotation(MyAutowired.class);
							String value = myAutowired.value();
							// 由于此类成员变量设置为private,需要强行设置
							field.setAccessible(true);
							try {
								//注入对象实例
								field.set(instance, beans.get(value));
							} catch (IllegalArgumentException e) {
								e.printStackTrace();
							} catch (IllegalAccessException e) {
								e.printStackTrace();
							}
						}else{
							continue;
						}
					}
				}else{
					continue;
				}
			}
		}
		
	}
	/**
	 * 
	 * <p>Title: methodMapping</p>  
	 * <p>Description: 获取controller里的方法和路径的映射</p>
	 */
	private void methodMapping() {
		if(beans.isEmpty()){
			System.out.println("没有实例化对象。。。");
			return;
		}
		for(String key : beans.keySet()){
			//获取实例对象
			Object instance = beans.get(key);
			//获取class对象
			Class<?> clazz = instance.getClass();
			//判断类上是否controller层
			if(clazz.isAnnotationPresent(MyController.class)){
				//判断类上是否有MyRequestMapping注解
				MyRequestMapping myRequestMapping = clazz.getAnnotation(MyRequestMapping.class);
				//获取controller上的路径
				String clazzPath = myRequestMapping.value();
				//获取controller类的所有方法
				Method[] methods = clazz.getMethods();
				if(methods.length>0){
					for(Method method : methods){
						//判断方法上是否有MyRequestMapping注解
						if(method.isAnnotationPresent(MyRequestMapping.class)){
							//获取方法上的路径
							MyRequestMapping requestMapping = method.getAnnotation(MyRequestMapping.class);
							String methodPath = requestMapping.value();
							//key值 类上的路径加上发放上的路径,value值为方法对象
							methodMap.put(clazzPath+methodPath, method);
						}else{
							continue;
						}
					}
				}else{
					continue;
				}
			}else{
				continue;
			}
		}
	}
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//所有请求转发到post
		this.doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("doPost...");
		//获取请求地址   如:spring-mvc/user/query
		String uri = req.getRequestURI();
		//截取请求地址
		//首先获取项目上下文
		String context = req.getContextPath();
		//请求路径
		String path = uri.replace(context, "");
		//通过path获取需要执行的方法
		Method method = (Method) methodMap.get(path.substring(0,path.length()-1));
		//获取该类的实例化对象
		TestController controller = (TestController) beans.get("/" + path.split("/")[1]);
		// 处理参数		
		HandlerAdapterService ha = (HandlerAdapterService) beans.get("myHandlerAdapter"); 		
		Object[] args = ha.handle(req, resp, method, beans);				
				
		try {
			// 通过反射来实现方法的调用
			method.invoke(controller, args);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}	
	}
}

5:web.xml引入servlet

<servlet>
	<servlet-name>DispatcherServlet</servlet-name>
	<servlet-class>com.zhjie.mySpring.servlet.DispatcherServlet</servlet-class>
	<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>DispatcherServlet</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>

6:使用策略模式来解析参数

HandlerAdapterService

package com.zhjie.mySpring.handlerAdapter;

import java.lang.reflect.Method;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 
 * <p>Title: HandlerAdapterService</p>  
 * <p>Description: 参数处理接口</p>  
 * @author zhjie  
 * @date 2020年2月22日
 */
public interface HandlerAdapterService {

	public Object[] handle(HttpServletRequest req, HttpServletResponse resp,
			Method method, Map<String, Object> beans);
}

MyHandlerAdapter

package com.zhjie.mySpring.handlerAdapter;


import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhjie.mySpring.annotation.MyService;

import com.zhjie.mySpring.argumentParsing.ArgumentParsing;
 
/**
 * 
 * <p>Title: MyHandlerAdapter</p>  
 * <p>Description: 参数处理</p>  
 * @author zhjie  
 * @date 2020年2月23日
 */
@MyService("myHandlerAdapter")
public class MyHandlerAdapter implements HandlerAdapterService {
 
	/**
	 * 参数处理
	 * method 方法对象
	 * beans  存放所有实例化对象
	 */
	public Object[] handle(HttpServletRequest req, HttpServletResponse resp,
			Method method, Map<String, Object> beans) {

		//获取方法中定义的参数
		Class<?>[] paramClazzs = method.getParameterTypes();
		
		// 定义一个返回参数的结果集
		Object[] args = new Object[paramClazzs.length];
		//Object[] args = {req, resp, "zhjie", "18"};

		// 定义一个ArgumentResolver实现类的Map
		Map<String, Object> argumentResolvers = getBeansOfType(beans, ArgumentParsing.class);
		//定义参数索引
		int paramIndex = 0;
		//定义数组下标索引
		int i = 0; 
		// 开始处理参数
		for(Class<?> paramClazz: paramClazzs) {
			//哪个参数对应了哪个参数解析类,用策略模式来找
            for(Map.Entry<String, Object> entry : argumentResolvers.entrySet()) {
                ArgumentParsing ar = (ArgumentParsing)entry.getValue();
                if (ar.support(paramClazz, paramIndex, method)) {
                    args[i++] = ar.argumentResolver(req,
                            resp,
                            paramClazz,
                            paramIndex,
                            method);
                }
            }
            paramIndex++;
		}
		return args;
	}

 

	/**
	 * 从beans中获取所有实现ArgumentResolver接口类的实例
	 * @param beans IOC容器中全部的bean
	 * @param intfType 定义的ArgumentResolver类
	 * @return
	 */
	private Map<String, Object> getBeansOfType(Map<String, Object> beans,
			Class<ArgumentParsing> intfType) {
		Map<String, Object> resultBeans = new HashMap<String, Object>();
		for(Map.Entry<String, Object> map: beans.entrySet()) {
			// 获取满足ArgumentResolver接口的bean
			Class<?>[] intfs = map.getValue().getClass().getInterfaces();
			if(intfs != null && intfs.length >0) {
				for(Class<?> intf: intfs) {
					// 将满足的bean存储在resultBeans中
					if(intf.isAssignableFrom(intfType)) {
						resultBeans.put(map.getKey(), map.getValue());
					}
				}
			}
		}
		return resultBeans;
	}
}

ArgumentParsing

package com.zhjie.mySpring.argumentParsing;

import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface ArgumentParsing {

	/**
	 * 判断当前的类是继承于ArgumentResolver
	 * @param type 当前参数注解的类对象
	 * @param paramIndex 参数下标
	 * @param method 当前的方法
	 * @return
	 */
	public boolean support(Class<?> type, int paramIndex, Method method);

	/**
	 * 
	 * @param request
	 * @param response
	 * @param type
	 * @param paramIndex
	 * @param method
	 * @return
	 */
	public Object argumentResolver(HttpServletRequest request,
	            HttpServletResponse response, Class<?> type, 
	            int paramIndex,
	            Method method);

}

HttpServletRequestArgumentParsing

package com.zhjie.mySpring.argumentParsing;

import java.lang.reflect.Method;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zhjie.mySpring.annotation.MyService;

@MyService("httpServletRequestArgumentParsing")
public class HttpServletRequestArgumentParsing implements ArgumentParsing {

	public boolean support(Class<?> type, int paramIndex, Method method) {
		return ServletRequest.class.isAssignableFrom(type);
	}

	public Object argumentResolver(HttpServletRequest request,
			HttpServletResponse response, Class<?> type, int paramIndex,
			Method method) {
		return request;
	}

 

}

HttpServletResponseArgumentParsing

package com.zhjie.mySpring.argumentParsing;

import java.lang.reflect.Method;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zhjie.mySpring.annotation.MyService;

@MyService("httpServletResponseArgumentParsing")
public class HttpServletResponseArgumentParsing implements ArgumentParsing {
	public boolean support(Class<?> type, int paramIndex, Method method) {
		return ServletResponse.class.isAssignableFrom(type);
	}

	public Object argumentResolver(HttpServletRequest request,
			HttpServletResponse response, Class<?> type, int paramIndex,
			Method method) {
		return response;
	}

 

}

RequestParamArgumentParsing

package com.zhjie.mySpring.argumentParsing;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhjie.mySpring.annotation.MyRequestParam;
import com.zhjie.mySpring.annotation.MyService;

@MyService("requestParamArgumentParsing")
public class RequestParamArgumentParsing implements ArgumentParsing {

	public boolean support(Class<?> type, int paramIndex, Method method) {
		// type = class java.lang.String
		// @MyRequestParam("name")String name
		//获取当前方法的参数
		Annotation[][] an = method.getParameterAnnotations();
		Annotation[] paramAns = an[paramIndex];
		for (Annotation paramAn : paramAns) {
        	//判断传进的paramAn.getClass()是不是 MyRequestParam 类型
        	if (MyRequestParam.class.isAssignableFrom(paramAn.getClass())) {
                return true;
            }
        }
		return false;
	}

	public Object argumentResolver(HttpServletRequest request,
			HttpServletResponse response, Class<?> type, int paramIndex,
			Method method) {
		//获取当前方法的参数
		Annotation[][] an = method.getParameterAnnotations();
		Annotation[] paramAns = an[paramIndex];
		for (Annotation paramAn : paramAns) {
        	//判断传进的paramAn.getClass()是不是 MyRequestParam 类型
        	if (MyRequestParam.class.isAssignableFrom(paramAn.getClass())) {
        		MyRequestParam cr = (MyRequestParam) paramAn;
                String value = cr.value();
                return request.getParameter(value);
            }
        }
		return null;
	}

 

}

7:启动项目

浏览器访问地址:http://localhost:8080/spring-mvc/user/query/?name=zhjie&age=18

8:运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值