《Spring3.X企业应用开发实战》学习笔记--SpringMVC

本篇是《Spring3.X企业应用开发实战》,陈雄华 林开雄著,电子工业出版社,2012.2出版”的学习笔记的第三篇,关于SpringMVC。

Spring MVC 3.0和早期版本相比拥有了一个质的飞跃,全面支持REST风格的WEB编程、完全注解驱动、处理方法签名非常灵活、处理方法不依赖于Servlet API等。

由于Spring MVC框架在后头做了非常多的隐性工作,所以想深入掌握Spring MVC 3.0并非易事,本章我们在学习Spring MVC的各项功能时,还深入其内部了解其后台的运作机理,只有了解这些机理后,才能更好地使用这个当前最先进的MVC框架。

服务器启动时加载配置文件的顺序:web.xml  applicationContext.xml  springmvc-servlet.xml。

Spring MVC概述

Spring MVC通过一套MVC注解,让POJO成为处理请求的控制器,无须实现任何接口,同时,Spring MVC还支持REST风格的URL请求:注解驱动及REST风格的Spring MVC是Spring 3.0最出彩的功能之一。

此外,Spring MVC在数据绑定、视图解析、本地化处理及静态资源处理上都有不俗的表现。

DispatcherServlet

Spring MVC框架围绕DispatcherServlet这个核心展开,DispatcherServlet是Spring MVC的总导演、总策划,它负责截获请求并将其分派给相应的处理器处理。

在web.xml中配置DispatcherServlet,截获特定的URL请求:

<servlet>
	<servlet-name>springmvc</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>springmvc</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

Spring如何将上下文中的SpringMVC组件装配到DispatcherServlet中?

WebApplicationContext初始化后,此时Spring上下文中的Bean已经初始化完毕,开始执行DispatcherServlet的initStrategies()方法,代码如下:

protected void initStrategies(ApplicationContext context) {
 initMultipartResolver(); //1.初始化上传文件解析器
 initLocalResolver();//2.初始化本地化解析器
 initThemeResolver();//3.初始化主题解析器
 initHandlerMappings();//4.初始化处理器映射器
 initHandlerAdapters();//5.初始化处理器适配器
 initHandlerExceptionResolver();//6.初始化处理器异常解析器
 initRequestToViewNameTranslator();//7.初始化请求道试图名解析器
 initViewResolvers();//8.初始化试图解析器
}

该方法的工作是通过反射机制查找并装配Spring容器中显式自定义的组件Bean,如果找不到,则装配默认的组件实例,默认的组件实例在spring-webmvc-版本.RELEASE.jar包中,org/springframework/web/servlet路径下的DispatcherServlet.properties中间中定义。

其中文件上传没有默认的解析器,如果需要,自行配置,比如:

<!-- 配置对文件上传的支持 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

注解驱动的控制器

在POJO类定义处标注@Controller,再通过<context:component-scan/>扫描相应的类包,即可使POJO成为一个能处理HTTP请求的控制器。

@RequestMapping:不但支持标注的URL,还支持Ant风格(即?、*和**的字符)和带有{xxx}占位符的URL。带占位符的URL是Spring 3.0新增的功能,该功能在Spring MVC向REST目标挺进的发展过程中具有里程碑的意义。

通过@PathVariable可以将URL中的占位符参数绑定到控制器处理方法的入参中。

如何设置方法入参以绑定请求信息

使用命令/表单对象绑定请求参数值:

这是最常用的,即入参就是一个POJO。Spring MVC会按照请求参数名和对象属性名进行匹配,自动为对象填充属性值,支持级联的属性名,例如:

