数据输出:如何将数据带给页面
1 package com.atguigu.controller; 2 3 import java.util.Map; 4 5 import org.springframework.stereotype.Controller; 6 import org.springframework.ui.Model; 7 import org.springframework.ui.ModelMap; 8 import org.springframework.web.bind.annotation.RequestMapping; 9 import org.springframework.web.bind.annotation.SessionAttributes; 10 import org.springframework.web.servlet.ModelAndView; 11 12 /** 13 * SpringMVC除过在方法上传入原生的request和session外还能怎么样把数据带给页面 14 * 15 * 1)、可以在方法处传入Map、或者Model或者ModelMap。 16 * 给这些参数里面保存的所有数据都会放在请求域中。可以在页面获取 17 * 关系: 18 * Map,Model,ModelMap:最终都是BindingAwareModelMap在工作; 19 * 相当于给BindingAwareModelMap中保存的东西都会被放在请求域中; 20 * 21 * Map(interface(jdk)) Model(interface(spring)) 22 * || // 23 * || // 24 * / // 25 * ModelMap(clas) // 26 * \ // 27 * \ // 28 * ExtendedModelMap 29 * || 30 * / 31 * BindingAwareModelMap 32 * 33 * 2)、方法的返回值可以变为ModelAndView类型; 34 * 既包含视图信息(页面地址)也包含模型数据(给页面带的数据); 35 * 而且数据是放在请求域中; 36 * request、session、application; 37 * 38 * 3)、SpringMVC提供了一种可以临时给Session域中保存数据的方式; 39 * 使用一个注解 @SessionAttributes(只能标在类上) 40 * @SessionAttributes(value="msg"): 41 * 给BindingAwareModelMap中保存的数据,或者ModelAndView中的数据, 42 * 同时给session中放一份; 43 * value指定保存数据时要给session中放的数据的key; 44 * 45 * value={"msg"}:只要保存的是这种key的数据,给Session中放一份 46 * types={String.class}:只要保存的是这种类型的数据,给Session中也放一份 47 * 48 * 后来推荐@SessionAttributes就别用了,可能会引发异常; 49 * 给session中放数据请使用原生API; 50 * 51 * @author lfy 52 * 53 */ 54 @SessionAttributes(value={"msg"},types={String.class}) 55 @Controller 56 public class OutputController { 57 58 //args:如何确定目标方法每一个参数的值;最难? 59 // method.invoke(this,args) 60 @RequestMapping("/handle01") 61 public String handle01(Map<String, Object> map){ 62 map.put("msg", "你好"); 63 map.put("haha", "哈哈哈"); 64 System.out.println("map的类型:"+map.getClass()); 65 return "success"; 66 } 67 68 /** 69 * Model:一个接口 70 * @param model 71 * @return 72 */ 73 @RequestMapping("/handle02") 74 public String handle02(Model model){ 75 model.addAttribute("msg", "你好坏!"); 76 model.addAttribute("haha", 18); 77 System.out.println("model的类型:"+model.getClass()); 78 return "success"; 79 } 80 81 @RequestMapping("/handle03") 82 public String handle03(ModelMap modelMap){ 83 modelMap.addAttribute("msg", "你好棒!"); 84 System.out.println("modelmap的类型:"+modelMap.getClass()); 85 return "success"; 86 } 87 88 /** 89 * 返回值是ModelAndView;可以为页面携带数据 90 * @return 91 */ 92 @RequestMapping("/handle04") 93 public ModelAndView handle04(){ 94 //之前的返回值我们就叫视图名;视图名视图解析器是会帮我们最终拼串得到页面的真实地址; 95 //ModelAndView mv = new ModelAndView("success"); 96 ModelAndView mv = new ModelAndView(); 97 mv.setViewName("success"); 98 mv.addObject("msg", "你好哦!"); 99 return mv; 100 } 101 102 }
ModelAttribute(由于MyBatis的使用,该注解已经不常用了)
使用场景:
1)页面:
1 package com.atguigu.controller; 2 3 import java.util.Map; 4 5 import javax.servlet.http.HttpServletRequest; 6 7 import org.springframework.stereotype.Controller; 8 import org.springframework.ui.Model; 9 import org.springframework.web.bind.annotation.ModelAttribute; 10 import org.springframework.web.bind.annotation.RequestMapping; 11 import org.springframework.web.bind.annotation.RequestParam; 12 13 import com.atguigu.bean.Book; 14 15 /** 16 * 测试ModelAttribute注解; 17 * 使用场景:书城的图书修改为例; 18 * 1)页面端; 19 * 显示要修改的图书的信息,图书的所有字段都在 20 * 2)servlet收到修改请求,调用dao; 21 * String sql="update bs_book set title=?, 22 * author=?,price=?, 23 * sales=?,stock=?,img_path=? 24 * where id=?"; 25 * 3)实际场景? 26 * 并不是全字段修改;只会修改部分字段,以修改用户信息为例; 27 * username password address; 28 * 1)、不修改的字段可以在页面进行展示但是不要提供修改输入框; 29 * 2)、为了简单,Controller直接在参数位置来写Book对象 30 * 3)、SpringMVC为我们自动封装book;(没有带的值是null) 31 * 4)、如果接下来调用了一个全字段更新的dao操作;会将其他的字段可能变为null; 32 * sql = "update bs_book set" 33 * if(book.getBookName()){ 34 * sql +="bookName=?," 35 * } 36 * if(book.getPrice()){ 37 * sql +="price=?" 38 * } 39 * 40 * 4)、如何能保证全字段更新的时候,只更新了页面携带的数据; 41 * 1)、修改dao;代价大? 42 * 2)、Book对象是如何封装的? 43 * 1)、SpringMVC创建一个book对象,每个属性都有默认值,bookName就是null; 44 * 1、让SpringMVC别创建book对象,直接从数据库中先取出一个id=100的book对象的信息 45 * 2、Book [id=100, bookName=西游记, author=张三, stock=12, sales=32, price=98.98] 46 * 47 * 2)、将请求中所有与book对应的属性一一设置过来; 48 * 3、使用刚才从数据库取出的book对象,给它 的里面设置值;(请求参数带了哪些值就覆盖之前的值) 49 * 4、带了的字段就改为携带的值,没带的字段就保持之前的值 50 * 3)、调用全字段更新就有问题; 51 * 5、将之前从数据库中查到的对象,并且封装了请求参数的对象。进行保存; 52 * 53 */ 54 @Controller 55 public class ModelAttributeTestController { 56 57 private Object o1; 58 private Object o2; 59 60 private Object b1; 61 private Object b2; 62 63 //bookDao.update(book); 64 //Book [id=100, bookName=null, author=张三, stock=12, sales=32, price=98.98] 65 /** 66 * String sql="update bs_book set bookName=?, 67 author=?,price=?, 68 sales=?,stock=?,img_path=? 69 where id=?"; 70 */ 71 /** 72 * 可以告诉SpringMVC不要new这个book了我刚才保存了一个book; 73 * 哪个就是从数据库中查询出来的;用我这个book? 74 * 75 * 76 * 同都是BindingAwareModelMap 77 * @param book 78 * @return 79 */ 80 @RequestMapping("/updateBook") 81 public String updateBook(@RequestParam(value="author")String author, 82 Map<String, Object> model, 83 HttpServletRequest request, 84 @ModelAttribute("haha")Book book 85 ){ 86 o2 = model; 87 b2 = book; 88 Object haha = model.get("haha"); 89 //System.out.println("传入的model:"+model.getClass()); 90 System.out.println("o1==o2?"+(o1 == o2)); 91 System.out.println("b1==b2?"+(b1 == b2)+"-->"+(b2 == haha)); 92 93 System.out.println("页面要提交过来的图书信息:"+book); 94 return "success"; 95 } 96 97 /** 98 * 1)、SpringMVC要封装请求参数的Book对象不应该是自己new出来的。 99 * 而应该是【从数据库中】拿到的准备好的对象 100 * 2)、再来使用这个对象封装请求参数 101 * 102 * @ModelAttribute: 103 * 参数:取出刚才保存的数据 104 * 方法位置:这个方法就会提前于目标方法先运行; 105 * 1)我们可以在这里提前查出数据库中图书的信息 106 * 2)将这个图书信息保存起来(方便下一个方法还能使用) 107 * 108 * 参数的map:BindingAwareModelMap 109 */ 110 @ModelAttribute 111 public void hahaMyModelAttribute(Map<String, Object> map){ 112 113 Book book = new Book(100, "西游记", "吴承恩", 98, 10, 98.98); 114 System.out.println("数据库中查到的图书信息是:"+book); 115 map.put("haha", book); 116 b1 = book; 117 o1 = map; 118 System.out.println("modelAttribute方法...查询了图书并给你保存起来了...他用的map的类型:"+map.getClass()); 119 } 120 121 }