简单mvc---模拟Springmvc

Posted javahxm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单mvc---模拟Springmvc相关的知识,希望对你有一定的参考价值。

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 ;
    

 

以上是关于简单mvc---模拟Springmvc的主要内容,如果未能解决你的问题,请参考以下文章

简单mvc---模拟Springmvc

短学期感想3

spring mvc中的mybatis怎么使用

简单模拟Sping MVC

Spring MVC Spring 安全性和错误处理

观察者模式的应用:模拟MVC架构的实现