Spring MVC 复习笔记04

复习

springmvc框架:

         DispatcherServlet前端控制器:接收request,进行response

         HandlerMapping处理器映射器:根据url查找Handler。(可以通过xml配置方式,注解方式)

         HandlerAdapter处理器适配器:根据特定规则去执行Handler,编写Handler时需要按照HandlerAdapter的要求去编写。

         Handler处理器(后端控制器):需要程序员去编写,常用注解开发方式。

               Handler处理器执行后结果 是ModelAndView,具体开发时Handler返回方法值类型包括 :ModelAndView、String(逻辑视图名)、void(通过在Handler形参中添加request和response,类似原始

               servlet开发方式,注意:可以通过指定response响应的结果类型实现json数据输出)

         View resolver视图解析器:根据逻辑视图名生成真正的视图(在springmvc中使用View对象表示)

         View视图:jsp页面,仅是数据展示,没有业务逻辑。

注解开发:

         使用注解方式的处理器映射器和适配器:

         <!--注解映射器 -->

        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

        <!--注解适配器 -->

        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

        在实际开发,使用<mvc:annotation-driven>代替上边处理器映射器和适配器配置。

@controller注解必须要加,作用标识类是一个Handler处理器。

@requestMapping注解必须要加,作用:

         1、对url和Handler的方法进行映射。

         2、可以窄化请求映射,设置Handler的根路径,url就是根路径+子路径请求方式

         3、可以限制http请求的方法

映射成功后,springmvc框架生成一个Handler对象,对象中只包括 一个映射成功的method。

注解开发中参数绑定:

         将request请求过来的key/value的数据(理解一个串),通过转换(参数绑定的一部分),将key/value串转成形参,将转换后的结果传给形参(整个参数绑定过程)。

         springmvc所支持参数绑定:

                  1、默认支持很多类型,HttpServletRequest、response、session、

                          model/modelMap(将模型数据填充到request域)

                  2、支持简单数据类型,整型、字符串、日期。。

                          只要保证request请求的参数名和形参名称一致,自动绑定成功

                          如果request请求的参数名和形参名称不一致,可以使用@RequestParam(指定request请求的参数名),@RequestParam加在形参的前边。

                  3、支持pojo类型

                          只要保证request请求的参数名称和pojo中的属性名一致,自动将request请求的参数设置到pojo的属性中。

                  注意:形参中即有pojo类型又有简单类型,参数绑定互不影响。

                  自定义参数绑定:

                          日期类型绑定自定义:

                                   定义的Converter<源类型,目标类型>接口实现类,比如:

                                   Converter<String,Date>表示:将请求的日期数据串转成java中的日期类型。

                                   注意:要转换的目标类型一定和接收的pojo中的属性类型一致。

                                   将定义的Converter实现类注入到处理器适配器中。

                                   <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

                                   <!-- conversionService -->

                                   <bean id="conversionService"  class="org.springframework.format.support.FormattingConversionServiceFactoryBean">

                                            <!-- 转换器 -->

                                           <property name="converters">

                                                   <list>

                                                              <bean class="cn.itcast.ssm.controller.converter.CustomDateConverter"/>

                                                   </list>

                                           </property>

                                   </bean>

springmvc和struts2区别:

springmvc面向方法开发的(更接近service接口的开发方式),struts2面向类开发。

springmvc可以单例开发,struts2只能是多例开发。

1. 包装类型pojo参数绑定

    第一种方法:在形参中 添加HttpServletRequest request参数,通过request接收查询条件参数。

    第二种方法:在形参中让包装类型的pojo接收查询条件参数。

    页面参数和controller方法形参定义

    页面参数:

         商品名称:<input name="itemsCustom.name" />

         注意:itemsCustom和包装pojo中的属性一致即可。

     controller方法形参:

         public ModelAndView queryItems(HttpServletRequest request,ItemsQueryVo itemsQueryVo) throws Exception

     

2. 集合类型绑定

    1). 数组绑定:

         controller方法定义:

         

         页面定义:         

         

      2). list绑定:

           

           

         

      3). map 绑定:

           也通过在包装pojo中定义map类型属性。

           在包装类中定义Map对象,并添加get/set方法,action使用包装对象接收。

           包装类中定义Map对象如下:

           Public class QueryVo { 

                    private Map<String, Object> itemInfo = new HashMap<String, Object>();

                     //get/set方法..

           }

           页面定义如下:

           <tr>

                <td>学生信息:</td>

                <td>姓名:<inputtype="text"name="itemInfo['name']"/>

                       年龄:<inputtype="text"name="itemInfo['price']"/>

                       .. .. ..

                </td>

           </tr>

           Contrller方法定义如下:

           public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{

                       System.out.println(queryVo.getStudentinfo());

           }

