本文共 8641 字,大约阅读时间需要 28 分钟。
这ContentNegotiatingViewResolver
不会解析视图本身,而是委托给其他视图解析器,选择类似于客户端请求的表示的视图。客户端可以从服务器请求表示方式存在两种策略:
请求用户fred的PDF表示,并
请求XML表示。Accept
HTTP请求标头以列出它理解的。例如,一个HTTP请求,
其中一个Accept
头设置为application/pdf
请求用户fred的PDF表示,同时
使用Accept
头设置来text/xml
请求XML表示。这个策略被称为 。 Accept 标题的一个问题是,不可能在HTML中的Web浏览器中设置它。例如,在Firefox中,它被修改为: 接受:text / html,application / xhtml + xml,application / xml; q = 0.9,* / *; q = 0.8 因此,在开发基于浏览器的Web应用程序时,通常会看到每个表示使用不同的URI。 |
为了支持资源的多个表示,Spring提供了 ContentNegotiatingViewResolver
根据Accept
HTTP请求的文件扩展名或头部来解析视图。ContentNegotiatingViewResolver
不执行视图分辨率本身,而是委托给您通过bean属性指定的视图解析器的列表ViewResolvers
。
在ContentNegotiatingViewResolver
选择一个合适的View
通过比较与所述媒体类型(也被称为媒体请求类型(一个或多个),以处理该请求 Content-Type
由支持)的View
与每个其相关联ViewResolvers
。View
具有兼容性的列表中的第一个将表示Content-Type
返回给客户端。如果链条不能提供兼容的视图,则会查看ViewResolver
通过DefaultViews
属性指定的视图列表。后一个选项适用于Views
可以呈现当前资源的适当表示的单例,而不管逻辑视图名称如何。的Accept
报头可以包括通配符,例如text/*
,在这种情况下View
,其内容类型是text/xml
为相容的匹配。
要支持基于文件扩展名的视图的自定义解析,请使用 ContentNegotiationManager
:请参见。
以下是一个示例配置ContentNegotiatingViewResolver
:
web.servlet.view.json.MappingJackson2JsonView“ /> web.servlet.view.json.MappingJackson2JsonView“ />
该InternalResourceViewResolver
手柄视图名称和JSP页面的翻译,而BeanNameViewResolver
返回基于bean的名称的视图。(有关Spring如何查找和实例化视图的更多详细信息,请参阅“ 解析视图”。)在此示例中,该content
bean是继承的类,该类AbstractAtomFeedView
返回Atom RSS提要。有关创建Atom Feed表示的更多信息,请参阅Atom视图。
在上述配置中,如果使用扩展名进行请求.html
,视图解析器将查找与text/html
媒体类型匹配的视图。在 InternalResourceViewResolver
提供了用于匹配视图text/html
。如果请求是使用文件扩展名.atom
,视图解析器将查找与application/atom+xml
媒体类型相匹配的视图。该视图由该 BeanNameViewResolver
映射提供给SampleContentAtomView
如果返回的视图名称是content
。如果使用文件扩展名进行请求.json
,则无论视图名称如何, MappingJackson2JsonView
将从DefaultViews
列表中选择实例。或者,客户端请求可以在没有文件扩展名的情况下进行,但是将Accept
标题设置为首选媒体类型,并且将发生对视图请求的相同解析。
如果“ContentNegotiatingViewResolver”的ViewResolver列表未被明确配置,它会自动使用应用程序上下文中定义的任何ViewResolvers。 |
相应的控制器代码返回表单的URI 或
应用
Accept
程序/ atom + xml 的头部的Atom RSS提要 如下所示。
@Controller public class ContentController { private ListcontentList = new ArrayList (); @GetMapping(“/ content”) public ModelAndView getContent(){ ModelAndView mav = new ModelAndView(); mav.setViewName(“content”); mav.addObject(“sampleContentList”,contentList); 返回 mav }}
Flash属性为一个请求存储旨在用于另一个的属性提供了一种方法。这是重定向时最常用的 – 例如 Post / Redirect / Get模式。闪存属性在重定向(通常在会话中)之前临时保存,以便在重定向后立即对请求提供可用的请求。
Spring MVC有两个主要的抽象支持Flash属性。FlashMap
用于保存Flash属性,FlashMapManager
用于存储,检索和管理 FlashMap
实例。
Flash属性支持始终是“开”的,不需要明确启用,尽管如果不使用它,它不会导致HTTP会话创建。在每个请求上都有一个“输入” FlashMap
,它具有从先前的请求传递的属性(如果有的话)和FlashMap
带有属性的“输出” ,以保存后续请求。这两个FlashMap
实例可以通过静态方法在Spring MVC中从任何地方访问RequestContextUtils
。
注释控制器通常不需要FlashMap
直接使用。相反, @RequestMapping
方法可以接受类型的参数,RedirectAttributes
并使用它来为重定向方案添加闪存属性。添加的Flash属性将 RedirectAttributes
自动传播到“输出”FlashMap。类似地,在重定向之后,来自“输入” FlashMap
的属性将自动添加到 Model
为目标URL提供服务的控制器中。
Spring MVC提供了一种用于使用UriComponentsBuilder
和构建和编码URI的机制 UriComponents
。
例如,您可以扩展和编码URI模板字符串:
UriComponents uriComponents = UriComponentsBuilder.fromUriString( “http://example.com/hotels/{hotel}/bookings/{booking}”).build();URI uri = uriComponents.expand(“42”,“21”).encode()。toUri();
请注意,这UriComponents
是不可变的expand()
,encode()
如果需要,并且操作返回新的实例。
您还可以使用各个URI组件进行扩展和编码:
UriComponents uriComponents = UriComponentsBuilder.newInstance() .scheme(“http”). host(“example.com”).path(“/酒店/ {酒店} /预订/ {预订}”).build() .expand(“42”,“21”) .encode();
在Servlet环境中,ServletUriComponentsBuilder
子类提供静态工厂方法从Servlet请求中复制可用的URL信息:
HttpServletRequest request = ...//重新使用host,scheme,port,path和query string //替换“accountId”查询参数ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromRequest(request) .replaceQueryParam(“accountId”,“{id}”).build() .expand(“123”) .encode();
或者,您可以选择复制可用信息的子集,直到并包括上下文路径:
//重新使用主机,端口和上下文路径//将“/ accounts”附加到路径ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromContextPath(request) .path(“/ accounts”).build()
或者在DispatcherServlet
按名称(例如/main/*
)映射的情况下,还可以包含servlet映射的文字部分:
//重新使用主机,端口,上下文路径//将servlet映射的文字部分附加到路径//将“/ accounts”附加到路径ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromServletMapping(request) .path(“/ accounts”).build()
Spring MVC还提供了一种构建控制器方法链接的机制。例如,给出:
@Controller @RequestMapping(“/ hotels / {hotel}”) public class BookingController { @GetMapping(“/ bookings / {booking}”) public String getBooking( @PathVariable Long booking){ // ... }}
您可以通过名称参考方法来准备链接:
UriComponents uriComponents = MvcUriComponentsBuilder .fromMethodName(BookingController 类,“getBooking” ,21).buildAndExpand(42);URI uri = uriComponents.encode()。toUri();
在上面的例子中,我们提供了实际的方法参数值,在这种情况下是长值21,用作路径变量并插入到URL中。此外,我们提供了值42,以填充任何剩余的URI变量,例如从类型级请求映射继承的“hotel”变量。如果该方法有更多的参数,您可以为URL不需要的参数提供null。一般而言@PathVariable
,@RequestParam
参数与构造URL相关。
还有其他的使用方法MvcUriComponentsBuilder
。例如,您可以使用类似于通过代理模拟测试的技术,以避免通过名称引用控制器方法(示例假定静态导入MvcUriComponentsBuilder.on
):
UriComponents uriComponents = MvcUriComponentsBuilder .fromMethodCall(上(BookingController。类).getBooking(21))buildAndExpand(42);URI uri = uriComponents.encode()。toUri();
上面的例子使用静态方法MvcUriComponentsBuilder
。在内部,他们依靠ServletUriComponentsBuilder
从当前请求的方案,主机,端口,上下文路径和servlet路径准备基本URL。这在大多数情况下运行良好,但有时可能不足。例如,您可能不在请求的上下文中(例如,准备链接的批处理),或者您可能需要插入路径前缀(例如,从请求路径中删除并需要重新插入到链接中的区域设置前缀)。
对于这种情况,您可以使用接受a UriComponentsBuilder
使用基本URL 的静态“fromXxx”重载方法 。或者您可以MvcUriComponentsBuilder
使用基本URL 创建一个实例,然后使用基于实例的“withXxx”方法。例如:
UriComponentsBuilder base = ServletUriComponentsBuilder.fromCurrentContextPath()。path(“/ en”);MvcUriComponentsBuilder builder = MvcUriComponentsBuilder.relativeTo(base);builder.withMethodCall(上(BookingController。类).getBooking(21))buildAndExpand(42);URI uri = uriComponents.encode()。toUri();
您还可以从JSP,Thymeleaf,FreeMarker等视图中构建带注释控制器的链接。这可以使用fromMappingName
方法,MvcUriComponentsBuilder
其中指的是按名称映射。
每个都会@RequestMapping
根据类的大写字母和完整的方法名称分配一个默认名称。例如,getFoo
类FooController
中的方法被分配名称“FC#getFoo”。该策略可以通过创建一个实例HandlerMethodMappingNamingStrategy
并将其插入到您中 来进行替换或定制RequestMappingHandlerMapping
。默认策略实现也会查看name属性@RequestMapping
,如果存在,则使用该属性。这意味着如果分配的默认映射名称与另一个冲突(例如重载方法),则可以在该目录上明确指定一个名称@RequestMapping
。
分配的请求映射名称在启动时记录在TRACE级别。 |
Spring JSP标签库提供了一个名为mvcUrl
该函数的函数,可用于根据此机制准备到控制器方法的链接。
例如:
@RequestMapping(“/ people / {id} / addresses”) public class PersonAddressController { @RequestMapping(“/ {country}”) public HttpEntity getAddress( @PathVariable String country){...}}
您可以从JSP准备一个链接,如下所示:
%@ taglib uri =“http://www.springframework.org/tags”prefix =“s”%>...获取地址
上述示例依赖于mvcUrl
在Spring标签库(即META-INF / spring.tld)中声明的JSP函数。对于更高级的案例(例如上一节所述的自定义基本URL),可以轻松地定义自己的函数或使用自定义标记文件,以便使用MvcUriComponentsBuilder
具有自定义基本URL 的特定实例。
Spring的大部分架构支持国际化,就像Spring Web MVC框架一样。DispatcherServlet
使您能够使用客户端的语言环境自动解析邮件。这是用LocaleResolver
对象完成的。
当一个请求进来时,DispatcherServlet
寻找一个区域设置解析器,如果它找到一个它试图使用它来设置区域设置。使用该RequestContext.getLocale()
方法,您可以随时检索由语言环境解析器解析的区域设置。
除了自动区域设置解析之外,您还可以将拦截器附加到处理程序映射(参见以获取有关处理程序映射拦截器的更多信息),以在特定情况下更改区域设置,例如,基于请求中的参数。
org.springframework.web.servlet.i18n
程序包中定义了语言环境解析器和拦截器, 并以正常方式在应用程序上下文中配置。以下是Spring中包含的区域解析器的选择。
除了获取客户的区域设置之外,了解他们的时区通常也是有用的。该LocaleContextResolver
界面提供了一个扩展LocaleResolver
,允许解析器提供更丰富LocaleContext
,可能包括时区信息。
如果可用,TimeZone
可以使用该RequestContext.getTimeZone()
方法获得 用户。时区信息将自动被Date / Time Converter
和Formatter
Spring注册的对象使用ConversionService
。
该语言环境解析器检查accept-language
客户端发送的请求中的标题(例如,Web浏览器)。通常此标题字段包含客户端操作系统的区域设置。请注意,此解析器不支持时区信息。
这个本地化解析器检查一个Cookie
可能的客户端中,看是否有 Locale
或TimeZone
指定。如果是这样,它使用指定的细节。使用此语言环境解析器的属性,您可以指定cookie的名称以及最大的年龄。在下面找到一个定义a的例子CookieLocaleResolver
。
<! - 以秒为单位。如果设置为-1,则cookie不会持久化(在浏览器关闭时删除) - >
表18.4。CookieLocaleResolver属性
属性 | 默认 | 描述 |
---|---|---|
cookieName | classname + LOCALE | cookie的名称 |
名cookieMaxAge | Servlet容器默认 | Cookie在客户端上保持持续的最长时间。如果指定了-1,则cookie不会被持久化; 只有客户端关闭浏览器才可用。 |
cookiePath | / | 将Cookie的可见性限制在您网站的某个部分。指定cookiePath时,cookie将只对该路径及其下方的路径可见。 |
在SessionLocaleResolver
可以检索Locale
并TimeZone
从可能与用户的请求相关的会话。相反 CookieLocaleResolver
,该策略将本地选择的区域设置存储在Servlet容器中HttpSession
。因此,这些设置对于每个会话都是临时的,因此在每个会话终止时丢失。
请注意,与Spring Session项目之类的外部会话管理机制没有直接关系。这SessionLocaleResolver
将简单地根据HttpSession
当前值来评估和修改相应的属性HttpServletRequest
。