一起写框架-MVC框架-基础功能-ServletAPI的动态绑定(五)
实现功能
以上的代码实现了通过路径执行对应的执行方法,但执行方法的参数是必须需要传入请求后响应的参数的。
分别为: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;i<parameters.length;i++){ 6 Class<?> typeClass = 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.测试结果,输出对应的对象。成功!