4. spring 校验

    1). 校验理解

         项目中,通常使用较多是前端的校验,比如页面中js校验。对于安全要求较高点建议在服务端进行校验。

         服务端校验:

         a. 控制层conroller:校验页面请求的参数的合法性。在服务端控制层conroller校验,不区分客户端类型(浏览器、手机客户端、远程调用)

         b. 业务层service(使用较多):主要校验关键业务参数,仅限于service接口中使用的参数。

         c. 持久层dao:一般是不校验的。

    2). springmvc校验需求

         springmvc使用hibernate的校验框架validation(和hibernate没有任何关系)。

         校验思路:

               页面提交请求的参数,请求到controller方法中,使用validation进行校验。如果校验出错,将错误信息展示到页面。

     3). 环境准备

               hibernate的校验框架validation所需要jar包:

               

     4). 配置校验器:

          

     5). 校验器注入到处理器适配器中

          

     6). 在pojo中添加校验规则

          在ItemsCustom.java中添加校验规则:

          

     7). CustomValidationMessages.properties

          在CustomValidationMessages.properties配置校验错误信息:

          

     8). 捕获校验错误信息

          

         //在需要校验的pojo前边添加@Validated,在需要校验的pojo后边添加BindingResult bindingResult接收校验出错信息

         //注意:@Validated和BindingResult bindingResult是配对出现,并且形参顺序是固定的(一前一后)

     9). 在页面显示校验错误信息

          在controller中将错误信息传到页面即可。

          

          页面显示错误信息:

          

    10). 分组校验

           a. 校验分组

           

           b. 在校验规则中添加分组

           

           c. 在controller方法使用指定分组的校验

            

5. 数据回显

    5.1 什么数据回显

          提交后,如果出现错误,将刚才提交的数据回显到刚才的提交页面。

    5.2 pojo数据回显方法

          1). springmvc默认对pojo数据进行回显。

               pojo数据传入controller方法后,springmvc自动将pojo数据放到request域,key等于pojo类型(首字母小写)

               使用@ModelAttribute指定pojo回显到页面在request中的key

          2). @ModelAttribute还可以将方法的返回值传到页面

               在商品查询列表页面,通过商品类型查询商品信息。

               在controller中定义商品类型查询方法,最终将商品类型传到页面。

               

          页面上可以得到itemTypes数据。

          

          使用最简单方法使用model,可以不用@ModelAttribute

          

      5.3 简单类型数据回显

            使用最简单方法使用model。

            model.addAttribute("id", id);

6. 异常处理

    6.1 异常处理思路

         系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。

         系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:

         

        springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。

    3.2 自定义异常类

          对不同的异常类型定义异常类,继承Exception。

          

     3.3 全局异常处理器

           思路:

           系统遇到异常,在程序中手动抛出,dao抛给service、service给controller、controller抛给前端控制器,前端控制器调用全局异常处理器。

           全局异常处理器处理思路:

                  解析出异常类型

                  如果该 异常类型是系统 自定义的异常,直接取出异常信息,在错误页面展示

                  如果该 异常类型不是系统 自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)

            springmvc提供一个HandlerExceptionResolver接口            

@Override
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {
        //handler就是处理器适配器要执行Handler对象(只有method)
        
//        解析出异常类型
//        如果该 异常类型是系统 自定义的异常,直接取出异常信息,在错误页面展示
//        String message = null;
//        if(ex instanceof CustomException){
//            message = ((CustomException)ex).getMessage();
//        }else{
////            如果该 异常类型不是系统 自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)
//            message="未知错误";
//        }
        
        //上边代码变为
        CustomException customException = null;
        if(ex instanceof CustomException){
            customException = (CustomException)ex;
        }else{
            customException = new CustomException("未知错误");
        }
        
        //错误信息
        String message = customException.getMessage();        
        
        ModelAndView modelAndView = new ModelAndView();
        
        //将错误信息传到页面
        modelAndView.addObject("message", message);
        
        //指向错误页面
        modelAndView.setViewName("error");

        return modelAndView;
    }

     6.4 错误页面

     

     6.5 在springmvc.xml配置全局异常处理器

     

     6.6 异常测试

           在controller、service、dao中任意一处需要手动抛出异常。

           如果是程序中手动抛出的异常,在错误页面中显示自定义的异常信息,如果不是手动抛出异常说明是一个运行时异常,在错误页面只显示“未知错误”。

           在商品修改的controller方法中抛出异常 .

           

           在service接口中抛出异常:

           

       如果与业务功能相关的异常,建议在service中抛出异常。

       与业务功能没有关系的异常,建议在controller中抛出。

       上边的功能,建议在service中抛出异常。

原文地址:https://www.cnblogs.com/Jtianlin/p/5224766.html