手搓 SpringMvc(简易最详细代码版)

目录

项目构建

1、环境搭建

打war包并引入依赖

        引入web

2、项目结构

代码实现

1、 自定义注解

2、控制层

3、服务层  

4、实现层

5、前端控制器

6、web.xml

效果

1、浏览器访问   

2、实现方法


项目构建

1、环境搭建

Maven项目,添加web模块

打war包并引入依赖

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

引入web

打开项目结构

web文件内容

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">
  

</web-app>

2、项目结构

代码实现

1、 自定义注解

        @Autowired

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


}

         @Controller

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

        @RequestMapping

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

        @RequestParam

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

        @Service

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

2、控制层

WriteController
@MvcController
@MvcRequestMapping("/write")
public class WriteController {
    @MvcAutowired("WriteServiceImpl")   //map.get("key)
    private WriteService writeService;

    @MvcRequestMapping("/query")
    public void query(HttpServletRequest request, HttpServletResponse response,
                      @MvcRequestParam("name") String name,
                      @MvcRequestParam("age") String age) {

        try {
            PrintWriter pw=response.getWriter();
            String result = writeService.query(name, age);
            pw.write(result);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

3、服务层  

WriteService

public interface WriteService {

    //查询方法
    String query(String name,String age);
}

4、实现层

@MvcService("WriteServiceImpl")  //map.put(WriteServiceImpl,new WriteServiceImpl)
public class WriteServiceImpl implements WriteService {
    @Override
    public String query(String name, String age) {
        return "name==="+name+";  age==="+age;
    }
}

5、前端控制器

定义一个名为DispatcherServlet  的Spring MVC框架的前端控制器,负责接收HTTP请求,根据请求信息调用相应的处理方法,并返回相应的HTTP响应

public class DispatcherServlet extends HttpServlet {

    List<String> classNames = new ArrayList<String>();

    Map<String, Object> beans = new HashMap<String, Object>();
    Map<String, Object> harldermap = new HashMap<String, Object>();
    
    private static final long serialVersionUID = 1L;


    public void init(ServletConfig config) {
        //把所有的bean扫描 ----扫描所有的class文件
        scanPackage("com.ll");

        doInstance(); //根据全类名创建bean

        doIoc();  //根据bean 进行依赖注入

        buildUrlMapping();  //构建url映射

    }


    //com.enjoy
    public void scanPackage(String basePackage) {
        URL url = this.getClass().getClassLoader().getResource("/" + basePackage.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(basePackage + "." + path);
            } else {
                //加入LIST
                classNames.add(basePackage + "." + filePath.getName());

            }
        }
    }

    //根据扫描到的List全类名 进行实例化
    public void doInstance() {
        if (classNames.size() <= 0) {
            System.out.println("没有扫描到任何类");
            return;
        }

        //list的所有class
        for (String className : classNames) {
            String cn = className.replace(".class", "");
            try {
                Class<?> aClass = Class.forName(cn);
                if (aClass.isAnnotationPresent(MvcController.class)) {
                    //是controller
                    Object instance = aClass.newInstance(); //创建控制类

                    MvcRequestMapping requestMapping = aClass.getAnnotation(MvcRequestMapping.class);
                    String rmvalue = requestMapping.value();  // /write
                    beans.put(rmvalue, instance);
                } else if (aClass.isAnnotationPresent(MvcService.class)) {
                    //是service
                    Object instance = aClass.newInstance();
                    MvcService service = aClass.getAnnotation(MvcService.class);
                    String serviceName = service.value();
                    beans.put(serviceName, instance);
                } else {
                    continue;
                }
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }

        }
    }


    //把service注入到controller
    public void doIoc() {

        if (beans.entrySet().size() <= 0) {
            System.out.println("没有一个实例化类");
        }
        for (Map.Entry<String, Object> entry : beans.entrySet()) {
            Object instance = entry.getValue();
            Class<?> clazz = instance.getClass();

            if (clazz.isAnnotationPresent(MvcController.class)) {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    if (field.isAnnotationPresent(MvcAutowired.class)) {
                        MvcAutowired autowired = field.getAnnotation(MvcAutowired.class);
                        String key = autowired.value();  // 获取service的key
                        field.setAccessible(true);
                        try {
                            field.set(instance, beans.get(key));
                        } catch (IllegalAccessException e) {
                            throw new RuntimeException(e);
                        }
                    } else {
                        continue;
                    }
                }
            }
        }

    }


    private void buildUrlMapping() {
        if (beans.entrySet().size() <= 0) {
            System.out.println("没有一个实例化类");
            return;
        }

        for (Map.Entry<String, Object> entry : beans.entrySet()) {
            Object instance = entry.getValue();
            Class<?> clazz = instance.getClass();
            if (clazz.isAnnotationPresent(MvcController.class)) {
                MvcRequestMapping requestMapping = clazz.getAnnotation(MvcRequestMapping.class);
                String classPath = requestMapping.value();  // /write

                Method[] methods = clazz.getMethods();

                for (Method method : methods) {
                    if (method.isAnnotationPresent(MvcRequestMapping.class)) {
                        MvcRequestMapping methodMapping = method.getAnnotation(MvcRequestMapping.class);
                        String methodPath = methodMapping.value();
                        harldermap.put(classPath + methodPath, method); // 修改这里
                    } else {
                        continue;
                    }
                }
            }else{
                continue;
            }
        }

    }


    @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 url = req.getRequestURI();
        String context = req.getContextPath();  //write-mvc
        String path = url.replace(context, ""); //write/query



        Method method = (Method) harldermap.get(path);
        if (method == null) {
            throw new RuntimeException("No handler method found for the path: " + path);
        }


        //根据key - /write 到 map去拿
        WriteController instance= (WriteController) beans.get("/"+path.split("/")[1]);

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

    }


    private static Object[] hand(HttpServletRequest request, HttpServletResponse response, Method method){
        //拿到当前执行的方法有哪些参数
        Class<?>[] paramClazzs = method.getParameterTypes();
        //根据参数的个数 创建数组
        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;
            }
            Annotation[] paramAns = method.getParameterAnnotations()[index];
            if (paramAns.length > 0) {

                for (Annotation paramAn : paramAns) {
                    if(MvcRequestParam.class.isAssignableFrom(paramAn.getClass())){
                      MvcRequestParam requestParam = (MvcRequestParam) paramAn;
                      args[args_i++] = request.getParameter(requestParam.value());
                    }
                }
            }
            index++;
        }
        return args;
    }

6、web.xml

定义了一个名为DispatcherServlet的Servlet,并在服务器启动时加载(load-on-startup值为0)。映射该Servlet到所有以/开头的URL路径上。

    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>com.ll.springmvc.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>

效果

1、浏览器访问   

http://localhost:8080/spring_mvc_war/

2、实现方法

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值