定义一个名为Problem实体类,如下:
public class Problem implements java.io.Serializable {
private static final long serialVersionUID = 5454155825314635342L;
/**
* id
*/
private java.lang.String id;
private java.lang.String problem;//问题描述
public Problem() {
// TODO 1. 看这里,虽然有一个缺省构造器
}
public Problem(java.lang.String id) {
this.id = id;//2. 这个构造器一般为程序开发时,快捷构造对象使用
}
public java.lang.String getId() {
return id;
}
public java.lang.String getProblem() {
return problem;
}
public void setProblem(java.lang.String problem) {
this.problem = problem;
}
}
因为设计时,就想着用户提的“问题内容”就用Problem类的problem属性保存。
请接口cotroller如下:
@Controller
@RequestMapping(value = "/test")
public class TestController extends BaseRestJSONController<CorpInfo, java.lang.String> {
static Logger log = LoggerFactory.getLogger(TestController.class);
@PostMapping("/problem")
public @ResponseBody MReturnObject person(Problem test) throws Exception {
return new MReturnObject(MReturnObject.ERROR, test);//3 按说test对象的id为null,test.problem的值为提交的内容
}
}
1.请求/test/problem提交参数时problem=小区大门坏了,3处打印应为test.id为null,test.problem为“小区大门坏了”。
2.实际3处spring封装的test对象的属性值是test.id为“小区大门坏了”,test.problem的值也为“小区大门坏了”。
问题分析:
参考了资料,主要是《精通Spring 4.x 企业应用开发实战》第17章节
17.3.2 数据转换
....
Java标准的PropertyEditor的核心功能是将一个字符串转换为一个Java对象,以便根据界面的输入或配置文件中的配置字符串构造出一一个JVM内部的Java对象。
但是Java原生的PropertyEditor存在以下不足:
只能用于字符串到Java对象的转换,不适用于任意两个Java类型之间的转换。
对源对象及目标对象所在的上下文信息(如注解、所在宿主类的结构等)不敏感,在类型转换时不能利用这些上下文信息实施高级的转换逻辑。
鉴于此,Spring 在核心模型中添加了-一个通用的类型转换模块,类型转换模块位于org.springframework. core.convert包中。Spring希望用这个类型转换体系替换Java标准的PropertyEditfor。但由于历史原因,Spring 将同时支持两者,在Bean配置、Spring MVC处理方法入参绑定中使用它们。
以上红色地方就说明了,当请求的参数名=入参对象定义的实体类名时,且该实体实现了“一个入参为字符串”的构造器,这时就会把problem的值(String)做为入参传入这个构造器反射生成对象,简单如下:
Problem problem=new Problem("小区大门坏了");//spring中是反射调用这个构造器,这里是形象说明问题,直接构造对象了
problem.setProblem("小区大门坏了");//此外为spring中生成对象后反射赋值。
所以虽然请求只提交了一个参数,但problem这两属性都赋了值。
1.如果Problem对象不定义一个“只含一个入参字符串”的构造器就不会产生上面的问题[上面实体赋值显然不是我们想要的结果]。
2.定义实体属性名时不要与实体名字相同。
3.提交的参数名不要与实体名相同[如果是为了业务或者利用这个现象另说],否则可能出其实现象。