SpringMVC页面向controller层传值的自动映射条件,
表单的name值与参数名对应,或使用注解@RequestParam进行对象,或与对象中的属性名对应,并且需要提供setter方法,才能完成参数的赋值,其中是如何进行赋值的过程我们并不知道吗、,也不关心,只知道、如何去使用它就够了,这也就是我们学习效率不高的原因,只知其然,不知其所以然
下面是模拟springMVC向入参为对象中映射值的过程,从此不在Servlet中使用request.getParameter;
条件:
- 表单name属性的值必须与对象属性名相同
- 必须提供属性公共的setter方法
在学习的过程中我们要常保持疑问,带着问题去学习,如果你连疑问都没有,那你自然就不知道你想要的答案是什么,没有想要的答案,也就没有学习的价值,先声明你的疑问,再去学习,
疑问:就是为什么需要这两个条件成立
准备代码:一个实体类,一个表单,一个servlet,
package com.entity;
import java.util.Date;
/**
*实体类,将参数值保存在此对象中
*/
public class Student {
private String name;
private Integer age;
private Double score;
private Date birthDay;
public Date getBirthDay() {
return birthDay;
}
public void setBirthDay(Date birthDay) {
this.birthDay = birthDay;
}
public Student() {
System.out.println("Student的无参构造");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
System.out.println("setName--------》");
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
", birthDay=" + birthDay +
'}';
}
}
表单 ,注:此处使用的是jsp,name值都与实体类中的属性名对应
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="studentServlet" method="post">
name: <input type="text" name="name"><br>
age:<input type="text" name="age"><br>
score:<input type="text" name="score"><br>
birthDay: <input type="text" name="birthDay"><br>
<input type="submit" value="提交"><br>
</form>
</body>
</html>
在参数自动映射中,我们也只能在Servlet中进行做文章了,为了代码的重用性,我将参数自动映射功能,封装成一个方法,想要使用只需要将此类拷贝即可,方法的具体内容:
package com.utils;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Enumeration;
public class BeanOperateTools {
/**
* 该方法是由Servlet调用
* 具体实现的参数封装方法
* @param obj 要将表单值封装至的对象
* @param req request对象,包含我们表单请求来的数据
* @throws Exception 可能抛出的异常
*/
public static void setValueSimple(Object obj, HttpServletRequest req) throws Exception {
//得到实体类的类信息
Class<?> cls = obj.getClass();
//获取所有的参数名称
Enumeration<String> enu = req.getParameterNames();
//遍历参数名称
while (enu.hasMoreElements()){
//获取参数名称
String paramName = enu.nextElement();
//获取对应的参数名称的值
String paramValue = req.getParameter(paramName);
//进行判断当前文本框是否填写值,没有值就跳过此属性值的封装
if("".equals(paramValue) || null==paramValue){
continue;
}
/*根据表单的name值类取得对应的属性,这就是
为什么需要我们表单的name值要与实体类的属性
名对应的原因,我们可以根据这个属性的类型,来
确定setter方法的参数类型,并确定是否需要进
行类型装换*/
Field field = cls.getDeclaredField(paramName);
//获取参数类型,没有包名,getSimpleName()此方法是去除包名的
String fieldType
=field.getType().getSimpleName();
/*获取指定的操作方法,以满足反射的调用
使用字符串set+属性名的方式,并把属性的首字母
大写,正好对应我们属相的setter方法,参数类型
就是上面的field
*/
Method method = cls.getMethod("set"+initcap(paramName), field.getType());
//此处进行判断是否需要进行类型的转换
if("String".equals(fieldType)){
//执行具体set方法,并传入具体值
method.invoke(obj, paramValue);
}else if("Integer".equals(fieldType) || "int".equals(fieldType)){
method.invoke(obj,Integer.parseInt(paramValue));
}else if("Double".equals(fieldType) || "double".equals(fieldType)){
method.invoke(obj,Double.parseDouble(paramValue));
}else if("Date".equals(fieldType)){
method.invoke(obj,new SimpleDateFormat("yyyy-MM-dd").parse(paramValue));
}
}
}
//将属性名的首字母大写
private static String initcap(String value){
return value.substring(0,1).toUpperCase().concat(value.substring(1));
}
}
参数封装方法已完成,只需要在Servlet中调用即可
package com.servlet;
import com.entity.Student;
import com.utils.BeanOperateTools;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "StudentServlet", urlPatterns = {
"/studentServlet"})
public class StudentServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
//要存储表单数据的对象
Student stu = new Student();
try {
//直接调用,传入要存储表单数据的对象,和request
BeanOperateTools.setValueSimple(stu,req);
} catch (Exception e){
e.printStackTrace();
}
//将封好的数据存入request中,
req.setAttribute("stu",stu);
//跳转页面,查看封装的数据是否正确
req.getRequestDispatcher("show.jsp").forward(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
}
show.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${stu}
</body>
</html>
写完这些我们在看一下springMVC的参数自动映射的条件:
- 表单name属性的值必须与对象属性名相同
- 必须提供属性公共的setter方法
现在知道为什么了吗!
参数自动映射的具体过程,大致就这些,不知道你看明白了吗,当然,我们所写的与springMVC的相比,那就是,小巫見大巫、木棍挑战坦克,重申:此文章,只是让我们能够了解springMVC在进行参数封装的过程,对框架能够有一个更加深层的认知