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,在浏览器中输入:
http://127.0.0.1:8080/MyMVC/Say/Anything?word=12345678
http://127.0.0.1:8080/MyMVC/Eat/Anything?fruit=1234&cnt=2
可以看到控制台打印出:
12345678
I'm eating 1234, 2