SpringMVC simple source code implementation

SpringMVC simple source implementation
source code Download

Procedural framework
Here Insert Picture Description
web.xml configuration
to start the servlet when you want the point to note here that all requests by, it is set to /, as well as set up, let the program loadHere Insert Picture Description

pom.xml introduced only servlet jar package
Here Insert Picture Description
annotations categories: simple imitation modeled springmvc make annotations, each annotation is only a five value method, in addition to the different positions defined annotation, no other differences
Here Insert Picture Description

Controller class source code and custom control class annotated with

@MyController
@MyRequestMapping("/my")
public class TestController{
	@MyAutowired(value = "testService")
	private TestService testService;

	@MyRequestMapping("/ok")
	public void updateUser(HttpServletRequest request,HttpServletResponse response,
						@MyRequestParam("name") String name,
						@MyRequestParam("password") String password){
		String user = testService.updateUser(name,password);
		try {
			response.getWriter().write(user);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	@MyRequestMapping("/no")
	public void noUser(HttpServletRequest request,HttpServletResponse response,
						@MyRequestParam("name") String name,
						@MyRequestParam("password") String password){
		String user = testService.updateUser(name,password);
		try {
			response.getWriter().write(user);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Source Service classes and custom classes using annotations

import com.ys.annotation.MyService;

@MyService("testService")
public class TestService {
	public String updateUser(String name, String password){
		return "name:"+name+"password:"+password;
	}
}


Servlet class core functionality

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
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.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ys.annotation.MyAutowired;
import com.ys.annotation.MyController;
import com.ys.annotation.MyRequestMapping;
import com.ys.annotation.MyRequestParam;
import com.ys.annotation.MyService;
import com.ys.controller.TestController;


public class TestServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	//用来存储class文件路径
	List<String> classNames = new ArrayList<String>();
	//用来存储controller类对象
	Map<String,Object> beans = new HashMap<String,Object>();
	//创建一个存储autowire的集合
	Map<String,Object> handlerMap = new HashMap<String,Object>();
	
	//tomcat启动扫描controller,service
	//通过反射实例化对象
	//处理autowired
	//path-method
	@Override
	public void init() throws ServletException {
		//扫描包
		scanPackage("com.ys");
		//实例化类对象
		instance();
		//扫描MyAutowired
		doAutowired();
		//处理requestMapping
		UrlHanding();
		test();
	}
	
	
	private void test() {
		System.out.println("---------------------------");
		for (String name : classNames) {
			System.out.println(name);
		}
		
		System.out.println("beans-------------------------------------");
		
		for (String key : beans.keySet()) {
			System.out.println("key:"+key+"\t"+"value:"+beans.get(key));
		}
		System.out.println("handlerMap--------------------------------");
		for (String key : handlerMap.keySet()) {
			System.out.println("key:"+key+"\t"+"value:"+handlerMap.get(key));
		}
	}


	private void UrlHanding() {
		// 遍历容器里的bean
		for (Map.Entry<String, Object> entry : beans.entrySet()) {
			// 获取到map中的对象
			Object instance = entry.getValue();
			// 获取到当前类的路径,可以利用反射对对象进行实例化
			Class<?> clazz = instance.getClass();
			// 注意:在controller下使用autowired注解
			if (clazz.isAnnotationPresent(MyController.class)) {
				//MyController类上会存在MyRequestMapping注解
				MyRequestMapping map1 = clazz.getAnnotation(MyRequestMapping.class);
				//获取类路径,类上的值,需要和方法上的进行拼接
				String classPath = map1.value();
				//获取对象所有的方法
				Method[] methods = clazz.getMethods();
				//遍历方法
				for (Method method : methods) {
					//判断方法上是否有注解
					if(method.isAnnotationPresent(MyRequestMapping.class)){
						//获取方法上的注解值
						MyRequestMapping map2 = method.getAnnotation(MyRequestMapping.class);
						//获取注解上的value
						String methodPath = map2.value();
						//拼接,并以路径为key,方法名为value存到map中
						handlerMap.put(classPath+methodPath, method);
					}else{
						continue;
					}
				}
			}else{
				continue;
			}
		}
	}

	private void doAutowired() {
		//遍历容器里的bean
		for (Map.Entry<String, Object> entry: beans.entrySet()) {
			//获取到map中的value值
			Object instance = entry.getValue();
			//获取到当前类的路径,可以利用反射对对象进行实例化
			Class<?> clazz = instance.getClass();
			//注意:在controller下使用autowired注解
			if(clazz.isAnnotationPresent(MyController.class)){
				//获取控制层中所有的属性
				Field[] fields = clazz.getDeclaredFields();
				//遍历属性
				for (Field field : fields) {
					//判断属性上是否有Autowired注解
					if(field.isAnnotationPresent(MyAutowired.class)){
						//获取属性上的注解
						MyAutowired ea = field.getAnnotation(MyAutowired.class);
						//获取注解值
						String key = ea.value();
						//根据注解值,获取bean的类路径
						//service上的值和autowired的值相同
						Object ins = beans.get(key);
						//暴力破解获取私有值
						field.setAccessible(true);
						
						
						//
						try {
							field.set(instance, ins);
						} catch (IllegalArgumentException e) {
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							e.printStackTrace();
						}
					}else{//如果有dao层,加一个else if
						continue;
					}
				}
			}
		}
	}


	private void instance() {
		for (String className : classNames) {
			//com.ys.xxx.xxx.class
			//截取掉当前的.class后缀
			String cn = className.replace(".class", "");
			try {
				//获取到当前类的路径,可以利用反射对对象进行实例化
				Class<?> clazz = Class.forName(cn);
				//判断当前类里是否声明了类上注解
				if(clazz.isAnnotationPresent(MyController.class)){
					//控制类
					Object instance = clazz.newInstance();
					//获取类上的requestmapping注解
					MyRequestMapping map1 = clazz.getAnnotation(MyRequestMapping.class);
					//获取注解的值
					String key = map1.value();
					//将注解上的值作为key值存入到map集合中
					beans.put(key, instance);
				}else if(clazz.isAnnotationPresent(MyService.class)){
					//业务类
					Object instance = clazz.newInstance();
					//获取类上的Myservice注解
					MyService map2 = clazz.getAnnotation(MyService.class);
					//获取注解的值
					String key = map2.value();
					//将注解上的值作为key值存入到map集合中
					beans.put(key, instance);
				}else{
					continue;
				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}


	//扫描所有的基础包下的文件,将所有的类路径存在list集合下
	private void scanPackage(String basepackage) {
		//将路径中的.换成java认识的/
		URL url = this.getClass().getClassLoader().getResource("/"+basepackage.replaceAll("\\.", "/"));
		
		
		//E:workpace/abc
		String fileStr = url.getFile();
		//找到基础包路径
		File file = new File(fileStr);
		//获取该文件下所有的文件
		String[] fileNames = file.list();
		//只需要文件,所以遍历
		for (String path : fileNames) {
			//fileStr+filename  基础包路径拼接上对应路径名
			File filePath = new File(fileStr+path);
			//判断是否是文件
			if(filePath.isDirectory()){
				//是文件的话递归直到是文件为止
				scanPackage(basepackage+"."+path);
			}else{
				//com.ys.xxx.xxx.class
				classNames.add(basepackage+"."+filePath.getName());
			}
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//  http://ip+端口/项目名/请求路径
		//  uri获取得是            /项目名/请求路径
		String uri = request.getRequestURI();
		System.out.println("uri:"+uri);
		//获取工程名
		String contextPath = request.getContextPath();
		System.out.println("contextPath:"+contextPath);
		//剪切   /请求路径
		String path = uri.replace(contextPath, ""); 
		System.out.println("path:"+path);
		//获取handlerMap中的方法
		Method method = (Method)handlerMap.get(path);
		System.out.println("method:"+method);
		//不足:进行了强转:因为只有一个controller类,所以,多个情况使用Object类型,具体使用时进行强转
		TestController instance = (TestController)beans.get("/"+path.split("/")[1]);
		System.out.println(instance);
		//参数处理
		Object[] args = hand(request, response, method);
//		调用方法
		try {
			method.invoke(instance, args);
		} 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 static Object[] hand(HttpServletRequest request, HttpServletResponse response,Method method){
		//拿到当前执行方法有哪些参数
		Class<?>[] paramClazzs = method.getParameterTypes();
		//根据参数个数,new一个参数的数组,将方法里的所有参数赋值大agrs中
		Object[] args = new Object[paramClazzs.length];
		
		int args_i = 0;
		int index = 0;
		for (Class<?>  paramClazz : paramClazzs) {
			if(ServletRequest.class.isAssignableFrom(paramClazz)){
				args[args_i++] = request;
			}
			if(ServletResponse.class.isAssignableFrom(paramClazz)){
				args[args_i++] = response;
			}
			
			Annotation[] paramAns = method.getParameterAnnotations()[index];
			if(paramAns.length>0){
				for (Annotation paramAn : paramAns) {
					if(MyRequestParam.class.isAssignableFrom(paramAn.getClass())){
						MyRequestParam mp = (MyRequestParam) paramAn;
						//找到注解里的name和password
						args[args_i++] = request.getParameter(mp.value());
					}
				}
			}
			index++;
		}
		return args;
	}
}



init method of the servlet test Test: traversal has completed the storage vessel results
Here Insert Picture Description
final operation result
Here Insert Picture Description

Guess you like

Origin blog.csdn.net/yang134679/article/details/88866926