`
yimeng528
  • 浏览: 188766 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

基于Spring MVC的Web应用开发(6) - Response

阅读更多

本文讲解Spring MVC的Response,深入了解一下@RequestMapping配合@ResponseBody的用法,同时介绍另外一个和Response有关的类ResponseEntity。

首先看看本文演示用到的类ResponseController:

Java代码 复制代码 收藏代码
  1. package org.springframework.samples.mvc.response;   
  2.   
  3. import org.springframework.http.HttpHeaders;   
  4. import org.springframework.http.HttpStatus;   
  5. import org.springframework.http.MediaType;   
  6. import org.springframework.http.ResponseEntity;   
  7. import org.springframework.stereotype.Controller;   
  8. import org.springframework.web.bind.annotation.RequestMapping;   
  9. import org.springframework.web.bind.annotation.RequestMethod;   
  10. import org.springframework.web.bind.annotation.ResponseBody;   
  11.   
  12. @Controller  
  13. public class ResponseController {   
  14.   
  15.     @RequestMapping(value="/response/annotation", method=RequestMethod.GET)   
  16.     public @ResponseBody String responseBody() {   
  17.         return "The String ResponseBody";   
  18.     }   
  19.   
  20.     @RequestMapping(value="/response/charset/accept", method=RequestMethod.GET)   
  21.     public @ResponseBody String responseAcceptHeaderCharset() {   
  22.         return "こんにちは世界! (\"Hello world!\" in Japanese)";   
  23.     }   
  24.   
  25.     @RequestMapping(value="/response/charset/produce", method=RequestMethod.GET, produces="text/plain;charset=UTF-8")   
  26.     public @ResponseBody String responseProducesConditionCharset() {   
  27.         return "こんにちは世界! (\"Hello world!\" in Japanese)";   
  28.     }   
  29.   
  30.     @RequestMapping(value="/response/entity/status", method=RequestMethod.GET)   
  31.     public ResponseEntity<String> responseEntityStatusCode() {   
  32.         return new ResponseEntity<String>("The String ResponseBody with custom status code (403 Forbidden - stephansun)",   
  33.                 HttpStatus.FORBIDDEN);   
  34.     }   
  35.   
  36.     @RequestMapping(value="/response/entity/headers", method=RequestMethod.GET)   
  37.     public ResponseEntity<String> responseEntityCustomHeaders() {   
  38.         HttpHeaders headers = new HttpHeaders();   
  39.         headers.setContentType(MediaType.TEXT_PLAIN);   
  40.         return new ResponseEntity<String>("The String ResponseBody with custom header Content-Type=text/plain",   
  41.                 headers, HttpStatus.OK);   
  42.     }   
  43.   
  44. }  
package org.springframework.samples.mvc.response;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class ResponseController {

	@RequestMapping(value="/response/annotation", method=RequestMethod.GET)
	public @ResponseBody String responseBody() {
		return "The String ResponseBody";
	}

	@RequestMapping(value="/response/charset/accept", method=RequestMethod.GET)
	public @ResponseBody String responseAcceptHeaderCharset() {
		return "こんにちは世界! (\"Hello world!\" in Japanese)";
	}

	@RequestMapping(value="/response/charset/produce", method=RequestMethod.GET, produces="text/plain;charset=UTF-8")
	public @ResponseBody String responseProducesConditionCharset() {
		return "こんにちは世界! (\"Hello world!\" in Japanese)";
	}

	@RequestMapping(value="/response/entity/status", method=RequestMethod.GET)
	public ResponseEntity<String> responseEntityStatusCode() {
		return new ResponseEntity<String>("The String ResponseBody with custom status code (403 Forbidden - stephansun)",
				HttpStatus.FORBIDDEN);
	}

	@RequestMapping(value="/response/entity/headers", method=RequestMethod.GET)
	public ResponseEntity<String> responseEntityCustomHeaders() {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.TEXT_PLAIN);
		return new ResponseEntity<String>("The String ResponseBody with custom header Content-Type=text/plain",
				headers, HttpStatus.OK);
	}

}

 

访问http://localhost:8080/web/response/response/annotation,对应responseBody(),这个方法很典型,之前已经见过多次了,将字符串直接输出到浏览器。

 

访问http://localhost:8080/web/response/charset/accept,对应responseAcceptHeaderCharset(),该方法和responseBody()并没有什么不同,只是,返回的字符串中带有日文。浏览器显示"???????? ("Hello world!" in Japanese)",有乱码出现。

 

访问http://localhost:8080/web/response/charset/produce,对应responseProducesConditionCharset(),该方法跟responseAcceptHeaderCharset()相比,在@RequestMapping中增加了“produces="text/plain;charset=UTF-8"”,浏览器显示"こんにちは世界! ("Hello world!" in Japanese)",乱码没有了。

为了将这两者的区别说清楚,看看日志:

responseAcceptHeaderCharset():

日志代码 复制代码 收藏代码
  1. DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor - Written [こんにちは世界! ("Hello world!" in Japanese)] as "text/html" using [org.springframework.http.converter.StringHttpMessageConverter@6b414655]  
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor - Written [こんにちは世界! ("Hello world!" in Japanese)] as "text/html" using [org.springframework.http.converter.StringHttpMessageConverter@6b414655]

responseProducesConditionCharset():

日志代码 复制代码 收藏代码
  1. DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor - Written [こんにちは世界! ("Hello world!" in Japanese)] as "text/plain;charset=UTF-8" using [org.springframework.http.converter.StringHttpMessageConverter@6b414655]  
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor - Written [こんにちは世界! ("Hello world!" in Japanese)] as "text/plain;charset=UTF-8" using [org.springframework.http.converter.StringHttpMessageConverter@6b414655]

 

前者使用默认的"text/html",后者使用了特定的"text/plain;charset=UTF-8"。为什么以"text/html"形式输出日文(其实中文也是一样的)就会乱码的根本原因我还没透彻地搞清楚,但我注意到spring-web-3.1.0.REALEASE.jar中org.springframework.http.converter.StringHttpMessageConverter中有这样一段代码:

Java代码 复制代码 收藏代码
  1. public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");  
public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");

应该跟"ISO-8859-1"有关系吧。

 

后者通过指定@RequestMapping的produces属性为text/plain,字符集为UTF-8,可以避免乱码,这个是可以理解的

 

最后看看responseEntityStatusCode()和responseEntityCustomHeaders()方法,这两个方法和前面的方法的区别是没有@ResponseBody,返回的类型为ResponseEntity<String>。

responseEntityStatusCode()方法返回一个字符串,并附带了HTTP状态码为HttpStatus.FORBIDDEN(即403);

responseEntityCustomHeaders()除了返回一个字符串,HTTP状态码为HttpStatus.OK(即200),还指定了返回内容的content-type为text/plain;

这里最容易困惑我们的就是HTTP状态码了,因为从浏览器的输出看不到任何与HTTP状态码相关的东西。

 

访问http://localhost:8080/web/response/entity/statushttp://localhost:8080/web/response/entity/headers

均能正常的将字符串内容显示在网页上,那么HttpStatus.FORBIDDEN起什么作用呢?

ResponseEntity继承于HttpEntity类,HttpEntity类的源代码的注释说"HttpEntity主要是和RestTemplate组合起来使用,同样也可以在SpringMVC中作为@Controller方法的返回值使用"。ResponseEntity类的源代码注释说"ResponseEntity是HttpEntity的扩展,增加了一个HttpStutus的状态码,通常和RestEntity配合使用,当然也可以在SpringMVC中作为@Controller方法的返回值使用"。那么使用RestTemplate写个程序模拟一下吧(RestTemplate的具体用法见本文附录):

Java代码 复制代码 收藏代码
  1. package org.springframework.samples.mvc.response;   
  2.   
  3. import org.springframework.http.HttpStatus;   
  4. import org.springframework.http.MediaType;   
  5. import org.springframework.http.ResponseEntity;   
  6. import org.springframework.web.client.RestTemplate;   
  7.   
  8. public class ResponseControllerTest {   
  9.   
  10.     public static void main(String[] args) {   
  11.         RestTemplate template = new RestTemplate();   
  12.         ResponseEntity<String> entity = template.getForEntity(   
  13.                 "http://localhost:8080/web/response/entity/status", String.class);   
  14.         String body = entity.getBody();   
  15.         MediaType contentType = entity.getHeaders().getContentType();   
  16.         HttpStatus statusCode = entity.getStatusCode();   
  17.         System.out.println("statusCode:[" + statusCode + "]");   
  18.     }   
  19. }  
package org.springframework.samples.mvc.response;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class ResponseControllerTest {

	public static void main(String[] args) {
		RestTemplate template = new RestTemplate();
		ResponseEntity<String> entity = template.getForEntity(
				"http://localhost:8080/web/response/entity/status", String.class);
		String body = entity.getBody();
		MediaType contentType = entity.getHeaders().getContentType();
		HttpStatus statusCode = entity.getStatusCode();
		System.out.println("statusCode:[" + statusCode + "]");
	}
}

访问http://localhost:8080/web/response/entity/status,观察日志:

日志代码 复制代码 收藏代码
  1. DEBUG: org.springframework.web.client.RestTemplate - Created GET request for "http://localhost:8080/web/response/entity/status"  
  2. DEBUG: org.springframework.web.client.RestTemplate - Setting request Accept header to [text/plain, */*]   
  3. WARN : org.springframework.web.client.RestTemplate - GET request for "http://localhost:8080/web/response/entity/status" resulted in 403 (Forbidden); invoking error handler   
  4. Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 403 Forbidden   
  5.     at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:76)   
  6.     at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:486)   
  7.     at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:443)   
  8.     at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401)   
  9.     at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:221)   
  10.     at org.springframework.samples.mvc.response.ResponseControllerTest.main(ResponseControllerTest.java:12)   
DEBUG: org.springframework.web.client.RestTemplate - Created GET request for "http://localhost:8080/web/response/entity/status"
DEBUG: org.springframework.web.client.RestTemplate - Setting request Accept header to [text/plain, */*]
WARN : org.springframework.web.client.RestTemplate - GET request for "http://localhost:8080/web/response/entity/status" resulted in 403 (Forbidden); invoking error handler
Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 403 Forbidden
	at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:76)
	at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:486)
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:443)
	at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401)
	at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:221)
	at org.springframework.samples.mvc.response.ResponseControllerTest.main(ResponseControllerTest.java:12) 

将URL换成http://localhost:8080/web/response/entity/headers,观察日志:

Java代码 复制代码 收藏代码
  1. DEBUG: org.springframework.web.client.RestTemplate - Created GET request for "http://localhost:8080/web/response/entity/headers"  
  2. DEBUG: org.springframework.web.client.RestTemplate - Setting request Accept header to [text/plain, */*]   
  3. DEBUG: org.springframework.web.client.RestTemplate - GET request for "http://localhost:8080/web/response/entity/headers" resulted in 200 (OK)   
  4. DEBUG: org.springframework.web.client.RestTemplate - Reading [java.lang.String] as "text/plain" using [org.springframework.http.converter.StringHttpMessageConverter@2e297ffb]   
  5. statusCode:[200]  
DEBUG: org.springframework.web.client.RestTemplate - Created GET request for "http://localhost:8080/web/response/entity/headers"
DEBUG: org.springframework.web.client.RestTemplate - Setting request Accept header to [text/plain, */*]
DEBUG: org.springframework.web.client.RestTemplate - GET request for "http://localhost:8080/web/response/entity/headers" resulted in 200 (OK)
DEBUG: org.springframework.web.client.RestTemplate - Reading [java.lang.String] as "text/plain" using [org.springframework.http.converter.StringHttpMessageConverter@2e297ffb]
statusCode:[200]

发现使用RestTemplate时,如果它发现返回的信息中HTTP状态码为403时,就抛出异常了,正好符合了我们的期望,至于为什么浏览器上没有体现,暂时还不不太明白(待补完)。

 

===================================================================

 

SpringSource的Team Blog上有一篇文章是关于@RequestMapping的produces属性的讨论。

 

===================================================================

 

附录Spring Reference Documentation中的相关内容:

 

[了解一下@RequesetMapping支持的返回值类型]

16.3.3.2 @RequestMapping注解方法支持的返回值类型

以下返回值的类型(return types)均支持:

  • ModelAndView对象,with the model implicitly enriched with command objects and the results of @ModelAttributes annotated reference data accessor methods.(恕我实在翻译不出 TAT)。
  • Model对象,with the view name implicitly determined through a RequestToViewNameTranslator and the model implicitly enriched with command objects and the results of @ModelAttribute annotated reference data accessor methods.
  • Map对象,for exposing a model, with the view name implicitly determined through a RequestToViewNameTranslator and the model implicitly enriched with command objects and the results of @ModelAttribute annotated reference data accessor methods.
  • View对象,with the model implicitly determined through command objects and @ModelAttribute annotated reference data accessor methods. The handler method may also programmatically enrich the model by declaring a Model argument (see above).
  • String,value that is interpreted as the logical view name, with the model implicitly determined through command objects and @ModelAttribute annotated reference data accessor methods. The handler method may also programmatically enrich the model by declaring a Model argument (see above).
  • void,if the method handles the response itself (by writing the response content directly, declaring an argument of type ServletResponse / HttpServletResponse for that purpose) or if the view name is supposed to be implicitly determined through a RequestToViewNameTranslator (not declaring a response argument in the handler method signature).
  • @ResponseBody,If the method is annotated with @ResponseBody, the return type is written to the response HTTP body. The return value will be converted to the declared method argument type using HttpMessageConverters. See Section 16.3.3.5, “Mapping the response body with the @ResponseBody annotation”.
  • HttpEntity或者ResponseEntityHttpEntity<?>或者ResponseEntity<?>对象可以取到Servlet的response的HTTP头信息(headers)和内容(contents)。这个实体(entity body)可以通过使用HttpMessageConverter类被转成Response流。See Section 16.3.3.6, “Using HttpEntity<?>”.
  • Any other return type is considered to be a single model attribute to be exposed to the view, using the attribute name specified through @ModelAttribute at the method level (or the default attribute name based on the return type class name). The model is implicitly enriched with command objects and the results of @ModelAttribute annotated reference data accessor methods.

 

[了解一下RestTemplate,下一篇文章有用]文档中有关RestTemplate的内容:

 

20.9 在客户端访问RESTful服务

RestTemplate是客户端访问RESTful服务的核心类。它在概念上同Spring中的其它模板类相似,如JdbcTemplate和JmsTemplate还有一些其它Spring portfolio工程中的模板类。RestTemplate提供了一个回调方法,使用HttpMessageConverter将对象marshal到HTTP请求体里,并且将response unmarshal成一个对象。使用XML作为消息格式是一个很普遍的做法,Spring提供了MarshallingHttpMessageConverter类,该类使用了Object-to-XML框架,该框架是org.springframe.oxm包的一部分。你有多种XML到Object映射技术可选。

本节介绍了如何使用RestTemplate以及和它相关的HttpMessageConverters。

20.9.1 RestTemplate

在Java中调用RESTful服务的一个经典的做法就是使用一个帮助类,如Jakarta Commons的HttpClient,对于通用的REST操作,HttpClient的实现代码比较底层,如下:

Java代码 复制代码 收藏代码
  1. String uri = "http://example.com/hotels/1/bookings";   
  2.   
  3. PostMethod post = new PostMethod(uri);   
  4. String request = // create booking request content   
  5. post.setRequestEntity(new StringRequestEntity(request));   
  6.   
  7. httpClient.executeMethod(post);   
  8.   
  9. if (HttpStatus.SC_CREATED == post.getStatusCode()) {   
  10.   Header location = post.getRequestHeader("Location");   
  11.   if (location != null) {   
  12.     System.out.println("Created new booking at :" + location.getValue());   
  13.   }   
  14. }  
String uri = "http://example.com/hotels/1/bookings";

PostMethod post = new PostMethod(uri);
String request = // create booking request content
post.setRequestEntity(new StringRequestEntity(request));

httpClient.executeMethod(post);

if (HttpStatus.SC_CREATED == post.getStatusCode()) {
  Header location = post.getRequestHeader("Location");
  if (location != null) {
    System.out.println("Created new booking at :" + location.getValue());
  }
}

 RestTemplate对HTTP的主要六种提交方式提供了更高层的抽象,使得调用RESTful服务时代码量更少,并且使REST表现的更好。

表格20.1 RestTemplate方法预览

 

HTTP方法 RestTemplate方法

DELETE delete

GET getForObject getForEntity

HEAD headForHeaders(String url, String... urlVariables)

OPTIONS optionsForAllow(String url, String... urlVariables)

POST postForLocation(String url, Object request, String... urlVariables) postForObject(String url, Object request, Class<T> responsetype, String... uriVariables)

PUT put(String url, Object request, String... urlVariables)

 

RestTemplate的方法名称遵循着一个命名规则,第一部分说明调用的是什么HTTP方法,第二部分说明的是返回了什么。比如,getForObject()方法对应GET请求,将HTTP response的内容转成你需要的一种对象类型,并返回这个对象。postForLocation()方法对应POST请求,converting the given object into a HTTP request and return the response HTTP Location header where the newly created object can be found.如果在执行一个HTTP请求时出现异常,会抛出RestClientException异常;可以在RestTemplate自定义ResponseErrorHandler的实现来自定义这种异常。

这些方法通过HttpMessageConverter实例将传递的对象转成HTTP消息,并将得到的HTTP消息转成对象返回。给主要mime类型服务的转换器(converter)默认就注册了,但是你也可以编写自己的转换器并通过messageConverters()bean属性注册。该模板默认注册的转换器实例是ByteArrayHttpMessageConverter,StringHttpMessageConverter,FormHttpMessageConverter以及SourceHttpMessageConverter。你可以使用messageConverters()bean属性重写这些默认实现,比如在使用MarshallingHttpMessageConverter或者MappingJacksonHttpMessageConverter时你就需要这么做。

每个方法有有两种类型的参数形式,一种是可变长度的String变量,另一种是Map<String, String>,比如:

Java代码 复制代码 收藏代码
  1. String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}",   
  2.                                           String.class,"42""21");  
String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}",
                                          String.class,"42", "21");

使用可变长度参数,

Java代码 复制代码 收藏代码
  1. Map<String, String> vars = Collections.singletonMap("hotel""42");   
  2. String result =   
  3.   restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);  
Map<String, String> vars = Collections.singletonMap("hotel", "42");
String result =
  restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);

使用一个Map<String, String> 。

你可以直接使用RestTemplate的默认构造器创建一个RestTemplate的实例。它会使用jdk中java.net包的标准Java类创建HTTP请求。你也可以自己指定一个ClientHttpRequestFactory的实现。Spring提供了CommonsClientHttpRequestFactory的实现,该类使用了Jakarta Commons的HttpClient创建HTTP请求。CommonsClientHttpRequestFactory配置了org.apache.commons.httpclient.HttpClient的一个实例,该实例反过来被credentials information或者连接池配置。

前面那个使用了Jakarta Commons的HttpClient类的例子可以直接使用RestTemplate重写,如下:

Java代码 复制代码 收藏代码
  1. uri = "http://example.com/hotels/{id}/bookings";   
  2.   
  3. RestTemplate template = new RestTemplate();   
  4.   
  5. Booking booking = // create booking object   
  6.   
  7. URI location = template.postForLocation(uri, booking, "1");  
uri = "http://example.com/hotels/{id}/bookings";

RestTemplate template = new RestTemplate();

Booking booking = // create booking object

URI location = template.postForLocation(uri, booking, "1");

通用的回调接口是RequestCallback,该接口在execute方法被调用时被调用。

Java代码 复制代码 收藏代码
  1. public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback,   
  2.                      ResponseExtractor<T> responseExtractor,   
  3.                      String... urlVariables)   
  4.   
  5.   
  6. // also has an overload with urlVariables as a Map<String, String>.  
public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback,
                     ResponseExtractor<T> responseExtractor,
                     String... urlVariables)


// also has an overload with urlVariables as a Map<String, String>.

RequestCallback接口定义如下:

Java代码 复制代码 收藏代码
  1. public interface RequestCallback {   
  2.  void doWithRequest(ClientHttpRequest request) throws IOException;   
  3. }  
public interface RequestCallback {
 void doWithRequest(ClientHttpRequest request) throws IOException;
}

该接口允许你管控(manipulate)request的header并且象request体中写数据。当使用execute方法时,你不必担心任何资源管理问题的,模板总是会关闭request,并且处理任何error,你可以参考API文档来获得更多有关使用execute方法及该模板其它方法参数含义的信息。

20.9.1.1 同URI一起工作

对HTTP的主要方法,RestTemplate的第一个参数是可变的,你可以使用一个String类型的URI,也可以使用java.net.URI类型的类,

String类型的URI接受可变长度的String参数或者Map<String, String>,这个URL字符串也是假定没有被编码(encoded)并且需要被编码的(encoded)的。举例如下:

Java代码 复制代码 收藏代码
  1. restTemplate.getForObject("http://example.com/hotel list", String.class);  
restTemplate.getForObject("http://example.com/hotel list", String.class);

这行代码使用GET方式请求http://example.com/hotel%20list。这意味着如果输入的URL字符串已经被编码了(encoded),它将被编码(encoded)两次 -- 比如:http://example.com/hotel%20list会变成http://example.com/hotel%2520list。如果这不是你所希望的,那就使用java.net.URI,它假定URL已经被编码(encoded)过了,如果你想要将一个单例的URI(fully expanded)复用多次的话,这个方法也是有用的。

UriComponentsBuilder类(我们已经见过了,不是吗? 译者)可以构建和编码一个包含了URI模板支持的URI,比如你可以从一个URL字符串开始:

Java代码 复制代码 收藏代码
  1. UriComponents uriComponents =    
  2.         UriComponentsBuilder.fromUriString("http://example.com/hotels/{hotel}/bookings/{booking}").build()   
  3.             .expand("42""21")   
  4.             .encode();   
  5.                
  6. URI uri = uriComponents.toUri();  
UriComponents uriComponents = 
        UriComponentsBuilder.fromUriString("http://example.com/hotels/{hotel}/bookings/{booking}").build()
            .expand("42", "21")
            .encode();
            
URI uri = uriComponents.toUri();

 或者单独地指定每个URI组件:

Java代码 复制代码 收藏代码
  1. UriComponents uriComponents =    
  2.         UriComponentsBuilder.newInstance()   
  3.             .scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}").build()   
  4.             .expand("42""21")   
  5.             .encode();   
  6.   
  7. URI uri = uriComponents.toUri();  
UriComponents uriComponents = 
        UriComponentsBuilder.newInstance()
            .scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}").build()
            .expand("42", "21")
            .encode();

URI uri = uriComponents.toUri();

 

 20.9.1.2 处理request和response的头信息(headers)

除了前面已经说到的方法外,RestTemplate还有一个exchange()方法,该方法可以用在基于HttpEntity类的任意HTTP方法的执行上。

也许最重要的一点是,exchange()方法可以用来添加request头信息(headers)以及读response的头信息(headers)。举例:

Java代码 复制代码 收藏代码
  1. HttpHeaders requestHeaders = new HttpHeaders();   
  2. requestHeaders.set("MyRequestHeader""MyValue");   
  3. HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);   
  4.   
  5. HttpEntity<String> response = template.exchange("http://example.com/hotels/{hotel}",   
  6.   HttpMethod.GET, requestEntity, String.class"42");   
  7.   
  8. String responseHeader = response.getHeaders().getFirst("MyResponseHeader");   
  9. String body = response.getBody();  
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("MyRequestHeader", "MyValue");
HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);

HttpEntity<String> response = template.exchange("http://example.com/hotels/{hotel}",
  HttpMethod.GET, requestEntity, String.class, "42");

String responseHeader = response.getHeaders().getFirst("MyResponseHeader");
String body = response.getBody();

在上面这个例子中,我们首先准备了一个request实体(entity),该实体包含了MyRequestHeader头信息(header)。然后我们取回(retrieve)response,读到这个MyResponseHeader和返回体(body)。

20.9.2 HTTP Message Conversion (本小节跟本文关系不大,略去 译者)

分享到:
评论

相关推荐

    spring mvc集成webservice

    Spring MVC 是一个强大的Java Web开发框架,用于构建可维护、高性能的Web应用程序。而Web服务是一种基于开放标准的,使得不同系统之间能够相互通信的技术。在本示例中,我们将探讨如何将Spring MVC与Web服务(特别是...

    Spring MVC 文件上传下载 后端 - Java.zip

    在Java Web开发中,Spring MVC框架是一个非常流行的用于构建企业级应用的模型-视图-控制器(MVC)架构。这个压缩包“Spring MVC 文件上传下载 后端 - Java.zip”很可能包含了关于如何在Spring MVC中实现文件上传和...

    spring-webmvc-portlet.rar

    本篇将详细解析如何将这两个框架整合,以实现更高效、更灵活的Web应用开发。 一、Spring Web MVC框架 Spring Web MVC是一个基于模型-视图-控制器(MVC)设计模式的Web应用框架,它提供了一种松散耦合的编程模型,...

    Spring Web MVC入门教程

    Spring Web MVC是一种基于MVC模式的轻量级Java Web应用框架,它是Spring框架的一部分,主要用于简化Web层的开发。Spring Web MVC允许开发者将应用程序分为三个主要组件:模型(Model)、视图(View)和控制器(Controller...

    Spring mvc 教程

    Spring Web MVC 是 Spring Framework 的一个重要组成部分,主要用于构建基于 Java 的 Web 应用程序。它提供了一个灵活且强大的 MVC 实现,使得开发者能够轻松地开发出复杂的 Web 应用。 #### Spring Web MVC 的新...

    最全的Spring MVC注解例子,异步请求,错误处理

    Spring MVC 是一个强大的Java Web开发框架,用于构建高效、可维护和模块化的Web应用程序。它在Spring框架的基础上,提供了一种优雅的方式来处理HTTP请求和响应。在这个“最全的Spring MVC注解例子”中,我们将深入...

    计算机外文翻译-Spring的web-MVC-构架模式.pdf

    【Spring的Web MVC构架模式】是Spring框架中的核心组件,用于构建Web应用程序。Spring MVC设计的核心是一个称为DispatcherServlet的前端控制器,它负责接收HTTP请求并分发到相应的处理器。这种架构模式允许开发者将...

    Spring MVC 入门实例

    基于 Spring 的 Web 应用程序接收到 http://localhost:8080/hello.do(事实上请求路径是 /hello.do) 的请求后, Spring 将这个请求交给一个名为 helloController 的程序进行处理, helloController 再调用 一个名为 ...

    spring_MVC源码

    14. &lt;bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /&gt; 15. 16. &lt;!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 --&gt; 17. &lt;bean class="org....

    计算机外文翻译-Spring的web-MVC-构架模式 (2).pdf

    【Spring的Web MVC构架模式】是Spring框架的重要组成部分,主要负责处理Web应用程序中的用户请求。Spring MVC的设计理念是提供一种灵活且可扩展的架构,让开发者能够更好地分离业务逻辑和表示层,从而提高代码的可...

    外文翻译-Spring的web-MVC-构架模式 (2).docx

    Spring框架的Web-MVC模块是其核心特性之一,旨在简化构建基于Java的Web应用程序的过程。该架构模式与其他轻量级应用框架,如Struts和Webwork,有着显著的区别。Spring不仅仅是一个Web框架,而是一个全方位的应用框架...

    基于注解的 Spring MVC 简单入门

    总结来说,基于注解的Spring MVC简化了Web应用的开发,通过注解可以实现控制器、请求映射、参数绑定等功能。`web.xml`和`dispatcher-servlet.xml`配置文件是设置Spring MVC的基础,而`@Controller`、`@...

    Servlet JSP Spring MVC初学指南(alin书签).pdf

    Servlet、JSP和Spring MVC是Java Web开发中的三个重要技术,它们在构建动态网页和企业级应用程序中扮演着核心角色。下面将详细解释这三个技术及其相互关系。 **Servlet** 是Java编程语言中的一种接口,由Java ...

    基于注解的spring mvc

    基于注解的Spring MVC是一种流行的Java Web开发框架,它极大地简化了控制器的配置和处理请求的方式。本节将深入探讨Spring MVC的注解驱动机制、基础配置以及控制器的返回值分析。 首先,让我们来看看Spring MVC的...

    spring_mvc_response

    Spring MVC 是一个基于 Java 的轻量级 Web 开发框架,它是 Spring 框架的一部分,专门用于构建 MVC(Model-View-Controller)架构的 Web 应用程序。本压缩包文件"spring_mvc_response"可能包含了一系列关于 Spring ...

    Spring MVC--6.RESTful SpringMVC CRUD

    Spring MVC是Spring框架的一部分,它为构建基于Java的Web应用程序提供了强大的模型-视图-控制器(MVC)架构。RESTful SpringMVC CRUD是指使用RESTful原则设计Spring MVC应用程序,以执行创建(Create)、读取(Retrieve...

    使用 Spring 2_5 基于注解驱动的 Spring MVC

    在本主题中,我们将深入探讨Spring框架的2.5版本引入的一个重要特性——基于注解的Spring MVC配置。Spring MVC是Spring框架的一部分,专门用于构建Web应用程序,它提供了一个模型-视图-控制器(MVC)架构来组织和...

    Spring_MVC详解学习

    配置Spring MVC框架是确保Web应用程序能够高效运行的关键步骤,尤其是在管理基于Spring的Web应用程序的多个实例时。本文将详细介绍Spring MVC框架的配置技巧,帮助开发者掌握如何便捷地管理和配置Web应用程序。 ...

    spring mvc异常处理

    Spring MVC 是一个强大的Java Web开发框架,用于构建可维护、高性能的Web应用程序。在实际的开发过程中,我们经常需要处理各种可能出现的异常情况。本文将深入探讨Spring MVC中的异常处理机制,帮助你更好地理解如何...

Global site tag (gtag.js) - Google Analytics