Created
May 14, 2014 18:22
-
-
Save philwebb/64260a6cc3bc813a3f57 to your computer and use it in GitHub Desktop.
ResponseEntity with builder methods
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2002-2012 the original author or authors. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package sample2; | |
import java.net.URI; | |
import java.util.Arrays; | |
import java.util.LinkedHashSet; | |
import java.util.Set; | |
import org.springframework.http.HttpEntity; | |
import org.springframework.http.HttpHeaders; | |
import org.springframework.http.HttpMethod; | |
import org.springframework.http.HttpStatus; | |
import org.springframework.http.MediaType; | |
import org.springframework.util.MultiValueMap; | |
import org.springframework.util.ObjectUtils; | |
/** | |
* Extension of {@link HttpEntity} that adds a {@link HttpStatus} status code. | |
* | |
* <p>Returned by {@link org.springframework.web.client.RestTemplate#getForEntity}: | |
* <pre class="code"> | |
* ResponseEntity<String> entity = template.getForEntity("http://example.com", String.class); | |
* String body = entity.getBody(); | |
* MediaType contentType = entity.getHeaders().getContentType(); | |
* HttpStatus statusCode = entity.getStatusCode(); | |
* </pre> | |
* <p>Can also be used in Spring MVC, as a return value from a @Controller method: | |
* <pre class="code"> | |
* @RequestMapping("/handle") | |
* public ResponseEntity<String> handle() { | |
* HttpHeaders responseHeaders = new HttpHeaders(); | |
* responseHeaders.set("MyResponseHeader", "MyValue"); | |
* return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED); | |
* } | |
* </pre> | |
* | |
* @author Arjen Poutsma | |
* @since 3.0.2 | |
* @see #getStatusCode() | |
*/ | |
public class ResponseEntity<T> extends HttpEntity<T> { | |
private final HttpStatus statusCode; | |
/** | |
* Create a new {@code ResponseEntity} with the given status code, and no body nor headers. | |
* @param statusCode the status code | |
*/ | |
public ResponseEntity(HttpStatus statusCode) { | |
super(); | |
this.statusCode = statusCode; | |
} | |
/** | |
* Create a new {@code ResponseEntity} with the given body and status code, and no headers. | |
* @param body the entity body | |
* @param statusCode the status code | |
*/ | |
public ResponseEntity(T body, HttpStatus statusCode) { | |
super(body); | |
this.statusCode = statusCode; | |
} | |
/** | |
* Create a new {@code HttpEntity} with the given headers and status code, and no body. | |
* @param headers the entity headers | |
* @param statusCode the status code | |
*/ | |
public ResponseEntity(MultiValueMap<String, String> headers, HttpStatus statusCode) { | |
super(headers); | |
this.statusCode = statusCode; | |
} | |
/** | |
* Create a new {@code HttpEntity} with the given body, headers, and status code. | |
* @param body the entity body | |
* @param headers the entity headers | |
* @param statusCode the status code | |
*/ | |
public ResponseEntity(T body, MultiValueMap<String, String> headers, HttpStatus statusCode) { | |
super(body, headers); | |
this.statusCode = statusCode; | |
} | |
/** | |
* Return the HTTP status code of the response. | |
* @return the HTTP status as an HttpStatus enum value | |
*/ | |
public HttpStatus getStatusCode() { | |
return this.statusCode; | |
} | |
@Override | |
public boolean equals(Object other) { | |
if (this == other) { | |
return true; | |
} | |
if (!(other instanceof ResponseEntity)) { | |
return false; | |
} | |
ResponseEntity<?> otherEntity = (ResponseEntity<?>) other; | |
return (ObjectUtils.nullSafeEquals(this.statusCode, otherEntity.statusCode) && super.equals(other)); | |
} | |
@Override | |
public int hashCode() { | |
return super.hashCode() * 29 + ObjectUtils.nullSafeHashCode(this.statusCode); | |
} | |
@Override | |
public String toString() { | |
StringBuilder builder = new StringBuilder("<"); | |
builder.append(this.statusCode.toString()); | |
builder.append(' '); | |
builder.append(this.statusCode.getReasonPhrase()); | |
builder.append(','); | |
T body = getBody(); | |
HttpHeaders headers = getHeaders(); | |
if (body != null) { | |
builder.append(body); | |
if (headers != null) { | |
builder.append(','); | |
} | |
} | |
if (headers != null) { | |
builder.append(headers); | |
} | |
builder.append('>'); | |
return builder.toString(); | |
} | |
public static <T> Builder<T> ok() { | |
return new Builder<T>(null, null, HttpStatus.OK); | |
} | |
public static <T> Builder<T> ok(T body) { | |
return new Builder<T>(body, null, HttpStatus.OK); | |
} | |
public static <T> Builder<T> created(URI location) { | |
return new Builder<T>(null, null, HttpStatus.CREATED).location(location); | |
} | |
public static <T> Builder<T> created(URI location, T body) { | |
return new Builder<T>(body, null, HttpStatus.CREATED).location(location); | |
} | |
public static <T> Builder<T> accepted() { | |
return new Builder<T>(null, null, HttpStatus.ACCEPTED); | |
} | |
public static <T> Builder<T> accepted(T body) { | |
return new Builder<T>(body, null, HttpStatus.ACCEPTED); | |
} | |
public static <T> HeadersBuilder<T> noContent() { | |
return new HeadersBuilder<T>(null, null, HttpStatus.NO_CONTENT); | |
} | |
public static <T> Builder<T> status(HttpStatus status) { | |
return new Builder<T>(null, null, status); | |
} | |
public static <T> Builder<T> status(HttpStatus status, T body) { | |
return new Builder<T>(body, null, status); | |
} | |
/** | |
* Abstract base class for {@link Builder} and {@link HeadersBuilder}. | |
*/ | |
public static abstract class AbstractBuilder<T, B extends AbstractBuilder<T, B>> extends ResponseEntity<T> { | |
public AbstractBuilder(T body, MultiValueMap<String, String> headers, HttpStatus statusCode) { | |
super(body, (headers == null ? new HttpHeaders() : headers), statusCode); | |
} | |
/** | |
* Add the given, single header value under the given name. | |
* @param headerName the header name | |
* @param headerValues the header value(s) | |
* @return a new builder | |
* @see HttpHeaders#add(String, String) | |
*/ | |
public B header(String headerName, String... headerValues) { | |
HttpHeaders newHeaders = newHeaders(); | |
for (String headerValue : headerValues) { | |
newHeaders.add(headerName, headerValue); | |
} | |
return newBuilder(newHeaders); | |
} | |
/** | |
* Set the set of allowed {@link HttpMethod HTTP methods}, as specified by the | |
* {@code Allow} header. | |
* @param allowedMethods the allowed methods | |
* @return a new builder | |
* @see HttpHeaders#setAllow(Set) | |
*/ | |
public B allow(HttpMethod... allowedMethods) { | |
HttpHeaders newHeaders = newHeaders(); | |
newHeaders.setAllow(new LinkedHashSet<HttpMethod>(Arrays.asList(allowedMethods))); | |
return newBuilder(newHeaders); | |
} | |
/** | |
* Sets the entity tag of the body, as specified by the {@code ETag} header. | |
* @param eTag the new entity tag | |
* @return a new builder | |
* @see HttpHeaders#setETag(String) | |
*/ | |
public B eTag(String eTag) { | |
HttpHeaders newHeaders = newHeaders(); | |
newHeaders.setETag(eTag); | |
return newBuilder(newHeaders); | |
} | |
/** | |
* Sets the time the resource was last changed, as specified by the {@code | |
* Last-Modified} header. <p>The date should be specified as the number of | |
* milliseconds since January 1, 1970 GMT. | |
* @param lastModified the last modified date | |
* @return a new builder | |
* @see HttpHeaders#setLastModified(long) | |
*/ | |
public B lastModified(long lastModified) { | |
HttpHeaders newHeaders = newHeaders(); | |
newHeaders.setLastModified(lastModified); | |
return newBuilder(newHeaders); | |
} | |
/** | |
* Set the location of a resource, as specified by the {@code Location} header. | |
* @param location the location | |
* @return a new builder | |
* @see HttpHeaders#setLocation(URI) | |
*/ | |
public B location(URI location) { | |
HttpHeaders newHeaders = newHeaders(); | |
newHeaders.setLocation(location); | |
return newBuilder(newHeaders); | |
} | |
protected final HttpHeaders newHeaders() { | |
HttpHeaders headers = new HttpHeaders(); | |
headers.putAll(getHeaders()); | |
return headers; | |
} | |
protected abstract B newBuilder(HttpHeaders newHeaders); | |
} | |
/** | |
* Builder that can be used to create {@link ResponseEntity} instances that do not | |
* contain a body. | |
*/ | |
public static class HeadersBuilder<T> extends AbstractBuilder<T, HeadersBuilder<T>> { | |
public HeadersBuilder(T body, MultiValueMap<String, String> headers, HttpStatus statusCode) { | |
super(body, headers, statusCode); | |
} | |
@Override | |
protected HeadersBuilder<T> newBuilder(HttpHeaders newHeaders) { | |
return new HeadersBuilder<T>(getBody(), newHeaders, getStatusCode()); | |
} | |
} | |
/** | |
* Builder that can be used to create {@link ResponseEntity} instances that do | |
* contain a body. | |
*/ | |
public static class Builder<T> extends AbstractBuilder<T, Builder<T>> { | |
public Builder(T body, MultiValueMap<String, String> headers, HttpStatus statusCode) { | |
super(body, headers, statusCode); | |
} | |
@Override | |
protected Builder<T> newBuilder(HttpHeaders newHeaders) { | |
return new Builder<T>(getBody(), newHeaders, getStatusCode()); | |
} | |
/** | |
* Set the length of the body in bytes, as specified by the {@code Content-Length} | |
* header. | |
* @param contentLength the content length | |
* @return a new builder | |
* @see HttpHeaders#setContentLength(long) | |
*/ | |
public Builder<T> contentLength(long contentLength) { | |
HttpHeaders newHeaders = newHeaders(); | |
newHeaders.setContentLength(contentLength); | |
return newBuilder(newHeaders); | |
} | |
/** | |
* Set the {@linkplain MediaType media type} of the body, as specified by the | |
* {@code Content-Type} header. | |
* @param mediaType the content media type | |
* @return a new builder | |
* @see HttpHeaders#setContentType(MediaType) | |
*/ | |
public Builder<T> contentType(MediaType mediaType) { | |
HttpHeaders newHeaders = newHeaders(); | |
newHeaders.setContentType(mediaType); | |
return newBuilder(newHeaders); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sample2; | |
import org.springframework.http.MediaType; | |
public class ResponseEntityUsage { | |
public ResponseEntity<Void> a() { | |
return ResponseEntity.ok(); | |
} | |
public ResponseEntity<?> a2() { | |
return ResponseEntity.ok(); | |
} | |
public ResponseEntity<String> b() { | |
return ResponseEntity.ok("test"); | |
} | |
public ResponseEntity<String> c() { | |
String body = ""; | |
return ResponseEntity.ok(body).contentType(MediaType.APPLICATION_JSON); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment