首页 > 技术文章 > 简单mvc---模拟Springmvc

JavaHxm 2019-07-09 15:02 原文

1、注解篇

Auwowrited

package org.aaron.mvc.annaotation;

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

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented    
public @interface AaronAutowrited {

    String value() default "";
}

 

Controller

package org.aaron.mvc.annaotation;

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

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented    
public @interface AaronController {

    String value() default "";
}

 

RequestMapping

package org.aaron.mvc.annaotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
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 AaronRequestMapping {

    String value() default "";
}

RequestParam

package org.aaron.mvc.annaotation;

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

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented    
public @interface AaronRequestParam {

    String value() default "";
}

Service

package org.aaron.mvc.annaotation;

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

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented    
public @interface AaronService {

    String value() default "";
}

2、DispatcherServlet

package org.aaron.mvc.servlet;

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.ServletConfig;
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 org.aaron.mvc.annaotation.AaronAutowrited;
import org.aaron.mvc.annaotation.AaronController;
import org.aaron.mvc.annaotation.AaronRequestMapping;
import org.aaron.mvc.annaotation.AaronRequestParam;
import org.aaron.mvc.annaotation.AaronService;
import org.omg.CORBA.Request;

public class DispatcherServlet extends HttpServlet {

    List<String> classNames = new ArrayList<String>();// 全类名路径
                                                        // //org.aaron.mvc.service.impl+类名
    
    Map<String,Object> beans = new HashMap<>();
    
    Map<String,Object> handlerMap = new HashMap<>();
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public void init(ServletConfig config) {
        // ioc
        // 扫描所有的bean----->扫描所有的class文件
        scanPackage("org.aaron"); // spring的做法是写在配置文件中
        // 根据类创建对象
        doInstance();
        doIoc();
        buildUrlMapping();//根据url 建立关系  method
    }

    // 扫描文件
    private void scanPackage(String basePackage) {
        URL url = this.getClass().getClassLoader().getResource("/" + basePackage.replaceAll("\\.", "/"));// 获取工作空间的编译路径
        System.err.println(url);
        String fileStr = url.getFile();
        File file = new File(fileStr);// 拿到目录下的文件和文件夹
        String[] filesStr = file.list(); // Aaron
        for (String path : filesStr) {

            File filePath = new File(fileStr + path);// org.aaron.mvc
            if (filePath.isDirectory()) {// 判断是文件还是文件夹 文件夹 递归继续找

                scanPackage(basePackage + "." + path);
            } else {

                classNames.add(basePackage + "." + filePath.getName());// org.aaron.mvc.xxx.xxxx.class
            }
        }
    }

