手写SpringMVC框架

/*1编写注解

编写Springmvc常用的注解

@controller

@requestmapper

@Serviceim

@autoware

通过编写如上所示的注解,来完成springmvc的基本功能

package xiao.it.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 XiaoAutoware {
      String value() default "null";
}

package xiao.it.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 XiaoController {
   String value() default "null";
}
package xiao.it.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.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface XiaoRequestMapping {
    String value() default "null";
}

package xiao.it.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 XiaoService {
    String value() default "null";
    String param() default "null";
}

/*2 重写httpservlet的get.post方法

写一个自己的httpservelet类来完成springmvc的请求转发操作

package xiao.it.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;

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




public class Xiao_wornDispacherServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	
	
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		this.doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		SpringmvxCore core=new SpringmvxCore();
		try {
			core.doDispacher( req, resp);
		} catch(Exception exception){
			PrintWriter writer = resp.getWriter();
			writer.write("404 请求异常");
		}
	}

    

}


/*3、包扫描

包扫描的目的
根据basepackage,就是基包(代码中指的是com),扫描下面的子包以及子包下的类
拿到包下的所有类文件后,我们就可以得到文件名
有包名有文件名,我们就可以通过反射new出这些类的实例
目的就是扫描基包下的所有的类文件,根据文件获取类的完整类名:包名+类名

通过文件的方式去扫描


4、把所有的类new出实例后,我们就要把类中的依赖关系注入进去
拿到类的Class对象
拿到field对象
拿到field上面的annotation对象
根据annotation对象拿annotation对象的属性
把属性当key拿到map中的实例
然后field。set把实例设置进去
5、建立一个url与类中方法的映射关系

其实是同样的做法
拿到类的Class对象
拿到Method对象
拿到Method上面的annotation对象

把url和method对象存到map中*/

package xiao.it.servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
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.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;

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

import org.apache.coyote.ActionCode;
import org.apache.tomcat.util.codec.binary.StringUtils;

import worn.it.struct.UrlMapping;
import xiao.it.annotation.XiaoAutoware;
import xiao.it.annotation.XiaoController;
import xiao.it.annotation.XiaoRequestMapping;
import xiao.it.annotation.XiaoService;



public class SpringmvxCore {

    //存放类名的文件.class
	public HashMap<String,String> nameMap=new HashMap<String, String>();
	
	//存放实例的结构  key=注解小写  value=对象
	public HashMap<String,Object> annotation=new HashMap();

