手写SpringMVC

在某课堂学习到手写SpringMVC后,用来记录一下自己的学习过程,加深一下印象。

首先我们得有一个思路:

1.我们要先对一个基本包进行扫描,扫描里面的子包以及子包下的类(可以将扫描到的包的路径保存在list中)

2.接着就是对扫描的包进行实例化(可以新建一个map<String,Object>来保存bean的id和实例)

3.依赖注入,把service层的实例注入到controller(需要利用反射获取对象的field,完成注入)

4.当上述完成之后,我们需要有一个path和method的映射关系,简单的来讲,就是根据uri的不同来调用不同的method,所以这时我们还需要一个map来保存这种映射关系

5.耐心、耐心、还是耐心!!!!!!

好了,简单的介绍完毕了,我们开始实现!

新建maven项目,打包方式为war,加入新建目录,并加入web.xml文件,maven中加入servlet的依赖,开始代码。

先来两张包的顺序图,这样看上去会更有条理。

一.我们先定义自己的注解,在springmvc中,我们常用的就是@Controller @Service@Repository@RequestMapping@Responsebody@AutoWired@Qualifier......

所以我们先自己定义注解代码如下,因为

package com.enjoy.james.annotation;

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

@Target({java.lang.annotation.ElementType.TYPE}) //作用范围:用在接口或类上
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Documented//明该注解将被包含在javadoc中    @Inherited:说明子类可以继承父类中的该注解
public @interface EnjoyController {
    String value() default "";
}


package com.enjoy.james.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 EnjoyQualifier {
    String value() default "";
}

package com.enjoy.james.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 EnjoyRequestHeader {
    String value() default "";
}

package com.enjoy.james.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 EnjoyRequestMapping {
	//路径EnjoyRequestMapping(value)
    String value() default "";
}

package com.enjoy.james.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 EnjoyRequestParam {
    String value() default "";
}

package com.enjoy.james.annotation;

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

@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnjoyService {
    String value() default "";
}

二.自定义注解完成之后,我们就可以像springmvc一样使用自己定义的注解了,但是这个时候,我们还是没有解析器的,所以是没有效果的,先写代码

新建一个controller类

package com.enjoy.james.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;

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

import com.enjoy.james.annotation.EnjoyController;
import com.enjoy.james.annotation.EnjoyQualifier;
import com.enjoy.james.annotation.EnjoyRequestHeader;
import com.enjoy.james.annotation.EnjoyRequestMapping;
import com.enjoy.james.annotation.EnjoyRequestParam;
import com.enjoy.james.service.JamesService;

@EnjoyController
@EnjoyRequestMapping("/james")
public class JamesController {
    
    @EnjoyQualifier("JamesServiceImpl")
    private JamesService jamesService;
    
