SpringMVC框架之第二篇

6.参数绑定(重点)
        Springmvc作为表现层框架,是连接页面和service层的桥梁,它负责所有请求的中转。怎么从请求中接收参数是重点,这也体现了我们刚开始说的Springmvc的第一个作用:“接收请求中的参数”。
        接收的参数具体有哪些类型呢?6.1~6.5是绝大部分参数绑定的类型,还有两种第二天课程讲。
        6.1.简述参数绑定的类型
        1.默认支持的参数类型:HttpServletRequest,HttpServletResponse,HttpSession,Model
        2.简单类型:String,long,double,boolean,Integer, Long等
        3.POJO类型
        4.POJO的包装类型-QueryVo
        5.自定义转换器Converter:适合参数在传入方法前做事前加工,比如不能自动完成的类型转换,去空格等。

        6.2.需求
        前面我们做完了商品列表画面的展示,下面继续做修改页面和保存修改。
        【修改页面】:在列表页面点击一条数据的【修改】,根据id查询这条数据的详细信息,然后显示在修改页面
        【保存修改】:在修改页面修改信息,然后点【保存】,把信息存到数据库,保存成功迁移到success页面。(正常保存完应该返回列表页面,但我们先做的简单一点,就暂时迁移到success页面。)
        下面我们就利用这个修改的业务需求来逐个演示各种参数绑定方法。
        6.3.业务实现的代码规划
        ·默认支持的参数类型实现【修改页面】显示;
        ·简单类型实现【保存修改】功能;
        ·POJO类型改进【保存修改】功能;
        ·针对日期类型,利用自定义转换器Converter实现字符串到日期类型转换,进一步完善【保存修改】功能;
        ·POJO的包装类型-QueryVo简单说明综合查询业务的综合查询条件的传递。
        6.4.默认支持的参数类型
        6.4.1.啥是默认支持的参数类型
        所谓默认支持的参数类型就是传不传它们都会存在的参数,想用时就在Controller方法中定义即可,用哪个定义哪个,不用不定义。
        默认参数有:
        HttpServletRequest:通过request对象获取请求信息
        HttpServletResponse:通过response处理响应信息
        HttpSession:通过session对象得到session中存放的对象
        Model:通过Model参数返回需要传递给页面的数据。
        注意:如果使用Model参数给页面传值,那方法的返回值可以不使用ModelAndView对象而只返回一个逻辑视图名(String字符串),此时返回的字符串会走视图解析器解析生成View对象。
        无论Springmvc怎样对结果和返回值进行处理封装,其本质都是使用Request对象向jsp传递数据。

        6.4.2.演示代码
        1.【itemList.jsp】的【修改】:

        2.【ItemsController.java】新定义一个方法
        <说明>
        ·HttpServletRequest:
        可以接收页面传递过来的参数。
        ·Model:前面讲过,略
            /**
             * 演示默认支持的类型参数:HttpServletRequest、HttpServletResponse、HttpSession、Model
             * 默认支持的参数类型就是传不传它们都存在的参数,想用时就在Controller方法中定义即可,
             * 用哪个就定义哪个,不用就不定义。
             */
            @RequestMapping("/toEdit")
            public String itemEdit(HttpServletRequest request, Model model) throws Exception {
                // 取得页面传过来的主键id
                Integer id = Integer.valueOf(request.getParameter("id"));
                Items itemsResult = itemsService.getItemsDetailById(id);
                // 设置返回给页面的数据
                model.addAttribute("item", itemsResult);
                // 返回页面的逻辑视图名
                return "editItem";
            }
        3.【ItemsService.java】新定义一个接口
            public Items findItemsById(Integer id) throws Exception;
        4.【ItemsServiceImpl.java】实现上面的接口方法
            public Items findItemsById(Integer id) throws Exception {
                Items items = itemsMapper.selectByPrimaryKey(id);
                return items;
            }   
        5.访问【http://localhost:8080/ssm2/list.action】,点击【修改】
        6.将返回页面的数据和返回页面的地址合体返回:
        SpringMVC提供一种专门用于Handler返回结果的类:ModelAndView(模型和视图类)。它相当于把Model类和视图路径字符串合并在一起返回。SpringMVC拿到这个类对象后仍然会调度视图解析器来解析这个视图文件路径,并把数据给刚由视图解析器生成的视图对象,由它执行页面的渲染。
        改造上面的方法:
            /**
             * 演示默认支持的类型参数:HttpServletRequest、HttpServletResponse、HttpSession、Model
             * 默认支持的参数类型就是传不传它们都存在的参数,想用时就在Controller方法中定义即可,
             * 用哪个就定义哪个,不用就不定义。
             */
            @RequestMapping("/toEdit")
            public ModelAndView itemEdit(HttpServletRequest request, Model model) throws Exception {
                // 取得页面传过来的主键id
                Integer id = Integer.valueOf(request.getParameter("id"));
                Items itemsResult = itemsService.getItemsDetailById(id);

                ModelAndView modelAndView = new ModelAndView();
                // 1. 设置返回页面需要的数据
                // 第一个参数是属性名称, 第二个参数是属性值
                modelAndView.addObject("item", itemsResult);
                // 2. 指定返回页面的地址
                modelAndView.setViewName("editItem");
                
                return modelAndView;
            }   
        项目实在中经常使用的还是直接返回字符串的那种,这个返回ModelAndView的不太常用。




        6.5.简单类型
        默认参数类型有一个缺点:用request.getParameter来取值可能需要额外的类型转换,从String转成其他类型。
        Springmvc可不可以直接接收这些类型的参数呢?答案是可以的,即直接接收简单类型的参数。Springmvc不仅可以直接接收多个简单类型参数,还可以自动进行简单的类型转换。
        6.5.1.简单类型就是java的简单类型
        例如:String、double、long、Integer、Boolean等。
        6.5.2.传参规范
        页面上input框的name属性值必须等于controller方法中接收时的参数名称
        6.5.3.演示代码
        1.从【资料\参考案例\jsp】中导入【editItem.jsp】到工程的jsp目录下。
        2.【ItemsController.java】新定义一个方法
            /**
             * 演示接收简单类型:String, Integer, Double, Boolean等
             * 要求:页面上input框的name属性值必须等于controller方法中接收时的参数的变量名称
             */
            @RequestMapping("/itemUpdate")
            public String itemUpdate(Integer id, String name, Float price, String detail) 
                    throws Exception {
                Items items = new Items();
                items.setId(id);
                items.setName(name);
                items.setPrice(price);
                items.setDetail(detail);
                itemsService.updateItems(items);
                return "success";
            }   
        3.【ItemsService.java】新定义一个接口
            public void updateItems(Items items) throws Exception;

        4.【ItemsServiceImpl.java】实现上面的接口方法
            public void updateItems(Items items) throws Exception {
                itemsMapper.updateByPrimaryKeySelective(items);
            }
        5.从【资料\参考案例\jsp】中导入【success.jsp】到工程的jsp目录下。
        6.进入修改页面修改信息并保存。
        6.5.4.解决post提交乱码问题
        web页面默认的编码是ISO8859-1,但这个编码不支持汉字,所以汉字参数传递过来会出现乱码。
        post请求乱码的解决方法:在web.xml中加一个过滤器解决。
        
        
        。。。。
            
            
                CharacterEncodingFilter
                org.springframework.web.filter.CharacterEncodingFilter
                
                    encoding
                    utf-8
                
            
            
                CharacterEncodingFilter
                /*
            
        。。。。
        

        6.5.5.解决get提交乱码问题
        对于get请求中文参数出现乱码解决方法有两个:
        1.修改tomcat配置文件【server.xml】添加编码与工程编码一致,如下:(常用)

        2.另外一种方法对参数进行重新编码:

        6.6.POJO类型
        实现对修改保存的改进,适应参数个数的变化,几十上百个参数时候是绝对不可能用简单类型传递参数的。
        6.6.1.传参规范
        页面中input框的name属性值必须等于Controller方法接收时的POJO参数中的属性名称
        6.6.2.演示代码
        【ItemsController.java】新定义一个保存更新的方法,将旧的注释掉
            /**
             * 演示接收简单类型:String, Integer, Double, Boolean等
             * 要求:页面上input框的name属性值必须等于controller方法中接收时的参数的变量名称
             */
        //  @RequestMapping("/itemUpdate")
        //  public String itemUpdate(Integer id, String name, Float price, String detail) 
        //          throws Exception {
        //      Items items = new Items();
        //      items.setId(id);
        //      items.setName(name);
        //      items.setPrice(price);
        //      items.setDetail(detail);
        //      items.setCreatetime(new Date());
        //      itemsService.updateItems(items);
        //      return "success";
        //  }
            
            /**
             * 演示接收POJO类型的参数
             * 要求:页面上input框的name属性值必须等于pojo中的属性名称
             * 
             * @return
             * @throws Exception
             */
            @RequestMapping("/itemUpdate")
            public String itemUpdate(Items items) 
                    throws Exception {
                itemsService.updateItems(items);
                return "success";

            }

        6.7.POJO的包装类型-QueryVo
        我们要想在列表页面加一个综合查询功能,查询条件可能有商品信息、用户信息、订单信息,因此我们需要一个QueryVo来包装这些查询信息。那如何传递包装的参数呢?
        6.7.1.传参规范
        页面中input框的name属性值必须等于Controller方法接收时的Vo参数中的属性.属性.属性....,即各层的属性名要相等。
        6.7.2.演示代码
        1.新定义【QueryVo.java】
        package cn.baidu.pojo;

        public class QueryVo {
            
            // 用户对象
            // ......
            // 订单对象
            // ......
            
            // 商品对象
            private Items items;

            public Items getItems() {
                return items;
            }

            public void setItems(Items items) {
                this.items = items;
            }
        }
        2.【itemList.jsp】中增加两个查询条件作为POJO的包装类型的示范说明:控件name属性的名称要符合要求。
        <%@ page language="java" contentType="text/html; charset=UTF-8"
            pageEncoding="UTF-8"%>
        <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
        <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt"%>
        
        
        
        
        查询商品列表
        
         
        
