實戰手寫SpringMvc

一、新建maven web項目

二、程序目錄結構

 Autowried註解

package org.lsh.mvcframe.annotation;

import java.lang.annotation.*;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowried {
    String value() default "";
}

Controller註解 

package org.lsh.mvcframe.annotation;

import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Controller {
    String value() default "";
}

RequestMapping註解 

​
package org.lsh.mvcframe.annotation;

import java.lang.annotation.*;

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestMapping {
    String value() default "";
}

​

RequestParam註解 

package org.lsh.mvcframe.annotation;

import java.lang.annotation.*;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    String value();
}

Service註解 

package org.lsh.mvcframe.annotation;

import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Service {
    String value() default "";
}

DispatcherServlet 

package org.lsh.mvcframe.servlet;


import org.lsh.demo.controller.HelloController;
import org.lsh.mvcframe.annotation.*;

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 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.*;

public class DispatcherServlet extends HttpServlet{

    List<String> classNames = new ArrayList<String>();
    Map<String,Object> beans= new HashMap<String,Object>();
    Map<String,Object> handlerMap=new HashMap<String,Object>();

    @Override
    public void init(ServletConfig config){
        scanPackage("org.lsh");
        doInstance();
        doIoc();
        buildUrlMapping();
    }

    public void scanPackage(String packagePath){
        //掃描編譯好的類路徑下的所有的類.class
        URL url=this.getClass().getClassLoader().getResource("/"+packagePath.replaceAll("\\.","/"));
        String fileStr=url.getFile();
        File file=new File(fileStr);

        String[] filesStr=file.list();
        for (String path:filesStr){
            File filePath =new File(fileStr+path);
            if(filePath.isDirectory()){
                scanPackage(packagePath+"."+path);
            }else{
                classNames.add(packagePath+"."+filePath.getName());
            }
        }
    }
    public void doInstance(){
        if(classNames.size()<=0){
            return;
        }
        for(String className:classNames){
            String cn=className.replace(".class","");
            try {
                Class<?> clazz=Class.forName(cn);
                if(clazz.isAnnotationPresent(Controller.class)){
                    Object instance=clazz.newInstance();
                    RequestMapping requestMapping=clazz.getAnnotation(RequestMapping.class);
                    String value=requestMapping.value();
                    beans.put(value,instance);
                }else if(clazz.isAnnotationPresent(Service.class)){
                    Object instance=clazz.newInstance();
                    Service service=clazz.getAnnotation(Service.class);
                    String value=service.value();
                    beans.put(value, instance);
                }else{
                    continue;
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    }
    public void doIoc(){
        if(beans.entrySet().size()<=0){
            return;
        }
        for(Map.Entry<String,Object> entry:beans.entrySet()){
            Object instance = entry.getValue();
            Class<?> clazz = instance.getClass();

            if (clazz.isAnnotationPresent(Controller.class)) {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    if (field.isAnnotationPresent(Autowried.class)) {
                        Autowried autowried = field.getAnnotation(Autowried.class);
                        String value = autowried.value();
                        field.setAccessible(true);
                        try {
                            field.set(instance, beans.get(value));
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    } else {
                        continue;
                    }
                }

            } else {
                continue;
            }

        }
    }

    public void buildUrlMapping(){
        if(beans.entrySet().size()<=0){
            return;
        }
        for(Map.Entry<String,Object> entry:beans.entrySet()){
            Object instance = entry.getValue();
            Class<?> clazz = instance.getClass();

            if(clazz.isAnnotationPresent(Controller.class)){
                RequestMapping requestMapping=entry.getValue().getClass().getAnnotation(RequestMapping.class);
                String controllerPath=requestMapping.value();

                Method[] methods =clazz.getMethods();
                for (Method method: methods) {
                    if(method.isAnnotationPresent(RequestMapping.class)){
                        RequestMapping methodRequestMapping = method.getAnnotation(RequestMapping.class);
                        String methodPath=methodRequestMapping.value();
                        handlerMap.put(controllerPath+methodPath, method);
                    }else{
                        continue;
                    }
                }
            }else{
                continue;
            }
        }
    }
    private static Object[] hand(HttpServletRequest request,HttpServletResponse response,Method method){
        //拿到當前待執行的方法有哪些參數
        Class<?>[] paramClazzs=method.getParameterTypes();
        //根據參數的個數,new 一個參數數組,將方法裏的所有參數賦值到args來
        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;
            }
            // 從0-3判斷有沒有RequestParam註解,很明顯paramClazz爲0和1時,不是,
            //當爲2和3時爲@RequestParam,需要解析
            Annotation[] paramAns=method.getParameterAnnotations()[index];
            if(paramAns.length>0){
                for (Annotation paramAn:paramAns){
                    if(RequestParam.class.isAssignableFrom(paramAn.getClass())){
                        RequestParam rp=(RequestParam) paramAn;
                        args[args_i++]=request.getParameter(rp.value());
                    }
                }
            }
            index++;
        }
        return args;
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String uri =req.getRequestURI();
        String context=req.getContextPath();
        String path=uri.replace(context,"");

        Method method = (Method) handlerMap.get(path);
        HelloController instance =(HelloController)beans.get("/"+path.split("/")[1]);

        Object[] arg = hand(req, resp, method);
        try {
            method.invoke(instance,arg);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }



    }
}

HelloController 

package org.lsh.demo.controller;

import org.lsh.mvcframe.annotation.Autowried;
import org.lsh.mvcframe.annotation.Controller;
import org.lsh.mvcframe.annotation.RequestMapping;
import org.lsh.mvcframe.annotation.RequestParam;
import org.lsh.demo.service.HelloService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
@RequestMapping("/hello")
public class HelloController {

    @Autowried("helloService")
    private HelloService helloService;

    @RequestMapping("/login")
    public void login(HttpServletRequest request, HttpServletResponse response,
                      @RequestParam("username") String username, @RequestParam("password") String password) throws IOException {
        String result=helloService.sayHello("123","123");
        response.getWriter().println(result);
    }
}

HelloService 

package org.lsh.demo.service;

public interface  HelloService {
    public String sayHello(String username,String password);
}

HelloServiceImpl 

package org.lsh.demo.service.impl;

import org.lsh.mvcframe.annotation.Service;
import org.lsh.demo.service.HelloService;

@Service("helloService")
public class HelloServiceImpl implements HelloService{
    public String sayHello(String username, String password) {
        return "Hello,"+username;
    }
}

web.xml 

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <display-name>spring-mvc</display-name>
  <servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.lsh.mvcframe.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>0</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

</web-app>
        

pom.xml 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <packaging>war</packaging>

  <name>springmvc</name>
  <groupId>org.lsh</groupId>
  <artifactId>springmvc</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.0.1</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

</project>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章