手写实现springMVC框架

 

项目目录结构:

手写实现springMVC框架_第1张图片

maven引入servlet包


	    javax.servlet
	    javax.servlet-api
	    3.0.1
	    provided
	  

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;
	/**
	 * 
	 * 

Title: query

*

Description: 查询

* @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;
/**
 * 
 * 

Title: DispatcherServlet

*

Description: servlet核心处理类

* @author zhjie * @date 2020年2月23日 */ public class DispatcherServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; // 存在当前加载的所有的类 List classNames = new ArrayList(); // 存放实例化对象 Map beans = new HashMap(); //存放controller里的方法和路径的映射 Map methodMap = new HashMap(); @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(); } /** * *

Title: doScanPackage

*

Description: 扫描所有类

* @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()); } } } /** * *

Title: doInstance

*

Description: 实例化

*/ 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(); } } } /** * *

Title: doIoc

*

Description: IOC

*/ 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; } } } } /** * *

Title: methodMapping

*

Description: 获取controller里的方法和路径的映射

*/ 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


	DispatcherServlet
	com.zhjie.mySpring.servlet.DispatcherServlet
	0


	DispatcherServlet
	/

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;
/**
 * 
 * 

Title: HandlerAdapterService

*

Description: 参数处理接口

* @author zhjie * @date 2020年2月22日 */ public interface HandlerAdapterService { public Object[] handle(HttpServletRequest req, HttpServletResponse resp, Method method, Map 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;
 
/**
 * 
 * 

Title: MyHandlerAdapter

*

Description: 参数处理

* @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 beans) { //获取方法中定义的参数 Class[] paramClazzs = method.getParameterTypes(); // 定义一个返回参数的结果集 Object[] args = new Object[paramClazzs.length]; //Object[] args = {req, resp, "zhjie", "18"}; // 定义一个ArgumentResolver实现类的Map Map argumentResolvers = getBeansOfType(beans, ArgumentParsing.class); //定义参数索引 int paramIndex = 0; //定义数组下标索引 int i = 0; // 开始处理参数 for(Class paramClazz: paramClazzs) { //哪个参数对应了哪个参数解析类,用策略模式来找 for(Map.Entry 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 getBeansOfType(Map beans, Class intfType) { Map resultBeans = new HashMap(); for(Map.Entry 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:运行结果

手写实现springMVC框架_第2张图片

你可能感兴趣的:(java,spring,java)