zoukankan      html  css  js  c++  java
  • springmvc总结

    1、SpringMVC 和 Struts2 对比

    ①、SpringMVC 的入口是 Servlet,而Struts2是Filter

    ②、SpringMVC会稍微比Struts2快些,SpringMVC是基于方法设计的,而Struts2是基于类设计的,每次发一次请求都会实例一个Action.

    ③、SpringMVC使用更加简洁,开发效率比Struts2高。支持JSR303,处理ajax的请求更方便

    ④、Struts2的OGNL表达式使页面的开发效率相比SpringMVC更高些。

    2、SpringMVC 和Spring 整合的问题

            是否还需要 整合spring?

            建议需要:通常情况下,类似于数据源,事务,整合其他框架都是放在Spring 的配置文件中

            (而不是放    在    SpringMVC        的        配        置文件中)

              实际上放入Spring配置文件对应的IOC容器中的还有Service 和 Dao.

              问题:若spring 的 IOC容器和SpringMVC 的 IOC 容器扫描的包有重合的部分,就会导致有的bean会被创建2次
                    解决:
                    1、使spring的IOC容器扫描的包和SpringMVC 的 IOC 容器扫描的包分开,没有重合的部分,
                    可是在实际开发中,如果按模块建包,则无法满足该情况
                    2、使用context:component-scan标签的context:exclude-filter、context:include-filter 
                    节点来规定只能扫描的注解
                    <context:component-scan base-package="com.test" use-default-filters="false">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
    </context:component-scan>

    springMVC 的 IOC 容器中的bean 可以来引用spring IOC容器中的bean,反之,则不行
    即 spring IOC容器中的bean不能引用springMVC IOC容器中的bean。

    因为 springMVC容器和spring容器有父子关系,spring容器为父容器,springMVC为子容器

    3、SpringMVC工作流程

    3、springMVC配置

    在web.xml中配置DispatcherServlet

    <!-- 配置DispatcherServlet -->
    <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:dispatcherServlet-servlet.xml</param-value>
    </init-param>

    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
    </servlet-mapping>
    <init-param>标签:

    springMVC配置文件默认在WEB-INF下,如果需要放在src下, 则需要在web.xml 配置DispatcherServlet中配置

    用<init-param>标签进行配置。

    注意:如果是用maven构建的项目,那么src目录是:src/main/resources(第一次用maven,在此折腾半天,才发现这个问题)

    <load-on-startup>1</load-on-startup>:表示在WEB容器启动时就实例化DispatcherServlet,而不是等到该servlet被选择时。正数数字越小,优先级越高。

    <url-pattern>/</url-pattern>:表示拦截所有的请求

    如果用到REST风格URL,还需在web.xml中配置HidddenHttpMethodFilter

    <!-- 配置HiddenHttpMethodFilter 作用可以把post请求转为delete或者put请求 -->
    <filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>
    然后配置springMVC配置文件

    注意该配置文件的名字格式为 <servlet-name>-servlet.xml

    <!-- 启用spring mvc 注解 -->
    <context:annotation-config></context:annotation-config>

    <!-- 需要扫描的spring控制类 -->
    <context:component-scan base-package="com.test"></context:component-scan>
    <context:component-scan base-package="com.cjl"></context:component-scan>


    <!-- 视图解析器配置:如何把handler方法返回的值解析为实际的物理视图(该解析器用于JSP页面) -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix">
    <value>/WEB-INF/views/</value>
    </property>
    <property name="suffix">
    <value>.jsp</value>
    </property>
    </bean>

    <!-- 配置视图解析器BeanNameViewResolver:使用视图的名字解析视图 -->
    <!-- 通过order属性来定义视图解析器的优先级,value越小优先级越高 -->
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
    <property name="order" value="100"></property>
    </bean>

    <!--配置直接跳转转发的页面 而无需经过Handler的方法 -->
    <mvc:view-controller path="/hello" view-name="hello"/>
    <!-- 直接跳转页码,不经过handler,在实际开发中,通常需要配置 mvc:annotation-driven 标签 -->
    <mvc:annotation-driven></mvc:annotation-driven>

    <!-- 静态资源 -->
    <!--
    default-servlet-handler 将在springmvc上下文中定义一个DefaultServletHttpRequestHandler
    它会地进入DispatcherServlet的请求进行筛查,如果发现是没有映射的请求,就将改请求交由WEB应用服务器默认的
    servlet 处理。如果不是静态资源的请求,才有DispatcherServlet继续处理

    一般WEB应用服务器默认的servlet的名称都是default
    若使用的WEB服务器的默认servlet名称不是default,则需要通过 default-servlet-name 属性显示指定
    -->
    <mvc:default-servlet-handler/>

    <!--
    配置多个拦截器,那么多个拦截器的执行顺序是什么?
    [FirstInterceptor] preHandle
    [SecondInterceptor] preHandle
    listAllEmployees
    [SecondInterceptor] postHandle
    [FirstInterceptor] postHandle
    [SecondInterceptor] afterCompletion
    [FirstInterceptor] afterCompletion

    preHandle 按正序执行
    postHandle、afterCompletion 按倒序执行

    若SecondInterceptor preHandle 返回false,则执行顺如下:
    [FirstInterceptor] preHandle
    [SecondInterceptor] preHandle
    [FirstInterceptor] afterCompletion
    -->
    <!--配置拦截器 -->
    <mvc:interceptors>
    <!--配置自定义拦截器 -->
    <bean class="com.test.interceptor.FirstInterceptor"></bean>


    <!-- 配置拦截器作用的路径-->
    <mvc:interceptor>
    <mvc:mapping path="/listAllEmployees"/>
    <!--
    <mvc:exclude-mapping path="/emp"/> -->
    <bean class="com.test.interceptor.SecondInterceptor"></bean>
    </mvc:interceptor>

    </mvc:interceptors>
    <!--配置拦截器 -->
    InternalResourceViewResolver:

    ①、级别默认最大,所以如果配置了其他视图解析器,都比它先执行,其他视图解析器,则按order顺序从小的数字开始执行。

    ②、prefix,suffix:该视图解析器的解析出该跳转的页面是:prefix+returnViewName+suffix,

    我的例子即是:/WEB-INF/views/xx.jsp

    ③、实际开发中 <mvc:view-controller> <mvc:annotation-driver> 要一起配置

    ④、<mvc:default-servlet-handler> 用于静态资源映射

    4、多个拦截器执行顺序

            [FirstInterceptor] preHandle
    [SecondInterceptor]  preHandle
    listAllEmployees  //目标方法
    [SecondInterceptor]  postHandle
    [FirstInterceptor]  postHandle
    [SecondInterceptor]  afterCompletion
    [FirstInterceptor]  afterCompletion

    preHandle 按正序执行
    postHandle、afterCompletion 按倒序执行
        
        若SecondInterceptor preHandle 返回false,则执行顺如下:
        [FirstInterceptor] preHandle
    [SecondInterceptor]  preHandle
    [FirstInterceptor]  afterCompletion

    5、Rest风格的URL

    新增:/order  post 

    修改:/order/1  put

    删除:/order/1 delete

    获取:/order/1  get

    如何发送put和delete请求呢?

    ①、先在springMVC配置文件中配置HiddenHttpMethodFilter

    ②、需要发送post请求

    ③、在发送post请求时,携带一个name=“_method”的隐藏域,值为PUT或者DELETE

    如何得到请求中的参数?

    在目标方法中用@PathVariable注解获取参数

    以delete为例,示例如下:

    <form action="testRest/1" method="post">
    <input type="hidden" name="_method" value="DELETE">
    <input type="submit" value="testRest Delete"/>
    </form>
    @RequestMapping(value="/testRest/{id}",method=RequestMethod.DELETE)
    public String testRestDelete(@PathVariable Integer id)
    {
    System.out.println("testRest DELETE:"+id);
    return "hello";
    }
     

    6、@ModelAttribute注解

    /**
    * 1、有@ModelAttribute 修饰的方法,会在每个目标方法执行之前被springMVC调用
    * 2、@ModelAttribute 注解也可以来修饰目标方法POJO类型的入参,其value 属性值有如下作用:
    * 1)、spirngMVC 会使用value属性值在implicitModel 中查找对应的对象,若存在则会直接换入到目标方法的入参中
    * 2)、springMVC会以value为key,POJO类型的对象为value,存入到request中。
    */
    @ModelAttribute
    public void geteUser(@RequestParam(value="id",required=false) Integer id,Map<String,Object> map)
    {
    System.out.println("testModelAttribute method");
    if(id != null)
    {
    //模拟从数据库取出一个对象
    User user = new User("1", "tom", "123456");
    System.out.println("从数据库取出一个对象:"+user);
    map.put("abc", user);
    }
    }


    /**
    * 运行流程:
    * 1、执行 @ModelAttribute 注解修饰的方法,从数据库取出对象,把对象放入map中,键为user
    * 2、springMVC 从map中取出user对象,并把表单中的请求参数赋给该user对象的对应属性
    * 3、springMVC 把上述对象传入目标方法的参数
    * 注意:在 @ModelAttribute修饰的方法中,放入到map时的键需要和目标参数的第一个字母小写的字符串一致
    *
    * springMVC确定目标方法POJO类型入参的过程
    * 1、确定一个key
    * 1)、若目标方法的POJO类型的参数没有使用 @ModelAttribute 作为参数,则key为POJO类名第一个字母小写
    * 2)、若使用了 @ModelAttribute来修饰,则key为 @ModelAttribute 注解的value属性值
    *
    * 2、在implicitModel中查找key对应的对象,若存,则作为入参传入
    * 1)、若在 @ModelAttribute 标记的方法中在Map中保存过,且key和1确定的key一致,则会获取到
    *
    * 3、若implicitModel中不存在key对应的对象,则检查当前的Handler是否使用了 @SessionAttributes 注解修饰,
    * 若使用了改注解,且 @SessionAttribute 注解的value属性值也包含了key,则会从HttpSession中来获取key所对应
    * 的value值,若存在则直接传入到目标方法的入参中,若不存在则抛出异常
    * 4、若Handler没有表示 @SessionAttributes注解 或 @SessionAttributes 注解的value值中不包含key,则会通过反射来创建POJO类型的参数,
    * 传入为目标方法的参数
    * 5、springMVC会把key 和 POJO类型的对象 保存到implicitModel中,进而会保存到request中。
    *
    *
    * 源码分析:
    * 1、首先调用@ModelAttribute 注解修饰的方法,实际上把@ModelAttribute方法中的map中的数据放在了 implicitmodel中
    * 2、解析请求处理器的目标参数,实际上该目标参数来自于 WebDataBinder对象的target属性
    * (1)、创建WebDataBinder 对象;
    * ①、确定 objectname 属性:若传入的attrName 属性值为“”,则objectName 为类名第一个字母小写
    * 注意:attrName 若目标方法的pojo属性使用了@ModelAttribute来修饰,则attrName 值即为@ModelAttribute的value 属性值
    *
    * ②、确定target 属性:
    * > 在implicitModel 中查找attrName 对应的属性值,若存在,ok
    * > *若不存在则验证当前Handler是否使用了@SessionAttribute进行修饰,若使用了,则 尝试从session中获取attrName 所对应的属性值,
    * 若session中没有对应的属性值,则抛出异常
    * > 若Handler没有使用@SessionAttribute进行修饰,或@SessionAttributes 中没有使用value值指定的key和attrName 相匹配,
    * 则通过反射创建了POJO对象
    *
    * (2)、springMVC把表单请求的参数赋给了WebDataBinder 的 target 对应的属性
    * (3)、*springMVC会把WebDataBinder的attrName 和target 给到 implicitModel,进而传到request 域对象中
    * (4)、把WebDataBinder 的 target作为参数传递给目标方法的入参
    */
    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(@ModelAttribute(value="abc") User user)
    {
    System.out.println("修改:"+user);
    return HELLO;
    }
    注意:①、@ModelAttribute 修饰的方法会在每个目标方法被调用之前调用。

    ②、如上例,如果 testModelAttribute 方法中,没有 @ModelAttribute(value="abc"),则spirngMVC默认以该POJO类名的第一个字母小写为key;如果有@ModelAttribute(value="abc"),且@ModelAttribute 修饰的方法中需要 map.put("abc", user);

    这时,就不以POJO类名第一个字母小写为key,以@ModelAttribute(value="abc") value为key。

    7、使用POJO对象绑定请求参数

    使用POJO对象绑定请求参数,springMVC会按请求参数名和POJO属性名进行自动匹配,自动为该对象填充属性值,支持级联属性。

    8、处理模型数据

     SpringMVC提供了以下几种途径输出模型数据:

     1)、ModelAndView:处理方法返回值类型为ModelAndView时,方法体即可通过该对象添加模型数据。

     2)、Map 及 Model:入参为 org.spirngframework.ui.Model、org.spriingframework.ui.ModelMap 或者 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中。

     3)、@SessionAttributes:将模型中的某个属性暂存到HttpSession中,以便多个请求之间可以共享这个属性。

        @SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中。

        --@SessionAttributes(types=User.class) 会将隐含模型中所有类型为User.class 的属性添加到会话中。

        --@SessionAttributes(value={"user1","user2"})

        --@SessionAttributes(types={User.class,Dept.class})

        --@SessionAttributes(value={"user1","user2"},types={Dept.class})

     4)、@ModelAttribute:方法入参标注该注解后,入参的对象就会放到数据模型中。属性暂存到HttpRequest中。

    9、 @ModelAttribute @SessionAttributes  标注的属性,前台如何取?

    request user:${requestScope.user }

    session user: ${sessionScope.user }
    注意:JSP页面EL表达式开关必须打开,否则页面不会正常显示,如下:

    <%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8" isELIgnored="false"%>
    isELIgnored:是否忽略EL表达式;

    如果为true,则${}中的表达式会原样输出,不会进行计算;

    如果是false,则会计算${}中的表达式;

    番外:目标方法中map中的值,页面如何取?

    time:${requestScope.time}
    10、处理静态资源

     优雅的REST风格的资源URL不希望带有.html  或 .do等后缀。

     若将DispatcherServlet 请求映射配置为/,则SpringMVC将会捕获WEB容器的所有请求,包括静态资源的请求,SpringMVC会将他们当成一个普通请求处理,因此找不到对应的处理器将导致错误。

    可以在SpringMVC的配置中配置<mvc:default-seervlet-handler/>的方式解决静态资源的问题

    <mvc:default-servlet-handler/>会在SpringMVC上下文中定义一个DefaultServletHttpRequestHandler,它会对进入DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由WEB应用服务器默认的Servlet处理,如果不是静态资源,才由DispatcherServlet继续处理。

    一般WEB应用服务器默认的Servlet的名称都是default。若所使用的WEB服务器的默认Servlet名称不是default,则需要通过

    default-servlet-name属性显示指定

    11、数据绑定流程

    1)、SpringMVC框架将ServletRequest 对象及目标方法的入参实例传递给WebDataBinderFactory实例,以创建DataBinder实例对象

    2)、DataBinder 调用装配在SpringMVC上下文中的ConversionService组件进行 数据类型转换、数据格式化 工作。将Servlet中的请求信息填充到入参对象中。

    3)、调用Validator 组件对已经绑定了请求信息的入参对象进行数据合法性校验,并最终生成数据绑定结果BindingData对象。

    4)、SpringMVC抽取BindingResult中的入参对象和校验错误对象,将它们赋给处理方法的响应入参。

    12、springMVC的各种注解

    1)、@Controller

        @Controller注解的类表示该类是个控制器类。

    2)、@PathVariable

        @PathVariable 绑定URL占位符的入参。带占位符的URL是spring3.0新增的功能,该功能在springMVC向REST目标挺进发展过程中具有里程碑的意义。

        通过 @PathVariable 可以将URL中占位符参数绑定到控制器处理方法的入参中:URL中的{xxx}占位符可以通过@PathVariable("xxx") 绑定到操作方法的入参中。

    3)、@ResquestMapping

        使用 @ResquestMapping 映射请求

    @ResquestMapping 可以用到类上,也可以用到方法上,如果类上加上了该注解,那么该control下的所有方法的mapping前面都会自动加上类上的mapping。例如:类上@ResquestMapping(value="/aaa"),方法上@ResquestMapping(value="/bbb.htm"),那么请求bbb.htm,实际的URL是:/aaa/bbb.htm

       ①、Ant 风格资源地址支持3中匹配符:

        --?:匹配文件名中的一个字符

        --* :匹配文件名中的任意字符

       --**:匹配多层路径

        ②、@RequestMapping就支持Ant风格的URL:

        -- /user/*/createUser:匹配

            /user/aaa/createUser、/user/bbb/createUser 等URL

       --/user/**/cereateUser:匹配

        /user/createUser 、/user/aaa/bbb/createUser 等 URL

    4)、@SessionAttributes

    若希望在多个请求之间公用某个模型属性数据,则可以在控制器类上 标注一个@SessionAttributes,SpringMVC将在模型中对应的属性暂存到HttpSession中。

    5)、@ModelAttribute

        --在方法定义上使用@ModelAttribute注解:SpringMVC在调用目标处理方法前,会先逐个调用在方法上标注了@ModelAttribute的方法

        --在方法 的入参前使用 @ModelAttribute注解:

        ①、可以从隐含对象中获取隐含的模型数据中获取对象,在将请求参数绑定到对象中,再传入入参。

        ②、将方法入参对象添加到模型中。

    6)、@AutoWired

        它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过@AutoWired的使用来消除 set,get 方法。

    7)、@ReponseBody

        用来修饰Controller的目标方法,通过适当的HttpMessageConverter转换器把返回值由String转换为指定的格式,放在Response的body区。如转换为JSON

    8)、@RequestHeader

        使用@RequestHeader 绑定请求报头的属性值。

        请求头包含了若干个属性,服务器可据此获知客户端的信息,通过@RequestHeader 即可将请求头中的属性值绑定到处理方法的入参中。

    9)、@CookieValue

        @CookieValue 可让处理方法入参绑定某个Cookie值

    10)、@RequestParam

        在处理方法入参处使用 @RequestParam 可以把请求参数传递给请求方法。

       --value:参数名

      --required:是否必须。默认为true,表示请求参数中必须包含对应的参数,若不存在,将抛出异常。

    11)、@InitBinder

       由 @InitBinder 标识的方式,可以对WebDataBinder 对象进行初始化。WebDataBinder 是 DataBinder 的子类,用于完成有表单字段到JavaBean属性的绑定。

      @InitBinder 方法不能有返回值,它必须声明为void

      @InitBinder 方法的参数通常是WebDataBinder 

    12)、@Repository

        用来标注数据访问组件,即Dao组件

    13)、@Component

        用于把普通POJO类融入Spring容器,相当于配置文件中的<bean id="" class="" />

        泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类。

    14)、@Service

        用于标注服务层,主要用来进行业务逻辑的处理

    15)、@ExceptionHandler

        用来修饰方法,出现异常时,执行该方法

    16)、@ControllerAdvice+@ExceptionHandler

        使一个Contoller成为全局的异常处理类

    13、
    Neither BindingResult nor plain target object for bean name 'command' available as request attribute

    出错场景:经过一个action跳转到新增用户页面

    @RequestMapping(value="/input",method=RequestMethod.GET)
    public String input()
    {
    return "input";
    }
     

    原因是:用<form:form>标签,springMVC解析JSP之前,先去attribute找该form对应的POJO对象,如果没有找到,则用默认的对象command,然后也没找到,所以报错。

    解决办法:

    ①、在JSP页面增加 <jsp:useBean id="command" class="com.cjl.beans.User" scope="request"></jsp:useBean> 引入该bean

    ②、在响应的controller中加入该代码 map.put("user", new User());,

    然后在JSP页面,<form:form> 该标签中加入modelAttribute="user" 即可。

  • 相关阅读:
    Beginning Silverlight 4 in C#数据绑定和Silverlight List控件
    使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置)
    分布式事物:第一章:分布式事物简介
    Redis数据结构存储系统:第三章:Redis在项目中如何使用?
    Android “NetworkOnMainThreadException”出错原因及解决办法
    asp.net 运行时, 报控件不存在
    Only the original thread that created a view hierarchy can touch its views
    android模拟器打开时比较慢,Run As就找不到模拟器
    db2数据库还原
    去掉代码中自动生成的TODO Autogenerated method stub
  • 原文地址:https://www.cnblogs.com/zhx2654188344/p/14637267.html
Copyright © 2011-2022 走看看