SpringMVC数据传输&ModelAttribute注解详细说明
** 测试ModelAttribute注解;**
package com.pzx.controller;
import com.pzx.bean.Book;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Map;
/**
* Created with IntelliJ IDEA.
* @Author: pzx
* @Date: 2021/08/19 17:52
* @Version:1.0
*
* 测试ModelAttribute注解;
* 使用场景;以书城的图书修改为例;
* 1)、页面端;
* 显示要修改的图书信息,图书的所有字段都在
*2)、servlet收到请求调用dao:
* String sql = "update bs_book set title=? ,
* author=?,price=?
* ,sales=?,stock=?,img_path=?
* where id =?"
* 3)实际场景?
* 并不是全字段修改;只会修改部分字符按,已修改用户信息为例
* username password address
* 1)、不修改的字段可以在页面展示,但是不要提供修改输入框;
* 2)、为了简单,Controller直接在参数位置来写Book对象
* 3)、SpringMVC为我们自动封装book;(没有带的值是null)
* 4)、如果接下来调用了一个全字段更新的dao操作;会将其他的字段变成null;
* sql="update bs_book set"
* if(book.getBookName()){
* sql +="bookName=?,"
* }
*
* if(book.getPrice()){
* sql +="price=?"
* }
*
*4)、如何能保证全字段更新的时候,只更新了页面携带的数据
* 1)、修改dao:代价太大
* 2)、Book对象是如何封装的?
* 1)、SpringMVC创建一个book对象,bookName默认就是null;
* 1、让SpringMVC别创建对象,直接从数据库中先取出id等于100的book的信息
* 2、Book{id=100, bookName='西游记', author='彭着想', stock=200000, sales=19999}
* 2)、将请求中所有的book对应的属性一一设置过来;
* 3、使用刚才从数据库中取出的book对象,给他设置值;(请求参数带了哪些就覆盖之前的值)
* 4、带了的字段就改为携带的值,没带的字段就保持之前的值
*
* 3)、调用全字段更新就有问题;
* 5、将之前从数据库中查到的对象,并且封装到请求参数的对象。进行保存;
*
*
*
*
*
*/
@Controller
public class ModelAttributeTestController {
private Object object1;
private Object object2;
private Object b1;
private Object b2;
/**
* 可以告诉SpringMVC不要new这个book了,我刚才保存了一个book
* 那个就是从数据库中查询出来的;用我这个book?
*
* 同是BindingAwareModelMap
*
* @param book
* @return
*/
@RequestMapping("/updateBook")
public String updateBook(@ModelAttribute("book") Book book, Map<String,Object> map) {
object2 = map;
Object book1 = map.get("book");
b2=book;
System.out.println("传入的model" + map.getClass());
System.out.println("object1==object2?" + (object1 == object2));
System.out.println("b1==b2?" + (b1 == b2)+"--------------->b2==book1"+(b2==book1));
System.out.println("页面提交过来的图书信息:" + book);
//bookDao.update(book);
//Book{id=100, bookName='null', author='彭着想', stock=200000, sales=19999}
/**
* * String sql = "update bs_book set title=? ,
* * author=?,price=?
* * ,sales=?,stock=?,img_path=?
* * where id =?"
*/
return "success";
}
/**
*
* 1)、SpringMVC要封装请求参数的Book对象不应该是自己去new对象。
* 而应该是【从数据库中】拿到的准备好的对象
*2)、再来使用这个对象来封装请求参数
*
*
*
* ModelAttribute
* 能够标在:
* 参数位置:取出刚才保存的数据
* 方法位置:这个方法就会提前于目标方法先运行
* 1)、 @ModelAttribute 我们可以在这里提前查出数据库中图书的信息
* 2)、将这个图书信息保存起来(方便下一个方法使用)
*
*/
@ModelAttribute
public void hahaMyModelAttribute(Map<String,Object> map) {
Book book = new Book(100, "西游记", "吴承恩", 12.58, 1000, 100);
System.out.println("数据库中查到的图书信息是" + book);
map.put("book", book);
object1 = map;
b1=book;
System.out.println("ModelAttribute方法....查询了图书并且保存了起来...他用的map类型" + map.getClass());
}
}
SpringMVC数据传输
package com.pzx.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
import java.util.Map;
/**
* Created with IntelliJ IDEA.
* @Author: pzx
* @Date: 2021/08/19 13:07
* @Version:1.0
*
*SpringMVC除过传入原生的request和session还能怎么样把数据带给页面
*
* 1)、可以在方法处传入Map或者Model或者ModelMap。
* 给这些参数保存的数据都会放在域中。可以在页面获取(最终都放在了请求域中了)
* 关系:
* Map,Model,ModelMap:最终都是BindingAwareModelMap在工作;
* 相当于BindingAwareModelMap中保存的东西都会放在请求域中;
*
* Map(interface(jdk)) Model(interface(Spring))
* || //
* || //
* \/ //
* ModelMap(class) //
* \\ //
* \\ //
* \\ //
* ExtendedModelMap
* ||
* \/
* BindingAwareModelMap
*
*
*2)、方法的返回值可以变为ModelAndView类型;
* 既包含视图信息(页面地址)也包含模型信息(给页面带的数据);
* 而且数据是放在请求域中的;
* request,session,application
*
*3)、SpringMVC提供了一种可以提供给Session域中保存数据的方式
* 使用一个注解 @SessionAttributes(只能标在类上)
*@SessionAttributes(value = "msg"):
* 给BindingAwareModelMap中保存的数据,或者是ModelAndView中的数据同时给session中放一份
* value指定保存数据时要给session中放的key
* value={"msg"}:只要保存的是key的数据,给session中放一份
* types = {String.class}:只要保存的是这种类型的时候,给session也放一份
*
* 后来推荐@SessionAttributes别用了,可能会引发异常;
* 给session中放数据请使用原生的API;
*
*
*
*/
@Controller
@SessionAttributes(value = {"hah","msg"},types = {String.class})
public class OutputController {
@RequestMapping("/handle01")
public String handle01(Map<String,Object> map){
map.put("msg","你好");
map.put("hah","哈哈哈哈,傻逼");
System.out.println("map的类型"+map.getClass());
return "success";
}
/**
*
* @param model
* @return
*/
@RequestMapping("/handle02")
public String handle02(Model model){
model.addAttribute("msg","你好坏!");
model.addAttribute("hah",18);
System.out.println("model的类型"+model.getClass());
return "success";
}
@RequestMapping("/handle03")
public String handle03(ModelMap modelMap){
modelMap.addAttribute("msg","你好骚!");
System.out.println("modelMap的类型"+modelMap.getClass());
return "success";
}
/**
* 返回值是ModelAndView;可以为页面携带数据
* @param modelMap
* @return
*/
@RequestMapping("/handle04")
public ModelAndView handle04(ModelMap modelMap){
//之前的返回值就叫视图名;视图名视图解析器会帮我们最终拼串得到页面的真实地址
//这个success就是要跳转的页面
// ModelAndView mv = new ModelAndView("success");
ModelAndView mv = new ModelAndView();
mv.setViewName("success");
mv.addObject("msg","你好肿瘤君!");
return mv;
}
}