@RequestMapping("/handleInsert)

public String handleInsert(User user,String operator)…

使用@RequestParam、@CookieValue、@RequestHeader,分别获取请求、Cookie、请求报文头的传入值,他们都有3个参数:

value:参数名;

required:是否必需,默认为true,表示请求中必须包含对应的参数名,如果不存在将抛出异常;

defaultValue:默认参数名,设置该参数时,自动将required设为false。极少情况需要使用该参数,也不推荐使用该参数

使用Servlet API对象作为入参:

public String handleInsert(HttpServletRequest request,HttpServletResponse response)...

另外Spring MVC在 org.springframework.web.context.request包中定义了若干个可代理Servlet原生API类的接口,如WebRequest和NativeWebRequest,他们也允许作为代理类的入参,通过这些代理类可访问请求对象的任何信息。

使用IO对象作为入参:

Servlet的ServletRequest拥有getInputStream()和getReader()方法,可以通过他们读取请求的信息。相应Servlet的ServletResponse拥有getOutputStream()和getWriter()方法,可以通过它们输出响应信息。

Spring MVC允许控制器的处理方法使用java.io.InputStream/java.io.Reader及java.io.OutputStream/java.io.Writer作为方法的入参,Spring MVC将获取ServletRequest的InputStream/Reader或ServletResponse的OutputStream/Writer,然后传递给控制器的处理方法。

使用其他类型的参数:

比如java.util.Locale、java.security.Principal,可以通过Servlet的HttpServletRequest的getLocale()及getUserPrincipal()得到相应的值。

HttpMessageConverter<T>进行消息对象转换

HttpMessageConverter<T>是Spring 3.0新添加的一个重要接口,它负责将请求信息转换为一个对象(类型为T),将对象(类型为T)输出为响应信息。

DispatcherServlet默认已经安装了AnnotationMethodHandlerAdapter作为HandlerAdapter的组件实现类,HttpMessageConverter即由AnnotationMethodHandlerAdapter使用,

将请求信息转换为对象,或将对象转换为响应信息。

Spring为HttpMessageConverter<T>提供了众多的实现类,他们组成了一个功能强大、用途广泛的HttpMessageConverter<T>家族。

AnnotationMethodHandlerAdapter默认一级装配了如下的HttpMessageConverter:

StringHttpMessageConverter

ByteArrayHttpMessageConverter

SourceHttpMessageConverter

XmlAwareFormHttpMessageConverter

如果需要装配其他类型的HttpMessageConverter,可在Spring的Web容器上下文中自行定义一个AnnotationMethodHandlerAdapter,如果在Spring容器中显式定义了一个

AnnotationMethodHandlerAdapter,则Spring MVC将使用它覆盖默认的AnnotationMethodHandlerAdapter。

如何使用HttpMessageConverter<T>将请求信息转换并绑定到处理方法的入参中呢?

Spring MVC提供了两种途径:

1.使用@RequestBody/@ResponseBody对处理方法进行标注

2.使用HttpEntity<T>/ResponseEntity<T>作为处理方法的入参或返回值

关于HttpMessageConverter<T>,得出如下几条结论:

1.当控制器处理方法使用到@RequestBody/@ResponseBody 或 HttpEntity<T>/ResponseEntity<T>时,Spring MVC才使用注册的HttpMessageConverter对请求/响应消息进行处理

2.当控制器处理方法使用到@RequestBody/@ResponseBody 或 HttpEntity<T>/ResponseEntity<T>时,Spring首先根据请求头或响应头的Accept属性选择匹配的HttpMessageConverter,进而根据参数类型或反向类型的过滤得到匹配的HttpMessageConverter,如果找不到可用的HttpMessageConverter将报错

[email protected]/@ResponseBody不需要成对出现,如果方法入参使用到@RequestBody,Spring MVC选择匹配的HttpMessageConverter将请求消息转换并绑定到该入参中。如果处理方法标注了

[email protected],Spring MVC选择匹配的HttpMessageConverter将方法返回值转换并输出相应消息。

5.HttpEntity<T>/ResponseEntity<T>的功用和@RequestBody/@ResponseBody相似

RestTemplate

RestTemplate是Spring 3.0新增的模板类,在客户端程序中可使用该类调用Web服务端的服务,它支持REST风格的URL。此外,它项AnnotationMethodHandlerAdapter一样拥有一个httpMessageConverter的注册表,它默认注册了5个HttpMessageConverter。

spring-servlet.xml

spring-servlet.xml配置(WEB-INFO目录下):

<!-- 这是简单配置,代替bean节点那种显示加载bean的配置方式,可以自动加载必须得如下两个bean -->
<!-- <mvc:annotation-driven /> -->
<!-- 这是标准配置,可以解决ResponseBody中文乱码问题 -->
<bean  class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean
 class="org.springframework.http.converter.StringHttpMessageConverter">
 <property name="supportedMediaTypes">
  <list>
   <value>text/plain;charset=UTF-8</value>
  </list>
 </property>
 <property name="writeAcceptCharset" value="false"/>
</bean>
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<!-- 装载拦截器  -->
<mvc:interceptors>
<!-- 更改语言环境时,一个'locale'的请求参数发送  -->
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
<!-- 权限拦截  -->
<mvc:interceptor>
<mvc:mapping path="/**/*.do" />
<bean class="com.shopyp.authority.interceptor.AuthorityInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>

处理模型数据

对于MVC框架来说模型数据是最重要的,因为控制(C)是为了产生模型数据(M),而视图(V)则是为了渲染模型数据。

如何将模型数据暴漏给视图是Spring MVC框架的一项重要工作,Spring MVC提供了多种途径输出模型数据,介绍如下:

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

2、@ModelAttribute:方法入参标注该注解后,入参的对象就会放到数据模型中

3、Map及Model:入参为org.springframework.ui.Model、org.springframework.ui.ModelMap或java.util.Map时,处理方法返回时,Map中的数据会自动添加到模型中

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

处理方法的数据绑定

我们知道Spring 会根据请求方法签名的不同,将请求信息中的信息以一定的方式转换并绑定到请求方法的入参中。

在请求消息到达真正调用处理方法的这一段时间内,Spring还完成了很多工作,包括数据转换、数据格式化及数据校验等。这一节使用较少,临时不去研究。

视图和视图解析器

请求处理方法执行完成后,最终返回一个ModelAndView对象。

对于那些返回String、View或ModelMap等类型的处理方法,Spring MVC也会在内部将它们装配成一个ModelAndView对象,它包含了视图逻辑名和模型对象的信息。

Spring MVC借助视图解析器(ViewResolver)得到最终的视图对象(View),这可能是我们常见的JSP视图,也可能是一个基于FreeMarker、Velocity模板技术的视图,还可能是PDF、Excel、XML、JSON等各种形式的视图。

对于最终究竟采取何种视图对象对模型对象进行渲染,Controller并不关心,Controller的工作重点聚集在生产模型数据的工作上,从而实现MVC的充分解耦。

FreeMarker配置:

 <!-- Freemarker配置,参考: http://www.cnblogs.com/hoojo/archive/2011/04/19/2020551.html-->
 <bean id="freemarkerConfig"
  class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
  <!-- 视图资源位置 -->
  <property name="templateLoaderPath" value="/WEB-INF/ftl/" />
  <property name="defaultEncoding" value="UTF-8" />
  <property name="freemarkerSettings">
   <props>
    <prop key="template_update_delay">0</prop><!-- 模板更新延时 -->
    <prop key="locale">zh_CN</prop>
    <prop key="default_encoding">UTF-8</prop>
    <prop key="output_encoding">UTF-8</prop>
    <prop key="template_exception_handler">rethrow</prop>
          <prop key="number_format">#.##</prop>
          <prop key="date_format">yyyy-MM-dd</prop>
          <prop key="time_format">HH:mm:ss</prop>
          <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
   </props>
  </property>
  <!-- 全局变量部分 -->
  <property name="freemarkerVariables">
   <map>
    <entry key="BasePath" value="${web.basepath}" />
    <entry key="xml_escape" value-ref="fmXmlEscape" />
   </map>
  </property>
 </bean>
 <bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape" />
 <!-- 配置freeMarker视图解析器 -->
 <bean id="ftlviewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />
  <!-- 如果配置了这个节点,则视图必须是ftl,redirect等前缀都失效了 -->
  <!-- <property name="viewNames" value="*.ftl"/> -->
  <property name="contentType" value="text/html;charset=UTF-8" />
  <property name="cache" value="true" />
  <property name="prefix" value="" />
  <property name="suffix" value="" />
 </bean>

针对在实际开发过程中使用到的FreeMarker语法,JSTL标签等,可以逐渐熟悉和记录。

FreeMarker和Velocity是除JSP之外被使用最多的页面模板技术。页面模板编写好页面结构,模板页面中使用一些特殊的变量标识符绑定Java对象的动态数据。

FreeMarker是一个模板引擎,一个基于模板生产文本输出的通用工具,FreeMarker可以基于模板产生HTML、XML、JAVA源代码等多种类型的输出内容。虽然FreeMarker具有一些编程能力,单通常由Java程序准备数据,FreeMarker仅负责基于模板对模型数据进行渲染的工作。

关于Web开发

要想成为一名Web开发高手,不能仅满足于知道如何做,更要抛开线程探究本质。

笔者认为要成为一名Web开发高手,必须熟练了解如下内容:

1、每次请求和响应的背后究竟发生了哪些步骤,客户端服务器是如何通过HTTP请求报文进行交互的;

2、深刻掌握MIME类型的知识;

3、深刻掌握HTTP响应状态码的知识,如404、303究竟代表什么。

时间: 2024-08-02 06:54:42

《Spring3.X企业应用开发实战》学习笔记--SpringMVC的相关文章

《Spring3.X企业应用开发实战》学习笔记--DAO和事务

本篇是"<Spring3.X企业应用开发实战>,陈雄华 林开雄著,电子工业出版社,2012.2出版"的学习笔记的第二篇,关于DAO和事务. 本篇从DAO操作,以及事务处理的基本知识谈起,介绍事务本身,以及Spring如何通过注解实现事务. DAO 近几年持久化技术领域异常喧嚣,各种框架如雨后春笋般地冒出,Sun也连接不断的颁布了几个持久化规范. Spring对多个持久化技术提供了持久化支持,包括Hibernate,iBatis,JDO,JPA,TopLink,另外,还通过S

Spring3.x企业应用开发实战1.环境搭建

书中搭建得环境是spring3.x,我选择得是spring 4.2.5.RELEASE系列得jar包搭建.记录下其中遇到得问题 1.jar包选择: spring4.x中没有spring-asm 和 spring web-servlet这两个jar包,因为 asm这个包已经在spring4.x得core包中包含 web-servlet 在spring4.下得webmvc中包含 2.环境搭建至书上得30页之后,用junit测试一直是空指针异常,在检查applicationContext.xml中确保

《Spring 3.x 企业应用开发实战》目录

图书信息:陈雄华 林开雄 编著 ISBN 978-7-121-15213-9 概述: 第1章:对Spring框架进行宏观性的概述,力图使读者建立起对Spring整体性的认识. 第2章:通过一个简单的例子展现开发Spring Web应用的整体过程,通过这个实例,读者可以快速跨入Spring Web应用的世界. 第3章:讲解Spring IoC容器的知识,通过具体的实例详细地讲解IoC概念.同时,对Spring框架的三个最重要的框架级接口进行了剖析,并对Bean的生命周期进行讲解. 第4章:讲解如何

Spring3.0官网文档学习笔记(一)

Part 1 Spring框架概述 Spring是模块化的,在应用中只需要引入你所需要用到的模块的jar包,其余的jar包不用引入. spring框架支持声明式的事务管理,通过RMI或web service访问你的逻辑,还有许多种方式保存数据. spring被设计成非侵入式的. 1.Spring框架简介 Spring框架提供了应用开发的基础部分,使得我们可以集中精神在业务开发层上. POJOS:plain old Java objects Spring允许创建非侵入式的POJO.这个特性支持Ja

ASP.Net MVC开发基础学习笔记(3):Razor视图引擎、控制器与路由机制学习

首页 头条 文章 频道                         设计频道 Web前端 Python开发 Java技术 Android应用 iOS应用 资源 小组 相亲 频道 首页 头条 文章 小组 相亲 资源 设计 前端 Python Java 安卓 iOS 登录 注册 首页 最新文章 经典回顾 开发 Web前端 Python Android iOS Java C/C++ PHP .NET Ruby Go 设计 UI设计 网页设计 交互设计 用户体验 设计教程 设计职场 极客 IT技术

微软企业库5.0学习笔记(10)ASP.NET模块依赖注入

您可以使用HTTP模块,一个到ASP.NET HttpApplicationState类的扩展,在Global.asax编写代码强制ASP.NET在每一个页面请求时自动注入依赖的对象,就像在ASP.NET Web窗体应用程序中讨论的一样. 下列方法显示了一个合适的方法能够获取PreRequestHandlerExecute事件将它自己注入到ASP.NET的执行流水线,在每个页面请求中通过容器的BuildUp方法运行Http模块,并获取OnPageInitComplete事件.当OnPageIni

ASP.Net MVC开发基础学习笔记:三、Razor视图引擎、控制器与路由机制学习

一.天降神器“剃须刀” — Razor视图引擎 1.1 千呼万唤始出来的MVC3.0 在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor.在这之前,我们一直在使用WebForm时代沿留下来的ASPX引擎或者第三方的NVelocity模板引擎. Razor在减少代码冗余.增强代码可读性和Visual Studio智能感知方面,都有着突出的优势.Razor一经推出就深受广大ASP.Net开发者的喜爱. 1.2 Razor的语法 (1)Razor文件类型:Razor支持两种文件类型,分

Spring3.0官网文档学习笔记(五)--3.3

3.3 概述 Table 3.1. The bean definition Property Explained in... class Section 3.3.2, "Instantiating beans" name Section 3.3.1, "Naming beans" scope Section 3.5, "Bean scopes" constructor arguments Section 3.4.1, "Dependen

Spring3.0官网文档学习笔记(六)--3.4.1

3.4 依赖 3.4.1 依赖注入 依赖注入两种方式:基于构造器的DI.基于setter方法的DI. 3.4.1.1 基于构造器的DI 参数是引入对象,且之前不存在父-子类关系: package x.y; public class Foo { public Foo(Bar bar, Baz baz) { // ... } } <beans> <bean id="foo" class="x.y.Foo"> <constructor-arg