Spring MVC
初识SpringMVC
大部分 Java 应用都是 Web 应用,展现层是Web 应用不可忽略的重要环节。Spring 为展现层提供了一个优秀的Web框架——Spring MVC。和众多其他的Web 框架一样,它基于 MVC 的设计理念。此外,它采用了松散耦合、可插拔的组件结构,比其他的MVC框架更具扩展性和灵活性。Spring MVC通过一套MVC注解,让POJO成为处理请求的控制器,无须实现任何接口。同时,Spring MVC还支持 RESTful风格的 URL 请求∶注解驱动及REST风格的 Spring MVC是 Spring的出色功能之一。此外,Spring MVC在数据绑定、视图解析、本地化处理及静态资源处理上都有许多不俗的表现。
SpringMVC简介
Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架,本质上相当于 Servlet。
Spring MVC 是结构最清晰的 Servlet+JSP+JavaBean 的实现,是一个典型的教科书式的 MVC 构架,不像 Struts 等其它框架都是变种或者不是完全基于 MVC 系统的框架。
Spring MVC 角色划分清晰,分工明细,并且和 Spring 框架无缝结合。Spring MVC 是当今业界最主流的 Web 开发框架,以及最热门的开发技能。
在 Spring MVC 框架中,Controller 替换 Servlet 来担负控制器的职责,用于接收请求,调用相应的 Model 进行处理,处理器完成业务处理后返回处理结果。Controller 调用相应的 View 并对处理结果进行视图渲染,最终客户端得到响应信息。
Spring MVC 框架采用松耦合可插拔的组件结构,具有高度可配置性,比起其它 MVC 框架更具有扩展性和灵活性。
此外,Spring MVC 的注解驱动和对 REST 风格的支持,也是它最具特色的功能。无论是在框架设计,还是扩展性、灵活性等方面都全面超越了 Struts2 等 MVC 框架。并且由于 Spring MVC 本身就是 Spring 框架的一部分,所以可以说与 Spring 框架是无缝集成,性能方面具有先天的优越性,对于开发者来说,开发效率也高于其它的 Web 框架,在企业中的应用越来越广泛,成为主流的 MVC 框架。
DispatcherServlet
DispatcherServlet是 Spring MVC的”灵魂”和”心脏”,它负责接收HTTP 请求并协调 Spring MVC 的各个组件完成请求处理的工作。和任何 Servlet 一样,用户必须在web.xml 中配置好 DispatcherServlet。这里进一步分析其具体的配置。 要了解 Spring MVC框架的工作机理,必须回答以下3个问题。
- DispatcherServlet 框架如何截获特定的HTTP请求并交由 Spring MVC框架处理?
- 位于 Web层的 Spring 容器(WebApplicationContext)如何与位于业务层的 Spring容器(ApplicationContext)建立关联,以使Web层的Bean可以调用业务层的Bean?
- 如何初始化 Spring MVC的各个组件,并将它们装配到 DispatcherServlet 中?
配置DispatcherServlet
在Servlet的学习中可以知道,通常会在web.xml中配置Servlet,并通过<servlet-mapping>指定其能处理的URL,在Servlet 3.0中还可以采用编程式的配置方法。因此本小节将就这两种方式进行讲解。
web.xml中配置DispatcherServlet
首先新建web项目并添加如下依赖:
1 | <!--spring-context --> |
在添加依赖后,需要在resource目录下新建SpringMVC的配置文件,因为在框架整合过程中SpringMVC有自身的配置,Spring也需要一些其他的配置,因此将SpringMVC的配置文件和Spring的配置文件进行分离。
Spring-mvc.xml配置文件如下:
1 |
|
在SpringMVC的配置文件中只是进行了简单的配置,配置用于扫描controller包,从而交由Spring容器实例化控制器。
spring.xml配置文件如下:
1 |
|
上述配置完成后,接下来要需要在web.xml中进行配置Dispatcher。代码如下:
1 |
|
在web.xml中首先需要配置org.springframework.web.servlet.DispatcherServlet,配置方式和前面所学的Servlet配置一致,需要注意的是在这里需要在
除此以外,需要配置org.springframework.web.context.ContextLoaderListener监听器,该监听器会在监听容器启动时,加载Spring配置文件,从而创建Spring IOC容器。
接着,新建cn.bytecollege.controller包中添加测试控制器,代码如下:
1 | package cn.bytecollege.controller; |
在上述代码中可以看出类中包含了@Controller,@ResponseBody,@RequestMapping注解,这些注解会在后续内容中进行讲解。
启动web服务后,在浏览器地址栏输入:http://localhost/index?name=admin。结果如下图:
在上例中已经成功将Spring和Spring MVC进行了整合。
编程式配置DispatcherServlet
Spring 4开始已经全面支持Servlet 3.0,因此,在Servlet 3.0及以上的环境中,也可以使用编程的方式来配置Servlet。下面的diam可以达到上述代码中和web.xml中配置一样的效果。需要注意的是如果使用这种方式配置,需要在项目中添加Servlet的依赖。
1 | package cn.bytecollege.init; |
在 Servlet 3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer 的类,如果发现已有实现类,就会调用它来配置 Servlet 容器。在 Spring 中,org.springframework.web.SpringServletContainer Initializer 类实现了该接口,同时这个类又会查找实现 org.springframework.web. WebApplicationInitializer 接口的类,并将配置任务交给这些实现类去完成。另外,Spring 提供了一个便利的抽象类 AbstractAnnotationConfigDispatcherServletInitializer 来实现这个接口,使得它在注册 DispatcherServlet 时只需简单地指定它的 Servlet 映射即可。在上述示例中,当应用部署到 Servlet3.0容器中时,容器启动时会自动发现它,并使用它来配置 Servlet 上下文。
详解Dispatcher
在上面的示例中Spring MVC应用已经成功运行了,那么前端控制器DispatcherServlet截获请求后做了什么工作呢?DispatcherServlet又是如何路由请求的呢?
分析DispatcherServlet核心源码如下:
1 | protected void initStrategies(ApplicationContext context) { |
initStrategies()方法将在 WebApplicationContext 初始化后自动执行,此时 Spring 上下文中的 Bean 已经初始化完毕。该方法的工作原理是∶通过反射机制查找并装配 Spring 容器中用户显式自定义的组件 Bean,如果找不到,则装配默认的组件实例。 Spring MVC定义了一套默认的组件实现类,也就是说,即使在 Spring容器中没有显式定义组件Bean,DispatcherServlet也会装配好一套可用的默认组件。在 spring-webmvc-4.x.jar 包的 org/springframework/web/servlet 类路径下拥有一个 DispatcherServlet. properties 配置文件,该文件指定了DispatcherServlet 所使用的默认组件。
1 | ##本地化解析器 |
如果用户希望采用非默认类型的组件,则只需在 Spring 配置文件中配置自定义的组件 Bean 即可。Spring MVC一旦发现上下文中有用户自定义的组件,就不会使用默认的组件。
以下是DispatcherServlet装配每种组件的细节:
文件上传解析器。只允许一个实例
- 查找名为 multipartResolver、类型为 MultipartResolver 的Bean作为该类型的组件。
- 如果用户没有在上下文中显示定义 MultipartResolver 类型的组件,则 DispartcherServlet 将不会加载该类型的组件。
本地化解析器。只允许一个实例
- 查找名为 localeResolver 、类型为 .LocaleResolver 的 Bean 作为该类型组件。
- 如果没有找到,则使用默认的实现类 AcceptHeaderLocaleResolver 作为该类型的组件。
主题解析器。只允许一个实例
- 查找名为 themeResolver 、类型为 ThemeResolver、的 Bean 作为该类型的组件。
- 如果没有找到,则使用默认的实现类 FixedThemeResolver 作为该类型组件。
处理器映射器。允许多个实例
- 如果 detectAllHandlerMappings 的属性为 true(默认为true),则根据类型匹配机制查找上下文以及 Spring 容器中所有类型为HandlerMapping 的 Bean,将他们作为该类型组件。
- 如果 detectAllHandlerMappings 的属性为 false,则查找名为 handlerMapping 、类型为 HandlerMapping 的 Bean 作为该类型组件。
- 如果通过以上两种方式都没有找到,则使用 BeanNameUrlHandlerMapping 实现类创建该类型的组件。
处理器适配器。允许多个实例
- 如果 detectAllHandlerAdapters 的属性为 true(默认为true),则根据类型匹配机制查找上下文以及 Spring 容器中所有类型为HandlerAdapter 的 Bean,将他们作为该类型组件。
- 如果 detectAllHandlerAdapters 的属性为 false,则查找名为 handlerAdapter 、类型为 HandlerAdapter 的Bean 作为该类型的组件。
- 如果通过以上两种方式都没有找到,则使用 DispatcherServlet.properties配置文件中指定的三个实现类分别创建一个适配器,并将其添加到适配器列表中。
处理器异常解析器。允许多个实例
- 如果 detectAllHandlerExceptionResolvers 的属性为 true(默认为true),则根据类型匹配机制查找上下文以及 Spring 容器中所有类型为 HandlerExceptionResolver 的 Bean ,将他们作为该类型组件。
- 如果 detectAllHandlerExceptionResolvers 的属性为 false ,则查找名为 handlerExceptionResolver 、类型为 HandlerExceptionResolver的 Bean 作为该类型组件。
- 如果通过以上两种方式都没有找到,则查找 DispatcherServlet.properties 配置文件中定义的默认实现类,注意,改文件中没有对应处理器异常解析器的默认实现类,用户可以自定义处理器异常解析器的实现类,将之添加到 DispatcherServlet.properties配置文件中。
视图名称解析器。只允许一个实例
- 查找名为 viewNameTranslator 、类型为 RequestToViewNameTranslator 的 Bean 作为该类型的组件。
- 如果没有找到,则使用默认的实现类 DefaultRequestToViewNameTranslator 作为该类型的组件。
视图解析器。允许多个实例
- 如果 detectAllViewResolvers 的属性为 true(默认为true),则根据类型匹配机制查找上下文以及 Spring 容器中所有类型为ViewResolver 的 Bean ,将它们作为该类型组件。
- 如果 detectAllViewResolvers 的属性为 false ,则查找名为 viewResolvers 、类型为 ViewResolver 的BEA作为该类型组件。
- 如果通过以上两种方式都没有找到,则查找 DispatcherServlet.properties 配置文件中定义默认实现类 InternalResourceViewResolver 作为该类型组件。
FlashMap 映射管理器。
- 查找名为 FlashMapManager 、类型为 SessionFlashMapManager 的 Bean 作为该类型组件,用于管理 FlashMap ,即数据默认存储在HttpSession 中。
SpringMVC 请求流程
Spring MVC应用的开发流程实际上是按请求–响应的流程来开发,下面通过一个流程图来介绍请求–响应的完整流程。
SpringMVC 的执行流程如下。
- 浏览器发起一个 HTTP request 请求,该请求会被提交到 DispatcherServlet(前端控制器);
- 由 DispatcherServlet 请求一个或多个 HandlerMapping(处理器映射器),并返回一个执行链(HandlerExecutionChain)。
- DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter(处理器适配器);
- HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler(常称为 Controller);
- Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象(Spring MVC的底层对象,包括 Model 数据模型和 View 视图信息);
- HandlerAdapter 接收到 ModelAndView 对象后,将其返回给 DispatcherServlet ;
- DispatcherServlet 接收到 ModelAndView 对象后,会请求 ViewResolver(视图解析器)对视图进行解析;
- ViewResolver 根据 View 信息匹配到相应的视图结果,并返回给 DispatcherServlet;
- DispatcherServlet 接收到具体的 View 视图后,进行视图渲染,将 Model 中的模型数据填充到 View 视图中的 request 域,生成最终的 View(视图);
- 视图负责将结果显示到浏览器(客户端)。
Spring MVC接口
Spring MVC 涉及到的组件有 DispatcherServlet(前端控制器)、HandlerMapping(处理器映射器)、HandlerAdapter(处理器适配器)、Handler(处理器)、ViewResolver(视图解析器)和 View(视图)。下面对各个组件的功能说明如下。
.DispatcherServlet
DispatcherServlet 是前端控制器,从上图可以看出,Spring MVC 的所有请求都要经过 DispatcherServlet 来统一分发。DispatcherServlet 相当于一个转发器或中央处理器,控制整个流程的执行,对各个组件进行统一调度,以降低组件之间的耦合性,有利于组件之间的拓展。
2.HandlerMapping
HandlerMapping 是处理器映射器,其作用是根据请求的 URL 路径,通过注解或者 XML 配置,寻找匹配的处理器(Handler)信息。
3.HandlerAdapter
HandlerAdapter 是处理器适配器,其作用是根据映射器找到的处理器(Handler)信息,按照特定规则执行相关的处理器(Handler)。
4.Handler
Handler 是处理器,和 Java Servlet 扮演的角色一致。其作用是执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装至 ModelAndView 对象中。
5.View Resolver
View Resolver 是视图解析器,其作用是进行解析操作,通过 ModelAndView 对象中的 View 信息将逻辑视图名解析成真正的视图 View(如通过一个 JSP 路径返回一个真正的 JSP 页面)。
6.View
View 是视图,其本身是一个接口,实现类支持不同的 View 类型(JSP、FreeMarker、Excel 等)。
以上组件中,需要开发人员进行开发的是处理器(Handler,常称Controller)和视图(View)。通俗的说,要开发处理该请求的具体代码逻辑,以及最终展示给用户的界面。
Spring MVC常用注解
Spring在2.5以前使用XML方式配置JavaBean,但是由于配置文件的不便以及臃肿等问题,Spring提供了@Controller、@RequestMapping、@ResponseBody等注解,不但减轻了配置,也使得开发更加的便利。在本章内将详细讲解SpringMVC中常用的注解
控制器注解
@Controller注解
在 POJO类定义处标注@Controller,再通过<context∶component-scan/>扫描相应的类包,即可使 POJO 成为一个能处理HTTP请求的控制器。
用户可以创建数量不限的控制器,分别处理不同的业务请求,如 LoginController、UserController、ForumController 等。每个控制器可拥有多个处理请求的方法,每个方法负责不同的请求操作。如何将请求映射到对应的控制器方法中是 Spring MVC框架的重要任务之一,这项任务由@RequestMapping 承担。
在控制器的类定义及方法定义处都可以标注@RequestMapping,类定义处的@RequestMapping提供初步的请求映射信息,方法定义处的@RequestMapping 提供进一步的细分映射信息。DispatcherServlet 截获请求后,就通过控制器上@RequestMapping 提供的映射信息确定请求所对应的处理方法。
将请求映射到控制器处理方法的工作包含一系列映射规则,这些规则是根据请求中的各种信息制定的,具体包括请求URL、请求参数、请求方法、请求头这4个方面的信息项。
首先查看@Controller源码:
1 |
|
从源码可以看出@Controller注解只有一个value属性,这个属性用于配置JavaBean在IOC容器中实例的名称,如果不配置则默认是类名首字母小写。下面的示例将演示这个注解的用法。
1 |
|
@RequestMapping注解
在上一小节已经简单介绍了@RequestMapping注解,@RequestMapping的作用是将HTTP请求正确的映射到对应的类中的方法。从而让对应的方法处理请求,并给出做出响应。首先查询@RequestMapping的源码:
1 |
|
@RequestMapping注解支持的常用属性示例如下。
属性 | 类型 | 是否必要 | 说明 |
---|---|---|---|
value | String[] | 否 | 用于将指定请求的地址映射到方法 |
name | String | 否 | 给映射地址指定一个别名 |
method | RequestMethod[] | 否 | 映射指定请求的方法,包括GET、POST、HEAD、OPTIONS、PUT、PATCH、DELETE、TRACE |
consumes | String[] | 否 | 指定处理请求的提交内容(Content-Type),例如:application/json |
produces | String[] | 否 | 指定返回的内容类型,返回的内容类型必须是request请求头中所包含的类型 |
params | String[] | 否 | 指定request中必须包含某些参数值时,才让该方法处理请求 |
headers | String[] | 否 | 指定request中必须包含某些指定的header值,才能让该方法处理请求 |
path | String[] | 否 | 用于将指定请求的地址映射到方法 |
1.value属性:@RequestMapping 是一个用来处理请求地址映射的注解,可以使用 @RequestMapping 注释一个方法或类。一个采用@RequestMapping注释的方法将成为一个请求处理方法, 例如:
1 |
|
2.method属性,该属性用来指示该方法仅处理哪些HTTP请求方式。
1 |
以上代码method=RequestMethod.GET表示该方法支持GET请求。也可以同时支持多个HTTP请求方式,如:
1 |
Spring 4.3 之后,新增了@GetMapping、@PostMapping、 @PutMapping、@DeleteMapping、@PatchMapping 注解,这几个注解可 以指定的属性和@RequestMapping注解类似,区别在于@GetMapping注 解只支持GET方式的请求;@PostMapping注解只支持POST方式的请求,@PutMapping@DeleteMapping、@PatchMapping分别对应PUT请 求、DELETE请求和PATCH请求,使用比较少。
3.consumes属性 该属性指定处理请求的提交内容类型(Content-Type)。
1 |
表示方法仅处理request Content-Type为“application/json”类型的请求。
4.produces属性,该属性指定返回的内容类型,返回的内容类型必须是 request 请求
头(Accept)中所包含的类型。
1 |
方法仅处理request请求中Accept头中包含了"application/json"的请 求,同时指明了返回的内容类型为application/json。
5.params属性 该属性指定request中必须包含某些参数值时,才让该方法处理。
1 |
方法仅处理其中名为“param、值为“value”的请求。
@RequestMapping 不但支持标准的 URL,还支持 Ant 风格(?、*和**字符)的和带{xxx}占位符的URL。以下 URL 都是合法的。
- /user/*/createUser∶ 匹配/user/aa/createUser、/user/bbb/createUser等 URL。
- /user/**/createUser∶匹配/user/createUser、/user/aaa/bbb/createUser 等URL。
- /user/createUser??∶匹配/user/createUseraa、/user/createUserbb等 URL。
- /user/{userld}∶匹配 user/123、user/456 等URL。
- /user/**/{userId}∶匹配 user/aa/bbb/123、user/aaa/456等 URL。
- company/{companyld}/user/{userId}/detail∶匹配 company/123/user/456/detail 等 URL。
请求处理方法参数
Spring MVC 对控制器处理方法签名的限制是很宽松的,用户几乎可以按自己喜欢的方式进行方法签名。在必要时对方法及方法入参标注相应的注解(如@PathVariable、@RequestParam、@RequestHeader 等)即可,Spring MVC 会优雅地完成剩下的工作∶将 HTTP请求的信息绑定到相应的方法入参中,并根据方法返回值类型做出相应的后续处理。
@RequestParam
在Servlet中我们知道,如果需要获取请求参数,需要使用HttpServletRequest对象的getParameter()方法,在SpringMVC中,只需要将方法参数列表中参数名称和请求参数名称保持一致,SpringMVC会自动将同名请求参数绑定到方法参数中,下面将示例这种用法:
新建页面,在页面中放置表单
1 | <body> |
定义Controller,并将页面提交的数据
1 |
|
需要注意的是页面中参数的name要和方法的参数名称保持一致,否则参数无法映射。如果出现页面中提交的参数名称不一致的情况,也可以使用@RequestParam注解将请求参数和方法参数进行绑定。以上例为例,假设页面中标签的name属性为username,那么在controller的方法参数上可以做如下修改:
1 |
|
查看@RequestParam注解源码:
1 |
|
各个属性含义如下:
属性 | 类型 | 是否必须 | 说明 |
---|---|---|---|
name | String | 否 | 指定请求参数绑定的名称 |
value | String | 否 | name属性的别名 |
required | boolean | 否 | 指定参数是否必须绑定 |
defaultValue | String | 否 | 如果没有传递参数则使用默认值 |
在@RequestParam注解的属性中需要特别注意的是required属性,该属性指参数是否必须绑定,默认是true,也就是说如果不绑定参数值,即没有向服务端传递对应的参数,程序将抛出异常。
多个请求参数的绑定
在上一小节的示例中可以知道通过请求参数和方法参数的绑定,如果请求参数较少的情况下可以使用这种方式,但是如果请求参数较多的情况下这种方式显得不那么方便,此时,可以将请求参数封装到VO类中,例如登录时,通常需要填写用户名和密码,此时就可以将用户名和密码封装到一个VO中,需要注意的是,请求参数的名称必须要和VO对象的实例变量名称相同如下例所示:
1 | <body> |
1 |
|
这种方式不但简化了请求参数的接收,也方便数据合法性的验证,关于数据验证的内容将会在下一章节进行讲解。
视图解析器
请求处理方法执行完成后,最终返回一个ModelAndView对象。对于那些返回String、View 或 ModelMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个ModelAndView 对象,该对象包含了视图逻辑名和模型对象的信息。 Spring MVC借助视图解析器(ViewResolver)得到最终的视图对象(View),这可能是我们常见的 JSP 视图,也可能是一个基于FreeMarker、Velocity 模板技术的视图,还可能是PDF、Excel、XML、JSON 等各种形式的视图。
视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。视图对象可以是常见的 JSP,还可以是 Excel或PDF 等形式不一的媒体形式。为了实现视图模型和具体实现技术的解耦,Spring在 org.springframework.web.servlet 包中定义了一个高度抽象的 View接口,该接口中定义了两个方法。 口 String getContentType()∶视图对应的 MIME类型,如 text/html、image/jpeg 等。口 void render(Map model,HttpServletRequest request,HttpServletResponse response)∶将 模型数据以某种MIME 类型渲染出来。 视图对象是一个 Bean,通常情况下,视图对象由视图解析器负责实例化。由于视图 Bean是无状态的,所以它们不会有线程安全的问题。
不同类型的视图实现技术对应不同的View实现类,这些视图实现类都位于org.springframework.web.servlet.view包中,常见的View如下:
视图类型 | 说明 |
---|---|
InternalResourceView | 将JSP活其他资源封装成一个视图,这InternalResourceViewResolver默认使用的视图实现类 |
JstlView | 如果JSP文件中使用了JSTL国际化标签的功能,则需要使用该视图 |
FreeMakerView | 使用FreeMaker模板引擎的视图 |
MappingJackson2JsonView | 将模型数据通过Jackson开源框架的ObjectMapper以JSON方式输出 |
返回视图
在web开发中通常处理完一个请求后,需要跳转到某个页面或者Controller,本小节将会详细介绍如何返回视图。
利用方法返回值
在SpringMVC中通过控制器内的方法来接受请求并处理请求,在定义方法时,可以将方法返回值定义成String类型,当处理请求后,直接返回视图的名称,SpringMVC会自动寻找返回值对应的视图,并进行跳转
1 |
|
使用View
在上面的内容中讲解了集中常见的View类型,如果使用View跳转页面时,可以将方法的返回值定义为View类型,在方法中创建View子类对象,从而进行视图的返回
1 |
|
在实际开发中,有时候不但需要跳转页面还需要把从数据库获取的数据传递到页面。很明显此时仅仅返回String或者View是不能满足需要的。那么如何解决这个问题呢?
针对这个问题,可以在方法参数中传入Model对象,Model对象用于将数据发送到视图,因为SpringMVC跳转视图默认使用请求转发方式,因此Model通常将数据封装进request对象。当页面跳转是,会自动将数据发送到视图。Model通过如下方法添加数据:
1 | Model addAttribute(String attributeName, ; Object attributeValue) |
下面的实例将演示如何使用Model传递数据:
1 |
|
使用ModelAndView
控制器处理方法的返回值如果是ModelAndView,则其既包含模型 数据信息,也包含视图信息,这样Spring MVC将使用包含的视图对模型 数据进行渲染。可以简单地将模型数据看成一个Map<String,Object>
对象。在处理方法中可以使用ModelAndView对象的如下方法添加模型数据:
1 | addObject(String attributeName,Object attributeValue); |
可以通过如下方法设置视图:
1 | setViewName(String viewName); |
下面示例ModelAndView的区别
1 |
|
视图解析
在web开发中,通常会将页面放置在WEB-INF目录下,如果在JSP/Servlet项目中,可以利用过滤器对请求进行转发,在SpringMVC中可以以如下方式配置:
1 | <bean id="internalResourceView" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> |
其中prefix配置了页面跳转的前缀路径,而suffix通常配置视图的扩展名,这样在跳转视图时,只需要写视图名称即可。例如跳转到/WEB-INF/success.jsp时,只需要填写视图名称success。
静态资源处理
在使用SpringMVC开发应用时,因为所有的请求都交由了DispatcherServlet处理,而DispatcherServlet并不会对静态资源进行处理,这就需要手动配置静态资源的位置。
<mvc∶resources/允许静态资源放置在任何地方,如 WEB-INF 目录下、类路径下等,甚至可以将 JavaScript 等静态文件打包到JAR 包中。通过location 属性指定静态资源的位置,由于location 属性是Resource类型,因此可以使用诸如”classpath∶”等的资源前缀指定资源位置。传统 Web 容器的静态资源只能放在 Web 容器的根路径下,<mvc∶resources/>则完全打破了这个限制。
在接收到静态资源的获取请求时,会检查请求头的Last-Modified值。如果静态资源没有发生变化,则直接返回 303响应状态码,指示客户端使用浏览器缓存的数据,而非将静态资源的内容输出到客户端,以充分节省带宽,提高程序性能。
在SpringMVC配置文件中进行如下配置:
1 | <mvc:resources mapping="/static/**" location="/WEB-INF/static"></mvc:resources> |
其中mapping属性配置的是访问静态资源时的路径,而location属性则是指静态资源实际存放的位置。
@SessionAttribute和@CookieValue
@SessionAttribute注解允许我们有选择地指定Model中的哪些属性转存到 HttpSession对象当中。 该注解源码如下:
1 |
|
示例代码如下:
1 |
|
以上代码会自动将session作用域中名为username的属性的值设置到username参数上。 @CookieValue的作用和@SessionAttribute的作用类似,只是作用域由Session变成了Cookie。