    @EnjoyRequestMapping("/query")
    public void query(HttpServletRequest request, HttpServletResponse response,
            @EnjoyRequestParam("name") String name,
            @EnjoyRequestParam("age") String age) {
        
        try {
            PrintWriter pw = response.getWriter();
            String result = jamesService.query(name,age);
            pw.write(result);
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    @EnjoyRequestMapping("/insert")
    public void insert(HttpServletRequest request,
            HttpServletResponse response) {
        try {
            PrintWriter pw = response.getWriter();
            String result = jamesService.insert("0000");
            
            pw.write(result);
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    @EnjoyRequestMapping("/update")
    public void update(HttpServletRequest request,
            HttpServletResponse response, String param) {
        try {
            PrintWriter pw = response.getWriter();
            String result = jamesService.update(param);
            
            pw.write(result);
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

接下来就是新建一个service接口,再新建一个类去实现这个接口,为了便于观察,我就放在一起了

//新建的一个接口,用来模拟数据库的增删改查操作
package com.enjoy.james.service;

public interface JamesService {
    
    String query(String name, String age);
    
    String insert(String param);
    
    String update(String param);
}
//再新建一个类去实现这个接口
package com.enjoy.james.service.impl;

import com.enjoy.james.annotation.EnjoyService;
import com.enjoy.james.service.JamesService;

@EnjoyService("JamesServiceImpl")
public class JamesServiceImpl implements JamesService {
    
    public String query(String name, String age) {
        
        return "{name="+name+",age="+age+"}";
    }
    
    public String insert(String param) {
        // TODO Auto-generated method stub
        return  "insert successful.....";
    }
    
    public String update(String param) {
        return "update successful.....";
    }
    
}

三.继承HttpServlet,并重写部分的方法,这个时候,写入自己的逻辑,并根据自己的注解对bean进行操作处理

package com.enjoy.james.servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
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 java.util.Properties;

import javax.servlet.Servlet;
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.enjoy.james.annotation.EnjoyController;
import com.enjoy.james.annotation.EnjoyQualifier;
import com.enjoy.james.annotation.EnjoyRequestMapping;
import com.enjoy.james.annotation.EnjoyService;
import com.enjoy.james.controller.JamesController;
import com.enjoy.james.handlerAdapter.HandlerAdapterService;

/**
 * Servlet implementation class DispatcherServlet
 */
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>();

	Map<String, Object> handlerMap = new HashMap<String, Object>();

	Properties prop = null;

	private static String HANDLERADAPTER = "jamesHandlerAdapter";

	/**
	 * Default constructor.
	 */
	public DispatcherServlet() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see Servlet#init(ServletConfig)
	 */
	public void init(ServletConfig config) throws ServletException {
		// 1、我们要根据一个基本包进行扫描,扫描里面的子包以及子包下的类
		scanPackage("com.enjoy");

		for (String classname : classNames) {
			System.out.println(classname);
		}

		// 2、我们肯定是要把扫描出来的类进行实例化
		instance();
		for (Map.Entry<String, Object> entry : beans.entrySet()) {
			System.out.println(entry.getKey() + ":" + entry.getValue());
		}

		// 3、依赖注入,把service层的实例注入到controller
		ioc();

		// 4、建立一个path与method的映射关系
		HandlerMapping();
		for (Map.Entry<String, Object> entry : handlerMap.entrySet()) {
			System.out.println(entry.getKey() + ":" + entry.getValue());
		}
		/*
		 * InputStream is = this.getClass()
		 * .getResourceAsStream("/config/properties/spring.properties"); prop =
		 * new Properties(); try { prop.load(is); } catch (IOException e) {
		 * e.printStackTrace(); }
		 */

	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doPost(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//获取到请求路径   /james-springmvc/james/query
		String uri = request.getRequestURI();

		String context = request.getContextPath();
		//将  "/james-springmvc/james/query"  去掉"/james-springmvc"
		String path = uri.replace(context, "");
		//根据请求路径来获取要执行的方法 
		Method method = (Method) handlerMap.get(path);
		//拿到控制类
		JamesController instance = (JamesController) beans.get("/" + path.split("/")[1]);
		//处理器
		HandlerAdapterService ha = (HandlerAdapterService) beans.get(HANDLERADAPTER);

		
		/*
		 * @RequestMapping("/order")
		 * order(@RequestBody String params, @RequestHeader @RequestParam String param1){//参数有多种类型接收方式
		 * }
		 */
		
		
		
		
		Object[] args = ha.hand(request, response, method, beans);

		try {
			method.invoke(instance, args);
			// method.invoke(instance, new
			// Object[]{request,response,null});//拿参数
			
			/*如果有多个参数类型,就得这样写了(可用策略模式,省去以下代码)
			 * if(ParamType == HttpServletRequest){
				
			}else if(ParamType == @RquestHeader){
				
			}else
			*用策略模式实现(把粒度控制得更细),新建 JamesHandlerAdapter
			*/
			
			
			
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	private void HandlerMapping() {
		if (beans.entrySet().size() <= 0) {
			System.out.println("没有类的实例化!");
			return;
		}

		for (Map.Entry<String, Object> entry : beans.entrySet()) {
			Object instance = entry.getValue();

			Class<?> clazz = instance.getClass();
			// 拿所有Controller的类
			if (clazz.isAnnotationPresent(EnjoyController.class)) {
				//@com.enjoy.james.annotation.EnjoyRequestMapping(value=/james)
				EnjoyRequestMapping requestMapping = (EnjoyRequestMapping) clazz
						.getAnnotation(EnjoyRequestMapping.class);
				// 获取Controller类上面的EnjoyRequestMapping注解里的请求路径
				String classPath = requestMapping.value();
				// 获取控制类里的所有方法
				Method[] methods = clazz.getMethods();
				// 获取方法上的EnjoyRequestMapping设置的路径,与方法名建立映射关系
				for (Method method : methods) {
					//判断哪些方法上使用EnjoyRequestMapping路径注解
					if (method.isAnnotationPresent(EnjoyRequestMapping.class)) {
						//@com.enjoy.james.annotation.EnjoyRequestMapping(value=/query)
						EnjoyRequestMapping methodrm = (EnjoyRequestMapping) method
								.getAnnotation(EnjoyRequestMapping.class);
						String methodPath = methodrm.value();
						// 把方法上与路径建立映射关系( /james/query--->public void com.enjoy.james.controller.JamesController.query )
						handlerMap.put(classPath + methodPath, method);
					} else {
						continue;
					}
				}
			}
		}
	}

	// 初始化IOC容器
	private void ioc() {

		if (beans.entrySet().size() <= 0) {
			System.out.println("没有类的实例化!");
			return;
		}
		//将实例化好的bean遍历,
		for (Map.Entry<String, Object> entry : beans.entrySet()) {
			Object instance = entry.getValue();//获取bean实例

			Class<?> clazz = instance.getClass();//获取类,用来判断类里声明了哪些注解(主要是针对控制类里的判断,比如使用了@Autowired  @Qualifier,对这些注解进行解析)
			//判断该类是否使用了EnjoyController注解
			if (clazz.isAnnotationPresent(EnjoyController.class)) {
				Field[] fields = clazz.getDeclaredFields();// 拿到类里面的属性
				// 判断是否声明了自动装配(依赖注入)注解,比如@Autrowired @Qualifier
				for (Field field : fields) {
					if (field.isAnnotationPresent(EnjoyQualifier.class)) {
						EnjoyQualifier qualifier = (EnjoyQualifier) field.getAnnotation(EnjoyQualifier.class);
						//拿到@EnjoyQualifier("JamesServiceImpl")里的指定要注入的bean名字"JamesServiceImpl"
						String value = qualifier.value();

						field.setAccessible(true);
						try {
							// 从MAP容器中获取"JamesServiceImpl"对应的bean,并注入实例控制层bean,解决依赖注入
							field.set(instance, beans.get(value));
						} catch (IllegalArgumentException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					} else {
						continue;
					}
				}
			} else {
				continue;
			}
		}
	}

	private void instance() {
		if (classNames.size() <= 0) {
			System.out.println("包扫描失败!");
			return;
		}
		//遍历扫描到的class文件,将需要实例化的类(加了注解的类)进行反射创建对象(像注解就不需要实例化)
		for (String className : classNames) {
			// com.enjoy.james.service.impl.JamesServiceImpl.class
			String cn = className.replace(".class", "");

			try {
				Class<?> clazz = Class.forName(cn);//拿到class类,用来实例化
				// 将扫描到的类,获取类名,并判断是否标记了EnjoyController注解
				if (clazz.isAnnotationPresent(EnjoyController.class)) {
					EnjoyController controller = (EnjoyController) clazz.getAnnotation(EnjoyController.class);
					Object instance = clazz.newInstance();
					//获取对应的请求路径"/james"
					EnjoyRequestMapping requestMapping = (EnjoyRequestMapping) clazz
							.getAnnotation(EnjoyRequestMapping.class);
					String rmvalue = requestMapping.value();//得到"/james"请求路径
					//用路径做为key,对应value为实例化对象
					beans.put(rmvalue, instance);
				} else if (clazz.isAnnotationPresent(EnjoyService.class)) {
					//获取当前clazz类的注解(通过这个注解可得到当前service的id)  @com.enjoy.james.annotation.EnjoyService(value=JamesServiceImpl)
					EnjoyService service = (EnjoyService) clazz.getAnnotation(EnjoyService.class);
					Object instance = clazz.newInstance();
					//put(JamesServiceImpl,instance)
					beans.put(service.value(), instance);
				} else {
					continue;
				}
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	private void scanPackage(String basePackage) {
		//扫描编译好的类路径下所有的类
		URL url = this.getClass().getClassLoader().getResource("/" + replaceTo(basePackage));

		String fileStr = url.getFile();

		File file = new File(fileStr);
		//拿到所有类com.enjoy下的james文件夹
		String[] filesStr = file.list();

		for (String path : filesStr) {
			File filePath = new File(fileStr + path);//扫描com.enjoy.james下的所有class类

			//递归调用扫描,如果是路径,继续扫描
			if (filePath.isDirectory()) {
				// com.enjoy.james
				scanPackage(basePackage + "." + path);
			} else {
				classNames.add(basePackage + "." + filePath.getName());//如果是class文件则加入List集合(待生成bean)
			}
		}
	}

	private String replaceTo(String basePackage) {
		return basePackage.replaceAll("\\.", "/");
	}

}

四.当根据不同的uri调用不同的方法去执行的时候,这个时候有一个问题就是方法中会有@RequestParam注解,我们要获取自己定义的注解的请求变量的信息,也就是获取到参数的列表,再调用方法,这个时候我们使用策略设计模式来完成。

//新建一个接口
package com.enjoy.james.argumentResolver;

import java.lang.reflect.Method;

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

public interface ArgumentResolver {
    
    public boolean support(Class<?> type, int paramIndex, Method method);
    
    //参数解析方法
    public Object argumentResolver(HttpServletRequest request,
            HttpServletResponse response, Class<?> type, 
            int paramIndex,//参数索引下坐标,有很多注解,你得知道是哪个参数的注解,每个参数的索引顺序不一样
            Method method);
}


//接下来是三个实现类,用来判断参数的类型
package com.enjoy.james.argumentResolver;

import java.lang.reflect.Method;

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

import com.enjoy.james.annotation.EnjoyService;

@EnjoyService("httpServletRequestArgumentResolver")
public class HttpServletRequestArgumentResolver implements ArgumentResolver {
	//判断传进来的参数是否为request
    public boolean support(Class<?> type, int paramIndex, Method method) {
        return ServletRequest.class.isAssignableFrom(type);
    }
    如果返回的参数是request,则直接返回
    public Object argumentResolver(HttpServletRequest request,
            HttpServletResponse response, Class<?> type, int paramIndex,
            Method method) {
        return request;
    }
    
}

package com.enjoy.james.argumentResolver;

import java.lang.reflect.Method;

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

import com.enjoy.james.annotation.EnjoyService;

@EnjoyService("httpServletResponseArgumentResolver")
public class HttpServletResponseArgumentResolver implements ArgumentResolver {
    //判断传进来的参数是否为response
    public boolean support(Class<?> type, int paramIndex, Method method) {
        return ServletResponse.class.isAssignableFrom(type);
    }
    //如果返回的参数是response,则直接返回
    public Object argumentResolver(HttpServletRequest request,
            HttpServletResponse response, Class<?> type, int paramIndex,
            Method method) {
        return response;
    }
    
}
package com.enjoy.james.argumentResolver;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

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

import com.enjoy.james.annotation.EnjoyRequestParam;
import com.enjoy.james.annotation.EnjoyService;

@EnjoyService("requestParamArgumentResolver")
//解析声明注解为RequestParam, 获取注解的值
public class RequestParamArgumentResolver implements ArgumentResolver {
	//判断传进来的参数是否为EnjoyRequestParam
    public boolean support(Class<?> type, int paramIndex, Method method) {
        
        Annotation[][] an = method.getParameterAnnotations();
        
        Annotation[] paramAns = an[paramIndex];
        
        for (Annotation paramAn : paramAns) {
        	//判断传进的paramAn.getClass()是不是 EnjoyRequestParam 类型
        	if (EnjoyRequestParam.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) {
            if (EnjoyRequestParam.class.isAssignableFrom(paramAn.getClass())) {
            	EnjoyRequestParam rp = (EnjoyRequestParam)paramAn;
                
                String value = rp.value();
                return request.getParameter(value);
            }
        }
        
        return null;
    }
    
}
//同样,对参数进行类型判断和处理的时候,先新建一个接口
package com.enjoy.james.handlerAdapter;

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//由JamesHandlerAdapter实现
public interface HandlerAdapterService {
    
    public Object[] hand(HttpServletRequest request,//拿request请求里的参数
            HttpServletResponse response,//
            Method method,
            Map<String, Object> beans);
}

//再新建一个实现类,负责类型判断和处理

package com.enjoy.james.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.enjoy.james.annotation.EnjoyService;
import com.enjoy.james.argumentResolver.ArgumentResolver;

@EnjoyService("jamesHandlerAdapter")
public class JamesHandlerAdapter implements HandlerAdapterService {
    //对method方法里的参数进行处理
    public Object[] hand(HttpServletRequest request,//需要传入request,拿请求的参数
            HttpServletResponse response, Method method,//执行的方法,可以拿到当前待执行的方法有哪些参数
            Map<String, Object> beans) {
        //拿到当前待执行的方法有哪些参数
        Class<?>[] paramClazzs = method.getParameterTypes();
        //根据参数的个数,new 一个参数的数组,将方法里的所有参数赋值到args来
        Object[] args = new Object[paramClazzs.length];
        
        //1、要拿到所有实现了ArgumentResolver这个接口的实现类
        Map<String, Object> argumentResolvers = getBeansOfType(beans,
                ArgumentResolver.class);
        
        int paramIndex = 0;
        int i = 0;
        //对每一个参数进行循环,每个参数都有特殊处理(比如RequestParam的处理类为 RequestParamArgumentResolver )
        for (Class<?> paramClazz : paramClazzs) {
        	//哪个参数对应了哪个参数解析类,用策略模式来找
            for (Map.Entry<String, Object> entry : argumentResolvers.entrySet()) {
                ArgumentResolver ar = (ArgumentResolver)entry.getValue();
                
                if (ar.support(paramClazz, paramIndex, method)) {
                    args[i++] = ar.argumentResolver(request,
                            response,
                            paramClazz,
                            paramIndex,
                            method);
                }
            }
            paramIndex++;
        }
        
        return args;
    }
    //获取实现了ArgumentResolver接口的所有实例(其实就是每个参数的注解实例)
    private Map<String, Object> getBeansOfType(Map<String, Object> beans,//所有bean
            Class<?> intfType) //类型的实例
    {
        
        Map<String, Object> resultBeans = new HashMap<String, Object>();
        
        for (Map.Entry<String, Object> entry : beans.entrySet()) {
        	//拿到实例-->反射对象-->它的接口(接口有多实现,所以为数组)
            Class<?>[] intfs = entry.getValue().getClass().getInterfaces();
            
            if (intfs != null && intfs.length > 0) {
                for (Class<?> intf : intfs) {
                	//接口的类型与传入进来的类型一样,把实例加到resultBeans里来
                	if (intf.isAssignableFrom(intfType)) {
                        resultBeans.put(entry.getKey(), entry.getValue());
                    }
                }
            }
        }
        
        return resultBeans;
    }
    
}

第四步简单来说就是我先获取方法的所有参数,然后我将刚才实现的三个类保存在map容器中,所以是双重for循环,第一层for是获取到的第n个方法的参数,第2层for是根据这个参数进行匹配,看是属于这三个类返回的哪种类型

然后我们的逻辑代码就已经完成了

最后,在web.xml文件中配置servlet信息

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
  	<servlet-name>DispatcherServlet</servlet-name>
  	<display-name>DispatcherServlet</display-name>
  	<description></description>
  	<servlet-class>com.enjoy.james.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>
</web-app>

我们在webapp目录下,新建一个index.jsp文件,用来启动服务后进行测试

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>utf-8</title>
</head>
<body>

<form action="james/query">
	姓名:<input type="text" name="name" id="name"/>
	年龄:<input type="text" name="age" id="id"/>
	<input type="submit" value="提交"/>
</form>
</body>
</html>

好了,配置已经完成,先进行测试

 

提交姓名和年龄后

如图,说明我们手写的springmvc没有错误,但还是有很多不足的,这里只做简单的讲解。

谢谢大家!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值