/** * @author solverpeng * @create 2016-08-04-9:43 */ public class Employee { private String empName; private Address address; public String getEmpName() { return empName; } public void setEmpName(String empName) { this.empName = empName; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Override public String toString() { return "Employee{" + "empName='" + empName + '\'' + ", address=" + address + '}'; } }
Employee/** * @author solverpeng * @create 2016-08-04-9:43 */ public class Address { private String addressName; public String getAddressName() { return addressName; } public void setAddressName(String addressName) { this.addressName = addressName; } @Override public String toString() { return "Address{" + "addressName='" + addressName + '\'' + '}'; } }
Address请求:同样包含 get 请求 和 post 请求
<a href="testBeanCascade?empName=jack&address.addressName=beijing">test bean cascade</a> <form action="testBeanCascade" method="post"> <label> empName:<input type="text" name="empName"/> </label> <label> Address:<input type="text" name="address.addressName"/> </label> <input type="submit" value="submit"/> </form>
handler 方法:
@RequestMapping("/testBeanCascade") public String testBeanCascade(Employee employee) { System.out.println(employee);//Employee{empName='jack', address=Address{addressName='beijing'}} return "success"; }
是如何绑定的呢?翻源码过程如下:
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#invokeHandlerMethod
ExtendedModelMap implicitModel = new BindingAwareModelMap();
Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
第一步:发现在 result 中已经包含了注入的 bean。所以注入是在methodInvoker.invokeHandlerMethod() 方法中做的。
第二步:org.springframework.web.bind.annotation.support.HandlerMethodInvoker#invokeHandlerMethod
Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
第三步:org.springframework.web.bind.annotation.support.HandlerMethodInvoker#resolveHandlerArguments
doBind(binder, webRequest, validate, validationHints, !assignBindingResult);// 这里进行的绑定
第四步:org.springframework.web.bind.ServletRequestDataBinder#bind
doBind(mpvs);
第五步:org.springframework.validation.DataBinder#doBind
this.applyPropertyValues(mpvs);
最终发现,是在 DataBinder 这个类的 doBind() 方法中进行的绑定。在翻源码的过程中,发现 resolveHandlerArguments() 方法值得大家看一看,不论水平高低,
其实真正解决 SpringMVC 参数问题就是在这个方法中解决的。
总结一下:Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。
二、SpringMVC 解决 Servlet 资源获取问题
1. SpringMVC 使用 Servlet 资源作为方法的入参来解决 Servlet 资源获取问题。
2.可以作为入参的 Servlet 资源有:HttpServletRequest、HttpServletResponse、HttpSession、Locale、InputStream、OutputStream、Reader、Writer
3.例子:
使用 HttpServletRequest 作为入参
请求:<a href="https://www.linuxidc.com/testServletAPI">test servlet api</a>
handler 方法: