手写SpringMVC IOC,让自己爽一爽(二)

手写SpringMVC IOC,让自己爽一爽(二)

下面开始进入第二节,手写DispatcherServlet。

(当然只是实现部分IOC部分,像其余的组件暂未实现)

首先创建一个DispatcherServlet  在这里为了和Spring Mvc中的做区分,我这里命名为ZyxDispatcherServlet。

 既然是一个Servlet就要继承HttpServlet,并且要重写四个方法:

  1. init();
  2. init(ServletConfig config);
  3. doGet(HttpServletRequest req, HttpServletResponse resp);
  4. doPost(HttpServletRequest req, HttpServletResponse resp);

3,4不用多说,既然要响应网页前端请求必须要有get和post方法的一个处理,GET请求直接转给POST统一做处理,而init方法具体暂时也不需要实现什么东西,2 才是最关键的部分,其中功能如下:

@Override
	public void init(ServletConfig config) throws ServletException {
		// 先整理思路


		// 1 先加载配置文件 读取web文件中的param-name 
		doLoadConfig(config.getInitParameter("contextConfigLocation"));


		// 2 扫描所有的包 
		doScanner(properties.getProperty("scanPackage"));
		
		// 3 初始化所有的类,并保存在IOC容器中
		doInstace();
		
		// 4 实现依赖注入
		doAutowired();
		
		// 5 构造一个HanderMapping 将请求的Url和Method建立关系 
		initHandlerMapping();
		
		// 6 等待请求,根据匹配的URL 去动态调用doPost 或者doGet
		
		System.out.println("ZyxDispatcherServlet init  加载完成!");
	}


下面贴上我的具体实现代码:

/**
	 * 获取配置文件
	 * @param path
	 */
	private void doLoadConfig(String path) {
		//获取输入流
		System.out.println("path :"+path);
		InputStream input =  this.getClass().getClassLoader().getResourceAsStream(path);
		try {
			properties.load(input);
		} catch (IOException e) {
			System.out.println("获取输入流发送错误"+e.getMessage());
			e.printStackTrace();
		}finally{
			try {
				input.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 扫描所有的包
	 * @author ZHANG_YX
	 * @date 2017年12月28日 上午9:21:52
	 */
	private void doScanner(String packageName) {

		System.out.println("packageName :"+packageName);
		URL url = this.getClass().getClassLoader().getResource("/"+packageName.replaceAll("\\.", "/"));
		File file = new File(url.getFile());
		for (File fi : file.listFiles()) {
			if(fi.isDirectory()){
				System.out.println("file name:"+fi.getName());
				doScanner(packageName+"."+fi.getName());
			}else{
				classNames.add(packageName+"."+fi.getName().replace(".class", ""));
			}
		}
	}
	/**
	 * 初始化所有的实例
	 * @author ZHANG_YX
	 * @date 2017年12月28日 上午9:18:11
	 */
	private void doInstace() {
		if(classNames.size()<1)return ;
		try {
			for(String className : classNames) {
				Class<?> clazz =Class.forName(className);
				if(clazz.isAnnotationPresent(ZyxController.class)){
					ioc.put(lowerFirst(clazz.getSimpleName()), clazz.newInstance());
				}else if(clazz.isAnnotationPresent(ZyxService.class)){
					//1 如果自己有名字 则用自己的名字
					//2 如果没有 则用类名首字母小写
					//3 如果是接口,则用实现接口的小写实例名
					ZyxService zyxservice = clazz.getAnnotation(ZyxService.class) ;
					String beanName = zyxservice.value();
					
					if(!beanName.equals("")){
						ioc.put(beanName, clazz.newInstance());
					}else{
						ioc.put(lowerFirst(clazz.getSimpleName()), clazz.newInstance());
					}
					Class[] interfaces = clazz.getInterfaces();
					for (Class class1 : interfaces) {
						System.out.println("class1.getName():"+class1.getName());
						ioc.put(class1.getSimpleName(), clazz.newInstance());
					}
				}else{
					  continue;
				}
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}

	private void doAutowired() {
		if(ioc.isEmpty())return;
		for (Entry entry : ioc.entrySet()) {
			Field []  fields = entry.getClass().getDeclaredFields();
			for (Field field : fields) {
				if(!field.isAnnotationPresent(ZyxAutowired.class)){continue;}
				ZyxAutowired zyxAutowired = field.getAnnotation(ZyxAutowired.class);
				//和初始化class一样  注入也是需要分三种情况(有名字,无名字)
				String beanName = zyxAutowired.value();
				if(!"".equals(beanName))
					beanName = field.getType().getName();
				field.setAccessible(true);
				try {
					field.set(entry.getValue(),ioc.get(beanName));
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private void initHandlerMapping(){
		if(ioc.isEmpty())return;
		
		for (Entry<String,Object> entry : ioc.entrySet()) {
			Class controllerClass =entry.getValue().getClass();
			if(!controllerClass.isAnnotationPresent(ZyxController.class))continue;
			
			String baseUrl = "";//获取requestMapping url
			if(controllerClass.isAnnotationPresent(ZyxRequestMapping.class)){
				ZyxRequestMapping mapping = (ZyxRequestMapping) controllerClass.getAnnotation(ZyxRequestMapping.class);
				baseUrl = mapping.value();
			}
			Method[] methods = controllerClass.getMethods();
			for (Method method : methods) {
				if(!method.isAnnotationPresent(ZyxRequestMapping.class))continue;
				ZyxRequestMapping methodMapping = method.getAnnotation(ZyxRequestMapping.class);
				baseUrl = "/"+baseUrl+methodMapping.value();
//				handlerMapping.put(baseUrl, method);
				Pattern pa = Pattern.compile(baseUrl);
				handlerMapping.add(new Handler(controllerClass,method,pa));
				
			}
		}
	}
	private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException{
		Handler handler = getHandler(req);
		if(handler==null){
			resp.getWriter().write("404 not Found Handler");
			return ;
		}
		handler.method.invoke(handler.controller, handler.paramMappingIndex);
		
		
		
	}
	private Handler getHandler(HttpServletRequest request){
		if(handlerMapping.isEmpty())return null;
		String contextPath = request.getContextPath();
		String url = request.getRequestURI();
		System.out.println("contextPath:"+contextPath);
//		url.replace(contextPath, "").replaceAll("/+", "/");
		System.out.println("url:"+url);
		for (Handler handler : handlerMapping) {
			Matcher matcher = handler.pattern.matcher(url);
			if(!matcher.matches())continue;
			return handler;
 		}
		return null;
	}
	private String lowerFirst(String name){
		char[] chars = name.toCharArray();
		chars[0] += 32;
		return String.valueOf(chars);
	}
	@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 {
		try {
			doDispatch( req,  resp);
		}  catch (Exception e) {
			resp.getWriter().write("500 doDispatch错误:"+Arrays.toString(e.getStackTrace()));
		}
	}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值