	//存储URL的映射 [{url,method},{url,method}]
	public HashMap<String,UrlMapping> hashmap=new HashMap();
	
	
	public void doDispacher(HttpServletRequest req, HttpServletResponse resp) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		
		//1读取配置文件
		InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("packege.properties");
		Properties properties =new Properties();
		properties.load(resourceAsStream);
		String string = (String) properties.get("scanpackage");
	    //所描类文件
	    Scanner(string);
	    //加载类文件 
	    loadClassFile();
	    //进行spring的IoC操作
	    spring_Ioc();
	    //组织地址映射
	    handlerMapping(req,resp);
	    //最后一部 处理请求
	    parseURL(req, resp);
	}
	
	/**
	 *  处理路劲映射
	 * @param req 请求
	 * @param resp 回应
	 * @throws ClassNotFoundException 
	 */
	private void handlerMapping(HttpServletRequest req, HttpServletResponse resp) throws ClassNotFoundException {
	     
		UrlMapping urlMapping=new UrlMapping();
		
		Collection<String> values = nameMap.values();
		for(String str:values){
			
    		String classPath=str.replace(".class", "");
    		Class<?> classd = Class.forName(classPath);
    		String contextPath = req.getContextPath();
		    String baseurl=contextPath;
			    if(!classd.isInterface()){
			    	if(classd.isAnnotationPresent(XiaoController.class)){
			    		
			    		if(classd.isAnnotationPresent(XiaoRequestMapping.class)){
				    		XiaoRequestMapping annotation2 = classd.getAnnotation(XiaoRequestMapping.class);
				    		baseurl=baseurl+annotation2.value();
				    	}
				    		
				    	Method[] methods = classd.getMethods();
				    	for(Method method:methods){
				    		if(method.isAnnotationPresent(XiaoRequestMapping.class)){
				    			XiaoRequestMapping anno = method.getAnnotation(XiaoRequestMapping.class);
				    			String value = anno.value();
				    			baseurl=baseurl+value;
				    			baseurl=baseurl.replaceAll("//", "/");
				    			urlMapping.setUrl(baseurl);
				    			urlMapping.setMethod(method);
				    		}
				    	}
				    	//控制层
				      	if(classd.isAnnotationPresent(XiaoController.class)){
				      		String simpleName = classd.getSimpleName();
				      		String dealFirst = dealFirst(simpleName);
				      		Object object = annotation.get(dealFirst);
				      		urlMapping.setObj(object);
				      	}
				      	hashmap.put(urlMapping.getUrl(), urlMapping);
			    		
			    		
			    	}
		    	
			    }
		}
	}

	/**
	 * 所描包文件封装
	 * @param file
	 */
	public void Scanner(String filepath){
		String repl= filepath.replaceAll("\\*", "");
		String res= repl.replaceAll("\\.\\.", "\\.");
		String rep = res.replaceAll("\\.", "/");
		URL resource = this.getClass().getClassLoader().getResource("/"+rep);		
		String path2 = resource.getPath();
		File fi=new File(path2);
		String[] listFile = fi.list();
		//扫描所有的文件
		for(String file:listFile){
			File fle=new File(path2+file);
			if(fle.isDirectory()){
				Scanner(filepath+"."+file);
			}else{
				String name = fle.getName();
			    String classpath=res+"."+name;
				nameMap.put(name,classpath);
			}
		}
		
	}
	
	/**
	 * 加载类文件
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
    public void loadClassFile() throws ClassNotFoundException, InstantiationException, IllegalAccessException{
    	
    	if(nameMap.size()<=0){
    		return ;
    	}
    	
    	Collection<String> values = nameMap.values();
    	for(String path:values){
    		String claname=path.replaceAll(".class", "");
    		Class<?> classd = Class.forName(claname);
    		if(!classd.isInterface()){
    			Object obj=classd.newInstance();
	    		if(classd.isAnnotationPresent(XiaoService.class)){
	    			XiaoService annotation2 = classd.getAnnotation(XiaoService.class);
	    			String key=null;
	    			String value = annotation2.value();
	    			
	    			if(!"null".equals(value)){
	    				key=value;
	    			}else{
	    				key=dealFirst(classd.getSimpleName());
	    			}
	    			annotation.put(key, obj);
	    		}else if(classd.isAnnotationPresent(XiaoController.class)){
	    			XiaoController annotation2 = classd.getAnnotation(XiaoController.class);
	    			String key=null;
	    			String value = annotation2.value();
	    			if(!"null".equals(value)){
	    				key=value;
	    			}else{
	    				key=dealFirst(classd.getSimpleName());
	    			}
	    			annotation.put(key, obj);
	    		}
    		}
    	}
    }
	
	/**
	 * 
	 * @param name  原始类名
	 * @return 首字母小写的类名
	 */
    public String dealFirst(String name){
    	String first_word = name.substring(0, 1);
    	String suString =name.substring(1);
    	String lowerCase = first_word.toLowerCase();
    	String finale=lowerCase+suString;
    	return finale;
    }
	
	/**
	 * 实例化类 并把类关系注入进去
	 * @throws ClassNotFoundException 
	 */
	public void spring_Ioc() throws ClassNotFoundException{
		try{
			Collection<Object> values = annotation.values();
			for(Object obj:values){
				Class<? extends Object> class1 = obj.getClass();
				Field[] fields = class1.getDeclaredFields();
				for(Field field:fields){
					if(field.isAnnotationPresent(XiaoAutoware.class)){
					     String name = field.getName();
					     Object object = annotation.get(name);
					     //字段中如果这个字段是私有的要对这个字段进行设置值
					     field.setAccessible(true);
					     //参数一  本对象 参数二  要注入的对象 
					     field.set(obj, object);
					}
				}	
			}
		}catch(Exception exception){
			;
		}
	}
	
	
	public void parseURL(HttpServletRequest req, HttpServletResponse resp) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		//获取请求参数
		StringBuffer requestURL = req.getRequestURL();
		String string = requestURL.toString();
		String requestURI = req.getRequestURI();
		UrlMapping urlMapping = hashmap.get(requestURI);
	
		if(null!=urlMapping){
			Object obj = urlMapping.getObj();
			Method method = urlMapping.getMethod();
			method.invoke(obj, null);
		}
	}
	
}