查询条件:
商品名称: 商品价格:
商品列表:
商品名称 商品价格 生产日期 商品描述 操作
${item.name } ${item.price } ${item.detail } 修改
3.【ItemsController.java】新定义一个方法,这里不做具体的查询过滤,我们主要学习的是参数的传递。 /** * 演示接收POJO的包装类型 - QueryVo * 要求: 页面上input框的name属性值必须等于POJO中属性.属性.属性..... * * @param vo * @return * @throws Exception */ @RequestMapping("/search") public String searchItems(QueryVo vo) throws Exception { System.out.println(vo); return "success"; } 6.8.自定义转换器Converter 前台传递的是一个时间格式的字符串,后台数据库存储的是一个日期类型的数据,需要转换,但自动转换会报错(可以试一试)。为了转换需要自定义转换器。 6.8.1.自定义转换器的作用 参数传递到方法之前的统一加工处理。 应用:最多的应用就是复杂类型转换、再有就是去掉金钱中的千分符等。比如:在Springmvc中接收参数时可以自动进行简单类型的类型转换,但是像String转Date这种复杂的类型转换,Springmvc不能自动完成,所以需要手动编写Converter转换器,来进行类型转换。 6.8.2.演示代码 1.将【editItem.jsp】中的【商品生产日期】项目的注释打开 2.自定义转换器Converter Converter的包名可以随意,我们这里定义一个全局的String到Date的转换器。 都要继承【Converter】接口,【S - source源的类型】,【T - target目标的类型】,我们这里的S是String,T是Date。 package cn.baidu.controller.converter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.core.convert.converter.Converter; /** * S - source源的类型 * T - target目标的类型 * @author Derek Sun */ public class CustomGlobalStrToDateConverter implements Converter { public Date convert(String source) { try { Date date = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(source); return date; } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } } 3.Converter的配置方式: 【SpringMVC.xml】 4.Converter的配置方式2(了解) 这种方式放到工程里不好用,就是用来理解Converter具体作用在处理器适配器上。 注意:此方法需要独立配置处理器映射器、适配器,不再使用 5. 【ItemsController.java】 /** * 演示接收POJO类型的参数 * 要求:页面上input框的name属性值必须等于pojo中的属性名称 */ @RequestMapping("/itemUpdate") public String itemUpdate(Items items) throws Exception { itemsService.updateItems(items); return "success"; } 再次启动运行。 5.仅仅是做一个日期类型的转化可以不用自定义转换器,还有一种更简单的做法:直接在pojo对应的日期属性变量上面加注解 @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss"),因此SpringMVC.xml恢复原来的配置 【SpringMVC.xml】 【Items.java】在pojo中对应的日期属性变量上使用注解@DateTimeFormat public class Items { 。。。。。。 @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") private Date createtime; 。。。。。。 } 启动测试,这样也是可以进行String到Date的类型转换的。 注意格式:【yyyy-MM-dd HH:mm:ss】 6.9.本节重点 要想顺利的保证前台的数据传到后台,在使用SpringMVC框架的前提下就要遵守SpringMVC传参的规范,具体规范如下: 1.默认支持的参数类型:HttpServletRequest,HttpServletResponse,HttpSession,Model。用哪个就在方法的形参中定义哪个,不用的不定义。 2.简单类型:String,long,double,boolean,Integer等 要求:页面中input框的name属性值必须等于Controller方法接收时的参数名称。 适合单个或少数参数的请求 3.POJO类型 要求:页面中input框的name属性值必须等于Controller方法接收时的POJO参数中的属性名称。 适合更新、插入操作。 4.POJO的包装类型-QueryVo 要求: 页面中input框的name属性值必须等于Controller方法接收时的Vo参数中的属性.属性.属性.... 适合综合查询。 5.自定义转换器Converter 作用:参数传递到方法之前的统一加工处理。 应用:复杂类型转换、去空格, 去钱的千分符等 7.Springmvc与Struts2区别 1.入口不同: springmvc的入口是一个servlet即前端控制器,而struts2入口是一个filter过虑器。 2.请求的拦截级别: Struts2是类级别的拦截,一个Action类对应一个request上下文; SpringMVC是方法级别的拦截,一个Controller类的方法对应一个request上下文。 3.单例与多例: Struts2是基于类开发,传递参数是通过Action类的属性,只能设计为多例。 Springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(默认是单例)。 4.接收参数和返回数据: Struts接收的请求参数存放于Action的属性中,是诸多方法共享的,程序可读性差。Struts采用值栈存储请求和响应的数据,通过OGNL存取数据;值栈存储方式太过原始。 Springmvc通过参数解析器是将request请求内容解析并给方法形参赋值,即请求参数是方法之间独立的。Springmvc对数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques对象传输到页面。 SSM整合思路 : web系统结构分为:三层 Controller层---> Service层---> Dao层 代码的目录结构: Controller层 controller目录:用@Controller注解修饰的类——SpringMVC的后端控制器(手动编写) Service层 service目录:用@Service注解修饰的类——业务处理模型(手动编写) Dao层 dao目录:mybatis动态代理扫描 利用mybatis逆向工程生成dao接口和映射文件 pojo目录:利用mybatis逆向工程生成pojo 配置文件的目录: config目录: SpringMVC的配置文件——SpringMVC.xml Controller层注解扫描,注解驱动,视图解析器(可能带有前缀和后缀) spring的配置文件 Service层注解扫描,事务管理——ApplicationContext-service.xml mybatis整合(整合会话工厂、动态代理的包扫描)——ApplicationContext-dao.xml mybatis的配置文件——MybatisConfig.xml 暂时保留一个空的配置文件——保留一个空的配置文件是为了将来好扩展 一些properties属性文件(日志,jdbc) web.xml——是java web的唯一入口 spring的监听 SpringMVC的前端控制器

你可能感兴趣的:(SpringMVC框架之第二篇)