[TOC]
# 接受表单数据
## 步骤 1 : 先运行,看到效果,再学习
先将完整的项目(向老师要相关资料),配置运行起来,确认可用之后,再学习做了哪些步骤以达到这样的效果。
访问页面提交数据
`http://localhost:8080/springmvc/addProduct.jsp`
## 步骤 2 : 模仿和排错
在确保可运行项目能够正确无误地运行之后,再严格照着教程的步骤,对代码模仿一遍。
模仿过程难免代码有出入,导致无法得到期望的运行结果,此时此刻通过比较**正确答案** ( 可运行项目 ) 和自己的代码,来定位问题所在。
采用这种方式,**学习有效果,排错有效率**,可以较为明显地提升学习速度,跨过学习路上的各个槛。
## 步骤 3 : 效果
这是通过页面增加产品名称和价格后,Spring MVC接受到参数,并显示出来
![](../images/Image021.png)
## 步骤 4 : pojo
实体类Product
~~~
package com.dodoke.pojo;
public class Product {
private int id;
private String name;
private float price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
~~~
## 步骤 5 : addProduct.jsp
在WebContent目录下 (不是在WEB-INF下)增加商品的页面addProduct.jsp(用于提交数据)
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="addProduct">
产品名称:<input type="text" name="name" value=""><br>
产品价格:<input type="text" name="price" value=""><br>
<input type="submit" value="增加商品">
</form>
</body>
</html>
~~~
## 步骤 6 : ProductController
控制器ProductController,准备一个add方法映射/addProduct路径
为add方法准备一个Product 参数,用于接收注入
最后跳转到showProduct页面显示用户提交的数据
注: addProduct.jsp 提交的name和price会自动注入到参数 product里(自动绑定)
注: 参数product会默认被当做值加入到ModelAndView 中,相当于:
`mav.addObject("product",product);`
~~~
package com.dodoke.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.dodoke.pojo.Product;
@Controller
public class ProductController {
@RequestMapping("/addProduct")
public ModelAndView add(Product product) throws Exception {
ModelAndView mav = new ModelAndView("showProduct");
return mav;
}
}
~~~
## 步骤 7 : showProduct.jsp
在WEB-INF/page 目录下创建 showProduct.jsp
用 EL 表达式显示用户提交的名称和价格
~~~
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
产品名称:${product.name }
产品价格:${product.price }
</body>
</html>
~~~
## 步骤 8 : 测试
访问页面
`http://localhost:8080/springmvc/addProduct.jsp`
提交数据,显示结果
![](../images/Image021.png)
> 整体流程总结:
> `http://localhost:8080/springMVC/addProduct.jsp` --> addProduct.jsp --> form提交到"addProduct"对应的ProductController.add(Product product) --> ModelAndView mav = new ModelAndView("showProduct") --> 跳转到showProduct.jsp
## 常见问题
1. ${product} 从何而来?
>不是参数名称,而是参数类型的小写吧
比如参数写的是Product xxx,其实是把Product小写成product后默认放在mav里。
> 详细解释:
> add()方法的【参数类型】会自动转小驼峰并加入到 ModelAndView 中作为 addObject() 的【第一个参数】,相当于 addObject("theFirstParam", product);
>
> 综上:addObject 里第一个参数是根据 add() 的参数类型自动转成小驼峰命名,第二个参数是 add() 的参数名。
> 区分命名,举个极端的栗子就明白了,
~~~
// bean 部分代码
public class MyFuckingProduct {...}
// controller 部分代码
public ModelAndView add(MyFuckingProduct 随便写我写中文应该没人发现吧) {...}
// jsp 部分代码
${myFuckingProduct.name}
// controller 中相当于
mav.addObject("myFuckingProduct", 随便写我写中文应该没人发现吧);
~~~
> 大家注意 add() 方法的参数,参数名是什么根本不用管,瞎写一通 fhdhdfai2u3y,没有关系,因为默认的 addObject()方法第一个参数只跟你的参数类型有关系,第二个参数就是你瞎写的参数名。
> 相当于:addObject("myFuckingProduct", 随便写我写中文应该没人发现吧);
> 然后 EL 表达式写什么就很明了了。
2. 下列代码,是否可以自己定义addObject()?
~~~
public ModelAndView add(Product product) throws Exception {
ModelAndView mav = new ModelAndView("showProduct");
return mav;
}
~~~
> 可以,mav.addObject("product",product);省略了。如果你想改参数也可以,加上这个mv.addObject("pro",pro);
第一个product相当于键值对的键,第二个product就是你的对象。
在show页面 你就应该写 pro.属性了。
2. 请问在接收到两个参数后,控制器是怎么把名称和价格注入到product对象中的,好像没看到注解什么的,是默认会注入的吗?
> springmvc的工作模式是这样的,当他发现页面传递过来有参数name的时候,同时检测到参数的Product这个类,有setName方法,那么就会把参数name的值,注入到这个product对象里去了。默认是按属性名匹配的。
3. 为add增加一个Product类型的参数是不是就是“注入”的应用呢?学到这个地方总感觉怪怪的,为什么要通过参数注入呢?直接在方法内部实例化这个对象不就得了?
> 在方法参数上注入,那么在方法里就可以直接使用该对象了。 而不需要向servlet那样,自己手动去实例化一个对象,手动获取request.getParameter("name"),手动设置在实例上。
> 这恰恰就是springmvc提高效率的地方,开发人员只需要关注在业务代码上面,其他的都交给框架做掉了。
4. @RequestMapping("/addProduct") 作用
>这里面的"/addProduct"是匹配请求路径,你的form表单提交时候你的action是addProduct,那么提交就会生成 /addProduct 这个请求的url,然后被你的requestMapping("/addProduct")匹配到,它就执行这个方法。