测试框架的使用

package worn.it.controller;

import worn.it.service.UserService;
import xiao.it.annotation.XiaoAutoware;
import xiao.it.annotation.XiaoController;
import xiao.it.annotation.XiaoRequestMapping;


@XiaoController
@XiaoRequestMapping(value="/")
public class UserController {

	@XiaoAutoware
	private UserService userService;

	@XiaoRequestMapping(value="/index")
	public String getPage(){
		userService.hello();
		return "index";
	}
	
	
}

package worn.it.service;

public interface UserService {
    void hello();
}

package worn.it.service;

import xiao.it.annotation.XiaoService;


@XiaoService(value="userService")
public class UserServiceIm implements UserService{

	@Override
	public void hello() {
		// TODO Auto-generated method stub
		System.out.println("hello spring mvc");
	}

	

}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
手写Spring MVC是指自己实现一个简单的Spring MVC框架,而不是使用官方提供的Spring MVC框架。在手写Spring MVC时,你需要实现以下几个关键部分: 1. 创建一个前端控制器(Front Controller):前端控制器是整个请求处理过程的入口点,负责接收请求并进行路由。你可以使用Servlet作为前端控制器,接收所有的HTTP请求,并将它们分发给相应的控制器。 2. 定义控制器类:控制器类负责处理特定URL的请求,并根据请求参数进行相应的处理。你可以使用注解(如@RequestMapping)来定义控制器类和方法的映射关系。 3. 实现视图解析器(View Resolver):视图解析器负责解析控制器返回的逻辑视图名,并将其转换为具体的视图对象或视图模板。你可以使用模板引擎(如Thymeleaf、Freemarker等)来渲染动态内容。 4. 注册控制器和视图解析器:在前端控制器中,你需要注册所有的控制器类和视图解析器,以便能够正确地处理请求和渲染视图。 5. 处理请求和响应:在控制器中,你需要编写相应的方法来处理请求,并根据业务逻辑生成响应。你可以使用HttpServletRequest和HttpServletResponse对象来访问请求参数和生成响应。 6. 配置URL映射:你需要在配置文件中配置URL与控制器方法的映射关系,以便能够正确地将请求分发给对应的控制器。 手写Spring MVC的过程可以帮助你更好地理解Spring MVC框架的工作原理和核心组件。但请注意,手写一个完整的Spring MVC框架可能会比较繁琐和复杂,特别是对于初学者来说。因此,如果你只是想学习Spring MVC的基本原理和用法,我建议你先阅读官方文档或参考一些教程来快速入门。如果你确实有兴趣手写Spring MVC,你可以参考引用中的博客文章,里面提供了一个手写Spring MVC框架的实现示例。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [手写 springmvc](https://download.csdn.net/download/knight_black_bob/10207699)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [SpringMvc手写简单实现篇 - MVC完结篇](https://blog.csdn.net/qq_35551875/article/details/121811048)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值