Spring4.x官方参考文档中文版——第21章 Web MVC框架(20)

来源:互联网 发布:dbc2000 传奇数据库 编辑:程序博客网 时间:2024/05/04 10:04

21.7 URI的组建

       Spring MVC提供了一种机制,可以使用UriComponentsBuilder和UriComponents来组建并编码URI。

       如下例所示,你能扩展并编码一个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组件来扩展并编码URI:

UriComponents uriComponents =UriComponentsBuilder.newInstance()       .scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}").build()       .expand("42", "21")       .encode();

       在Servlet环境下,ServletUriComponentBuilder的子类提供了一个静态工厂方法,这个方法可以从Servlet请求中,复制有效的URL信息。如下:

HttpServletRequest request = ... // 重用原request中的host,scheme格式,端口,路径和查询参数的字符串// 替换掉"accountId" 的查询参数值 ServletUriComponentsBuilder ucb =ServletUriComponentsBuilder.fromRequest(request)       .replaceQueryParam("accountId", "{id}").build()       .expand("123")       .encode();

       此外,你也可以选择拷贝可用信息中的一部分,并追加到context路径后面:

// 重用host,port(端口)和context路径// 把"/accounts"追加到路径后面 ServletUriComponentsBuilder ucb =ServletUriComponentsBuilder.fromContextPath(request)       .path("/accounts").build()

        或者,在DispatcherServlet已基于名字进行了映射时(比如/main/*这种),你也可以获得servlet映射所包含的部分值,如下:

// 重用 host, port,context path// 追加servlet映射到路径下的部分值// 追加"/accounts" 到路径上 ServletUriComponentsBuilder ucb =ServletUriComponentsBuilder.fromServletMapping(request)       .path("/accounts").build()

21.7.1 组建连接到controller和方法的URI

       Spring MVC提供了一种机制,能组建连接到controller的方法中的链接,如下例所示:

UriComponents uriComponents = MvcUriComponentsBuilder   .fromMethodName(BookingController.class, "getBooking", 21).buildAndExpand(42); URI uri = uriComponents.encode().toUri();

       在上面的例子中,我们提供了实际的方法入参值,在此情况下,这个长整形值21会被看作路径变量来使用,并且把它添加到URL中。此外,我们提供了42这个值,用来填补在URI中剩余的变量,比如从类级别请求映射中继承的”hotel”变量。如果在这个方法里有更多的入参,你能够为那些URL并不需要的入参设置为null。一般来说,只有@PathVariable和@RequestParam的入参与构建URL相关。

       还有一种额外的方法来使用MvcUriComponentsBuilder。例如:你可以使用某种类似mock测试的技术,这种技术通过代理来避免基于名称来参考匹配控制器的方法。(下面的例子假设静态导入了MvcUriComponentsBuilder.on):

UriComponents uriComponents =MvcUriComponentsBuilder   .fromMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42); URI uri = uriComponents.encode().toUri();

       上面的例子使用MvcUriComponentsBuilder中的静态方法。在这个方法内部,它们依赖于ServletUriComponentsBuilder来从现存的请求中,根据它的scheme(结构), host, port(端口),context路径和servlet路径,准备好URL。再多数情况下,这样效果很好,但有些情况下,可能会效率低下。例如:你可能会在请求的context的外面(比如:链接准备时的批量处理过程)或者你需要插入一个路径的前缀(例如: 本地前缀从请求路径中被移除了,并且需要重新添加到链接中)。

       在这种情况下,你可以使用静态的”fromXxx”重载的方法来允许一个UriComponentsBuilder来使用URL。或者,你可以创建一个带有URL的MvcUriComponentsBuilder的实例,然后使用这个实例的”withXxx”的方法,例如: 

UriComponentsBuilder base = ServletUriComponentsBuilder.fromCurrentContextPath().path("/en");MvcUriComponentsBuilder builder = MvcUriComponentsBuilder.relativeTo(base);builder.withMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42); URI uri = uriComponents.encode().toUri();

21.7.2 在视图中组建连接到controller和方法中的URI

       你同样可以从类似JSP,Thymeleaf, FreeMarker等视图中,组建链接到注解式controller中。可以通过使用MvcUriComponentsBuilder中的fromMappingName方法来实现,这个方法是基于名字来进行映射的。

       每一个@RequestMapping都被赋予了一个默认名,这个名字默认是类名中的大写字母加上方法名的全称。例如,有个方法叫”getFoo”,这个方法在FooController中,那么这个默认名就是”FC#getFoo”。这种命名的策略还可以通过创建HandlerMethodMappingNamingStrategy的实例,并把这个实例加入进你的RequestMappingHandlerMapping中来进行自定义。这种默认策略的实现,也会在@RequestMapping中的name属性存在时进行使用。这表示,默认指定的映射名与另一个名字冲突的时候(比如:重载的方法),你可以在@RequestMapping上显式地为其指定一个名字。

 

请注意:

       这些被指定了的请求映射名会在启动时的TRACE级别记录日志。

 

       Spring的JSP标签库提供了一个叫做mvcUrl的功能,这个功能能基于它的的机制,来把需要连接到controller方法的链接准备到位。如下例:

@RequestMapping("/people/{id}/addresses")public class PersonAddressController {     @RequestMapping("/{country}")    public HttpEntity getAddress(@PathVariable String country) { ... }}

       你能够为其准备好一个链接,如下:

<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>...<a href="${s:mvcUrl(''PAC#getAddress'').arg(0,''US'').buildAndExpand(''123'')}">Get Address</a>

       上面的例子中,依赖了在JSP中声明了Spring标签库(比如META-INF/spring.tld)的 mvcUrl这个功能。若需处理更多进阶的情况(比如在上一节讲到过的自定义URL),为了使用拥有一个自定基础URL的特定的MvcUriComponentsBuilder实例,来自定义一个功能,或者是使用自定义的标签文件,都是很方便的。

1 0
原创粉丝点击