    // 根据扫描的类名 实例化
    private void doInstance() {
        if (classNames.size() <= 0) {
            System.err.println("扫描失败");
            return;
        }
        // 遍历 扫描到class文件
        for (String className : classNames) {
            String cn = className.replace(".class", "");
            try {
                Class<?> clazz = Class.forName(cn); // 获取到org.aaron.
                if (clazz.isAnnotationPresent(AaronController.class)) {// 判断是不是有控制场注解
                    Object instance = clazz.newInstance();// 创建类 实例化的对象
                    AaronRequestMapping requestMapping = clazz.getAnnotation(AaronRequestMapping.class);//拿到 mapping 注解
                    String rm = requestMapping.value();//获取到mapping的value        
                    beans.put(rm, instance);// 
                }else if (clazz.isAnnotationPresent(AaronService.class)){
                    
                    AaronService aaronService = clazz.getAnnotation(AaronService.class);
                    Object instance = clazz.newInstance();
                    beans.put(aaronService.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();
            }
        }

    }
    //把service 注入到Controller
    public void doIoc(){
        if(beans.entrySet().size()<=0){
            
            System.err.println("没有实例化的类");
        }
        //遍历map的实例化的类
        for(Map.Entry<String, Object> entry: beans.entrySet()){
            Object instace = entry.getValue();
            Class<?> clazz = instace.getClass();
            if(clazz.isAnnotationPresent(AaronController.class)){
                
                Field[] fields =clazz.getDeclaredFields();
                for(Field field : fields){
                    if(field.isAnnotationPresent(AaronAutowrited.class)){//判断当前遍历是否有注解
                        AaronAutowrited aaronAutowrited = field.getAnnotation(AaronAutowrited.class);
                        String key = aaronAutowrited.value();//获取到 注解的value
                        field.setAccessible(true);//因为是private  无法修改值
                        try {
                            field.set(instace, beans.get(key));
                        } 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 buildUrlMapping(){
        
        if(beans.entrySet().size()<=0){//没有类的实例化
            System.err.println("没有类的实例化");
            return;
        }
        for(Map.Entry<String, Object> entry : beans.entrySet()){
            Object instance = entry.getValue();
            Class<?> clazz = instance.getClass();
            if(clazz.isAnnotationPresent(AaronController.class)){
                
                AaronRequestMapping aaronRequestMapping = clazz.getAnnotation(AaronRequestMapping.class);
                String classPath = aaronRequestMapping.value();//拿到类上的mapping
                Method[] methods = clazz.getMethods();//拿到类的方法
                for(Method method : methods){
                    if(method.isAnnotationPresent(AaronRequestMapping.class)){//判断了方法上面是否有注解
                        AaronRequestMapping methodMapping = method.getAnnotation(AaronRequestMapping.class);
                        String methodPath = methodMapping.value();//获取到注解的value
                        handlerMap.put(classPath+methodPath, method);
                        
                    }else{
                        continue;
                    }
                    
                }
            }else{
                continue;
            }
        }
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.err.println("test1");
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //获取请求路径 /项目名/ctrl/method
        String uri = req.getRequestURI();
        String content = req.getContextPath();//获取项目名
        String path = uri.replace(content, "");//ctrl/method
        Method method = (Method)handlerMap.get(path);
        Object instance = (Object)beans.get("/"+path.split("/")[1]);// ctrl
        Object[] agrs = hand(req,resp,method);
        try {
            method.invoke(instance, agrs);
        } 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();
        }
        super.doPost(req, resp);
    }
    //处理参数
    private static Object[] hand(HttpServletRequest req, HttpServletResponse resp,Method method){
        //拿到当前执行的方法有哪些参数
        Class<?>[] paramClazzs = method.getParameterTypes();
        //根据参数的个数 new一个存放参数的数组
        Object[] args = new Object[paramClazzs.length];
        int arg_i = 0 ;
        int index = 0;
        for(Class<?> paramClazz : paramClazzs){
            if(ServletRequest.class.isAssignableFrom(paramClazz)){
                
                args[arg_i++] = req;
            }
            if(ServletResponse.class.isAssignableFrom(paramClazz)){
                
                args[arg_i++] = resp;
            }
            Annotation[] paramAns = method.getParameterAnnotations()[index];
            if(paramAns.length>0){
                for(Annotation paramAn : paramAns){
                    if(AaronRequestParam.class.isAssignableFrom(paramAn.getClass())){
                        AaronRequestParam rp = (AaronRequestParam)paramAn;
                        args[arg_i++] =  req.getParameter(rp.value());
                        
                    }
                    
                }
                
            }
            index++;
        }
        return args;
        
    }
    

}

3、实战篇

controller代码

package org.aaron.mvc.ctrl;

import java.io.IOException;
import java.io.PrintWriter;

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

import org.aaron.mvc.annaotation.AaronAutowrited;
import org.aaron.mvc.annaotation.AaronController;
import org.aaron.mvc.annaotation.AaronRequestMapping;
import org.aaron.mvc.annaotation.AaronRequestParam;
import org.aaron.mvc.service.TestService;

    
@AaronController
@AaronRequestMapping("/Aaron")
public class TestCtrl {

    @AaronAutowrited("TestServiceImpl")
    private TestService service;
    
    @AaronRequestMapping("/query")
    public void query(HttpServletRequest request,HttpServletResponse response,
            @AaronRequestParam("name") String name, @AaronRequestParam("age") String age){
        String result =  service.query(name, age);
        try {
            PrintWriter out;
         
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html; charset=utf-8");
            out = response.getWriter();
     
            out.write(result);
            out.close();
        
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        
    }
    
}

service接口

package org.aaron.mvc.service;

public interface TestService {

    String query(String name,String age);
}

 

service接口实现

package org.aaron.mvc.service.impl;

import org.aaron.mvc.annaotation.AaronService;
import org.aaron.mvc.service.TestService;


@AaronService("TestServiceImpl")
public class TestServiceImpl implements TestService{

    public String query(String name, String age) {
        // TODO Auto-generated method stub
        return "当前用户:"+name+"年龄"+age ;
    }

}

 

推荐阅读