实现功能
以上的代码实现了通过路径执行对应的执行方法,但执行方法的参数是必须需要传入请求后响应的参数的。
分别为:HttpServletRequest和HttpServletResponse。然后通过这个两个对象获得参数和处理参数。
需求:我们希望根据方法声明的参数列表决定是否需要ServletAPI的对象
- HttpServletRequest
- HttpServletResponse
- HttpSession
- ServletContext
而不是固定必须HttpServletRequest和HttpServletResponse。
实现思路
通过反射技术获得执行方法的参数列表。判断需要传入的ServletAPI对象。
实现步骤
1.在ControllerRelolver类中增加一个判断执行方法的参数列表方法 getparameterObjects
1 private Object[] getparameterObjects(Parameter[] parameters) { 2 // 1.创建设置一个参数对象的数组,参数的格式和参数类型的个一致 3 Object[] parameterObjects = new Object[parameters.length]; 4 //2.根据参数的类型,将对于的对象填在对象数组中 5 for(int i=0;itypeClass = parameters[i].getType(); 7 //3.根据判断方法参数的类型和我们制定的4个作用是否是父子类关系。如果是就赋值 8 if(ServletRequest.class.isAssignableFrom(typeClass)){ 9 parameterObjects[i]=this.request;10 }else if(ServletResponse.class.isAssignableFrom(typeClass)){11 parameterObjects[i]=this.response;12 }else if(HttpSession.class.isAssignableFrom(typeClass)){13 parameterObjects[i]=this.session;14 }else if(ServletContext.class.isAssignableFrom(typeClass)){15 parameterObjects[i]=this.application;16 }17 18 }19 return parameterObjects;20 }
2.修改ControllerRelolver的execute()方法,调用getparameterObjects方法来根据执行方法的参数列表,动态调用Controller的方法时传入对应的值
1 public String execute(HttpServletRequest request,HttpServletResponse response,Context context) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{ 2 //1.设置Servlet需要的API对象 3 this.request=request; 4 this.response=response; 5 this.session=request.getSession(); 6 this.application=request.getServletContext(); 7 8 //1.获得请求过来的路径 9 String uri = request.getRequestURI();10 //2.根据路径规则,获得映射路径11 String path = this.pathRule(uri);12 //3.通过路径获得容器中对应的业务控制器的对象和执行方法13 MappingEnttiy mappingEnttiy = this.getRequestMethod(path, context);14 //4.获得执行方法15 Method method = mappingEnttiy.getMethod();16 //5.获得路径对应的业务控制器17 Object controller = mappingEnttiy.getController();18 //6.执行方法,执行方法必须有request,response两个参数19 Parameter[] parameters = method.getParameters();20 //7.给执行的方法,设置根据执行方法的参数赋予对应的ServletAPI对象21 Object[] objects = this.getparameterObjects(parameters);22 //8.动态调用方法,将参数对应的对象赋值执行方法23 Object resultObject = method.invoke(controller, objects);24 if(resultObject!=null){25 //7.返回执行方法返回的映射字符串26 return (String) resultObject;27 }28 return null;29 }
测试代码
1.测试web项目的目录结构
2.修改测试的UserController的执行方法,有多个ServletAPI的参数
1 /** 2 * 路径规则: 3 * 1.必须包括有/开头 4 * 2.后缀必须忽略不写 5 * 如:http://localhost:8080/webmvc-demo-test-01/test.do 6 * 对应的映射路径为:/test 7 * 8 */ 9 @RequestMapping(value = "/login")10 public String login(HttpServletRequest request,HttpServletResponse response,ServletContext application,HttpSession session){11 System.out.println("-登录Controller-");12 System.out.println(request);13 System.out.println(response);14 System.out.println(application);15 System.out.println(session);16 return "redirect:/login.jsp";17 18 }
3.测试结果,输出对应的对象。成功!