zoukankan      html  css  js  c++  java
  • JavaWeb之搭建自己的MVC框架(三)

    1. 前言

            在前两节的内容中,我们完成了一个基本的框架搭建。但是如果我们在前端请求中增加参数,我们要怎么传递到后台方法呢?接下来我们就来研讨这部分内容。

    2. 实现

            (1)首先我们增加一个新的注解ParamMapping,用来给方法的参数标注其对应的前端参数名称。

    package com.mvc.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.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ParamMapping {    
        public String param() default "";
    }

            (2)我们在SayController中增加一个方法SayAnything,内容如下:

    package com.mvc.controller;
    
    import com.mvc.annotation.ParamMapping;
    import com.mvc.annotation.URLMapping;
    
    @URLMapping(url="/Say")
    public class SayController{
        
        @URLMapping(url="/Hello")
        public String SayHello(){
            System.out.println("Hello");
            return "Hello";
        }
        
        @URLMapping(url="/Hi")
        public String SayHi(){
            System.out.println("Hi");
            return "Hi";
        }
        
        @URLMapping(url="/Anything")
        public String SayAnything(@ParamMapping(param="word") String word){
            System.out.println(word);
            return word;
        }    
    }

            在SayAnything的参数中,我们对String word参数进行了注解@ParamMapping(param="word"),表示将来前端传参数名word,我们的框架会将其对应到SayAnything的String word参数中。

            (3)我们在SayController中增加一个方法SayAnything,内容如下:

    package com.mvc.controller;
    
    import com.mvc.annotation.ParamMapping;
    import com.mvc.annotation.URLMapping;
    
    @URLMapping(url="/Eat")
    public class EatController {
        
        @URLMapping(url="/Apple")
        public String EatApple(){
            System.out.println("I'm eating apples");
            return "Apple";
        }
        
        @URLMapping(url="/Banana")
        public String EatBanana(){
            System.out.println("I'm eating Banana");
            return "Banana";
        }
        
        @URLMapping(url="/Anything")
        public String EatAnything(@ParamMapping(param="fruit") String fruit, 
                                  @ParamMapping(param="cnt") Integer cnt) {
            System.out.println("I'm eating "+fruit+", "+cnt);
            return fruit;
        }
    }

            EatAnything的参数的注解和SayAnything是同一个道理。  

            (4)调整ServletCenter,使其完成前端参数到JAVA后台参数的传递过程。

    package com.mvc.servlet;
    
    import java.io.IOException;
    import java.lang.annotation.Annotation;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import com.mvc.annotation.ParamMapping;
    import com.mvc.base.MVCBase;
    import com.mvc.listener.UrlMappingCollection;
    
    public class ServletCenter extends HttpServlet {
        private static final long serialVersionUID = -1163369749078348562L;
    
        private void doTransfer(HttpServletRequest req, HttpServletResponse resp) 
                throws ServletException, IOException, ClassNotFoundException, 
                       SecurityException, NoSuchMethodException, IllegalArgumentException, 
                       IllegalAccessException, InvocationTargetException, 
                       InstantiationException {        
            for (MVCBase mvcBase : UrlMappingCollection.getMvcBases()) {
                if (req.getRequestURI().equals(
                             req.getServletContext().getContextPath()+mvcBase.getUrl())) {
                    Class<?> clazz = Class.forName(mvcBase.getController());
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
                        if (method.getName().equals(mvcBase.getMethod())) {
                            //拿到参数类型列表
                            Class<?>[] paramTypes =  method.getParameterTypes();
                            //拿到参数的注解列表
                            Annotation[][] paramAnno = method.getParameterAnnotations();
                            //new一个参数值数组吗,将来调用方法的时候要用
                            Object[] paramValues = new Object[paramTypes.length];
                            //每个参数会形成paramAnno的第一维,每个参数的每个注解会行程paramAnno的第二维
                            //所以paramAnno.length和paramTypes.length是相等的。
                            for (int i=0; i<paramAnno.length; i++) { 
                                for (int j=0; j<paramAnno[i].length; j++) {
                                    if (paramAnno[i][j] instanceof ParamMapping) {
                                        String paramName = ((ParamMapping) paramAnno[i][j]).param();
                                        if (req.getParameter(paramName) != null) {
                                            if (paramTypes[i].equals(String.class)) {
                                                paramValues[i] = req.getParameter(paramName);
                                            } else if (paramTypes[i].equals(Integer.class)) {
                                                paramValues[i] = Integer.valueOf(
                                                                   req.getParameter(paramName));
                                            } else {
                                                //其他类型待后续扩展
                                            }
                                        }    
                                    }
                                }
                            }
                            method.invoke(clazz.newInstance(), paramValues);
                        }
                    }            
                }
            }
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
                               throws ServletException, IOException {
            try {
                doTransfer(req, resp);
            } catch (Exception e) {
                System.out.println(e.toString());
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
                                throws ServletException, IOException {
            try {
                doTransfer(req, resp);
            } catch (Exception e) {
                System.out.println(e.toString());
            }
        }
    }

    3. 测试效果:

            启动tomcat,在浏览器中输入:

            可以看到控制台打印出:

      • 12345678    
      • I'm eating 1234, 2
    笔者只是初学者,开此博客的初衷是为了给自己的学习过程留一个痕迹。所以您可能发现笔者措辞不严谨、逻辑不合理,甚至代码有错误、结论很偏颇等等。笔者感激各位的讨论和指正,并在此不胜感激!拜谢!欢迎加QQ群讨论:852410026
  • 相关阅读:
    2020.10.25【NOIP提高A组】模拟 总结
    6831. 2020.10.24【NOIP提高A组】T1.lover
    枚举一个数$n$的所有质因子
    gmoj 6832. 2020.10.24【NOIP提高A组】T2.world
    2020.10.24【NOIP提高A组】模拟 总结
    2020.10.17【NOIP提高A组】模拟 总结
    jQuery EasyUI Portal 保存拖动位置,仿谷歌DashBoard效果的
    SQLMAP注入教程-11种常见SQLMAP使用方法详解
    Windows下sqlmap的安装图解
    swap file "*.swp" already exists!的解决方法
  • 原文地址:https://www.cnblogs.com/LOVE0612/p/5317281.html
Copyright © 2011-2022 走看看