spring DefaultServerRequest 源码
spring DefaultServerRequest 代码
文件路径:/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java
/*
* Copyright 2002-2022 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
*
* https://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 org.springframework.web.servlet.function;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.InetSocketAddress;
import java.net.URI;
import java.nio.charset.Charset;
import java.security.Principal;
import java.time.Instant;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.Set;
import java.util.stream.Collectors;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.Part;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRange;
import org.springframework.http.MediaType;
import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import org.springframework.web.util.ServletRequestPathUtils;
import org.springframework.web.util.UriBuilder;
/**
* {@code ServerRequest} implementation based on a {@link HttpServletRequest}.
*
* @author Arjen Poutsma
* @author Sam Brannen
* @since 5.2
*/
class DefaultServerRequest implements ServerRequest {
private final ServletServerHttpRequest serverHttpRequest;
private final RequestPath requestPath;
private final Headers headers;
private final List<HttpMessageConverter<?>> messageConverters;
private final MultiValueMap<String, String> params;
private final Map<String, Object> attributes;
@Nullable
private MultiValueMap<String, Part> parts;
public DefaultServerRequest(HttpServletRequest servletRequest, List<HttpMessageConverter<?>> messageConverters) {
this.serverHttpRequest = new ServletServerHttpRequest(servletRequest);
this.messageConverters = Collections.unmodifiableList(new ArrayList<>(messageConverters));
this.headers = new DefaultRequestHeaders(this.serverHttpRequest.getHeaders());
this.params = CollectionUtils.toMultiValueMap(new ServletParametersMap(servletRequest));
this.attributes = new ServletAttributesMap(servletRequest);
// DispatcherServlet parses the path but for other scenarios (e.g. tests) we might need to
this.requestPath = (ServletRequestPathUtils.hasParsedRequestPath(servletRequest) ?
ServletRequestPathUtils.getParsedRequestPath(servletRequest) :
ServletRequestPathUtils.parseAndCache(servletRequest));
}
@Override
public HttpMethod method() {
return HttpMethod.valueOf(servletRequest().getMethod());
}
@Override
@Deprecated
public String methodName() {
return servletRequest().getMethod();
}
@Override
public URI uri() {
return this.serverHttpRequest.getURI();
}
@Override
public UriBuilder uriBuilder() {
return ServletUriComponentsBuilder.fromRequest(servletRequest());
}
@Override
public RequestPath requestPath() {
return this.requestPath;
}
@Override
public Headers headers() {
return this.headers;
}
@Override
public MultiValueMap<String, Cookie> cookies() {
Cookie[] cookies = servletRequest().getCookies();
if (cookies == null) {
cookies = new Cookie[0];
}
MultiValueMap<String, Cookie> result = new LinkedMultiValueMap<>(cookies.length);
for (Cookie cookie : cookies) {
result.add(cookie.getName(), cookie);
}
return result;
}
@Override
public HttpServletRequest servletRequest() {
return this.serverHttpRequest.getServletRequest();
}
@Override
public Optional<InetSocketAddress> remoteAddress() {
return Optional.of(this.serverHttpRequest.getRemoteAddress());
}
@Override
public List<HttpMessageConverter<?>> messageConverters() {
return this.messageConverters;
}
@Override
public <T> T body(Class<T> bodyType) throws IOException, ServletException {
return bodyInternal(bodyType, bodyType);
}
@Override
public <T> T body(ParameterizedTypeReference<T> bodyType) throws IOException, ServletException {
Type type = bodyType.getType();
return bodyInternal(type, bodyClass(type));
}
static Class<?> bodyClass(Type type) {
if (type instanceof Class<?> clazz) {
return clazz;
}
if (type instanceof ParameterizedType parameterizedType &&
parameterizedType.getRawType() instanceof Class<?> rawType) {
return rawType;
}
return Object.class;
}
@SuppressWarnings("unchecked")
private <T> T bodyInternal(Type bodyType, Class<?> bodyClass) throws ServletException, IOException {
MediaType contentType = this.headers.contentType().orElse(MediaType.APPLICATION_OCTET_STREAM);
for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
if (messageConverter instanceof GenericHttpMessageConverter<?> genericMessageConverter) {
if (genericMessageConverter.canRead(bodyType, bodyClass, contentType)) {
return (T) genericMessageConverter.read(bodyType, bodyClass, this.serverHttpRequest);
}
}
if (messageConverter.canRead(bodyClass, contentType)) {
HttpMessageConverter<T> theConverter =
(HttpMessageConverter<T>) messageConverter;
Class<? extends T> clazz = (Class<? extends T>) bodyClass;
return theConverter.read(clazz, this.serverHttpRequest);
}
}
throw new HttpMediaTypeNotSupportedException(contentType, getSupportedMediaTypes(bodyClass), method());
}
private List<MediaType> getSupportedMediaTypes(Class<?> bodyClass) {
List<MediaType> result = new ArrayList<>(this.messageConverters.size());
for (HttpMessageConverter<?> converter : this.messageConverters) {
result.addAll(converter.getSupportedMediaTypes(bodyClass));
}
MimeTypeUtils.sortBySpecificity(result);
return result;
}
@Override
public Optional<Object> attribute(String name) {
return Optional.ofNullable(servletRequest().getAttribute(name));
}
@Override
public Map<String, Object> attributes() {
return this.attributes;
}
@Override
public Optional<String> param(String name) {
return Optional.ofNullable(servletRequest().getParameter(name));
}
@Override
public MultiValueMap<String, String> params() {
return this.params;
}
@Override
public MultiValueMap<String, Part> multipartData() throws IOException, ServletException {
MultiValueMap<String, Part> result = this.parts;
if (result == null) {
result = servletRequest().getParts().stream()
.collect(Collectors.groupingBy(Part::getName,
LinkedMultiValueMap::new,
Collectors.toList()));
this.parts = result;
}
return result;
}
@Override
@SuppressWarnings("unchecked")
public Map<String, String> pathVariables() {
Map<String, String> pathVariables = (Map<String, String>)
servletRequest().getAttribute(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
if (pathVariables != null) {
return pathVariables;
}
else {
return Collections.emptyMap();
}
}
@Override
public HttpSession session() {
return servletRequest().getSession(true);
}
@Override
public Optional<Principal> principal() {
return Optional.ofNullable(this.serverHttpRequest.getPrincipal());
}
@Override
public String toString() {
return String.format("HTTP %s %s", method(), path());
}
static Optional<ServerResponse> checkNotModified(
HttpServletRequest servletRequest, @Nullable Instant lastModified, @Nullable String etag) {
long lastModifiedTimestamp = -1;
if (lastModified != null && lastModified.isAfter(Instant.EPOCH)) {
lastModifiedTimestamp = lastModified.toEpochMilli();
}
CheckNotModifiedResponse response = new CheckNotModifiedResponse();
WebRequest webRequest = new ServletWebRequest(servletRequest, response);
if (webRequest.checkNotModified(etag, lastModifiedTimestamp)) {
return Optional.of(ServerResponse.status(response.status).
headers(headers -> headers.addAll(response.headers))
.build());
}
else {
return Optional.empty();
}
}
/**
* Default implementation of {@link Headers}.
*/
static class DefaultRequestHeaders implements Headers {
private final HttpHeaders httpHeaders;
public DefaultRequestHeaders(HttpHeaders httpHeaders) {
this.httpHeaders = HttpHeaders.readOnlyHttpHeaders(httpHeaders);
}
@Override
public List<MediaType> accept() {
return this.httpHeaders.getAccept();
}
@Override
public List<Charset> acceptCharset() {
return this.httpHeaders.getAcceptCharset();
}
@Override
public List<Locale.LanguageRange> acceptLanguage() {
return this.httpHeaders.getAcceptLanguage();
}
@Override
public OptionalLong contentLength() {
long value = this.httpHeaders.getContentLength();
return (value != -1 ? OptionalLong.of(value) : OptionalLong.empty());
}
@Override
public Optional<MediaType> contentType() {
return Optional.ofNullable(this.httpHeaders.getContentType());
}
@Override
public InetSocketAddress host() {
return this.httpHeaders.getHost();
}
@Override
public List<HttpRange> range() {
return this.httpHeaders.getRange();
}
@Override
public List<String> header(String headerName) {
List<String> headerValues = this.httpHeaders.get(headerName);
return (headerValues != null ? headerValues : Collections.emptyList());
}
@Override
public HttpHeaders asHttpHeaders() {
return this.httpHeaders;
}
@Override
public String toString() {
return this.httpHeaders.toString();
}
}
private static final class ServletParametersMap extends AbstractMap<String, List<String>> {
private final HttpServletRequest servletRequest;
private ServletParametersMap(HttpServletRequest servletRequest) {
this.servletRequest = servletRequest;
}
@Override
public Set<Entry<String, List<String>>> entrySet() {
return this.servletRequest.getParameterMap().entrySet().stream()
.map(entry -> {
List<String> value = Arrays.asList(entry.getValue());
return new SimpleImmutableEntry<>(entry.getKey(), value);
})
.collect(Collectors.toSet());
}
@Override
public int size() {
return this.servletRequest.getParameterMap().size();
}
@Override
public List<String> get(Object key) {
String name = (String) key;
String[] parameterValues = this.servletRequest.getParameterValues(name);
if (!ObjectUtils.isEmpty(parameterValues)) {
return Arrays.asList(parameterValues);
}
else {
return Collections.emptyList();
}
}
@Override
public List<String> put(String key, List<String> value) {
throw new UnsupportedOperationException();
}
@Override
public List<String> remove(Object key) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
}
private static final class ServletAttributesMap extends AbstractMap<String, Object> {
private final HttpServletRequest servletRequest;
private ServletAttributesMap(HttpServletRequest servletRequest) {
this.servletRequest = servletRequest;
}
@Override
public boolean containsKey(Object key) {
String name = (String) key;
return this.servletRequest.getAttribute(name) != null;
}
@Override
public void clear() {
List<String> attributeNames = Collections.list(this.servletRequest.getAttributeNames());
attributeNames.forEach(this.servletRequest::removeAttribute);
}
@Override
public Set<Entry<String, Object>> entrySet() {
return Collections.list(this.servletRequest.getAttributeNames()).stream()
.map(name -> {
Object value = this.servletRequest.getAttribute(name);
return new SimpleImmutableEntry<>(name, value);
})
.collect(Collectors.toSet());
}
@Override
public Object get(Object key) {
String name = (String) key;
return this.servletRequest.getAttribute(name);
}
@Override
public Object put(String key, Object value) {
Object oldValue = this.servletRequest.getAttribute(key);
this.servletRequest.setAttribute(key, value);
return oldValue;
}
@Override
public Object remove(Object key) {
String name = (String) key;
Object value = this.servletRequest.getAttribute(name);
this.servletRequest.removeAttribute(name);
return value;
}
}
/**
* Simple implementation of {@link HttpServletResponse} used by
* {@link #checkNotModified(HttpServletRequest, Instant, String)} to record status and headers set by
* {@link ServletWebRequest#checkNotModified(String, long)}. Throws an {@code UnsupportedOperationException}
* for other methods.
*/
private static final class CheckNotModifiedResponse implements HttpServletResponse {
private final HttpHeaders headers = new HttpHeaders();
private int status = 200;
@Override
public boolean containsHeader(String name) {
return this.headers.containsKey(name);
}
@Override
public void setDateHeader(String name, long date) {
this.headers.setDate(name, date);
}
@Override
public void setHeader(String name, String value) {
this.headers.set(name, value);
}
@Override
public void addHeader(String name, String value) {
this.headers.add(name, value);
}
@Override
public void setStatus(int sc) {
this.status = sc;
}
@Override
@Deprecated
public void setStatus(int sc, String sm) {
this.status = sc;
}
@Override
public int getStatus() {
return this.status;
}
@Override
@Nullable
public String getHeader(String name) {
return this.headers.getFirst(name);
}
@Override
public Collection<String> getHeaders(String name) {
List<String> result = this.headers.get(name);
return (result != null ? result : Collections.emptyList());
}
@Override
public Collection<String> getHeaderNames() {
return this.headers.keySet();
}
// Unsupported
@Override
public void addCookie(Cookie cookie) {
throw new UnsupportedOperationException();
}
@Override
public String encodeURL(String url) {
throw new UnsupportedOperationException();
}
@Override
public String encodeRedirectURL(String url) {
throw new UnsupportedOperationException();
}
@Override
@Deprecated
public String encodeUrl(String url) {
throw new UnsupportedOperationException();
}
@Override
@Deprecated
public String encodeRedirectUrl(String url) {
throw new UnsupportedOperationException();
}
@Override
public void sendError(int sc, String msg) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void sendError(int sc) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void sendRedirect(String location) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void addDateHeader(String name, long date) {
throw new UnsupportedOperationException();
}
@Override
public void setIntHeader(String name, int value) {
throw new UnsupportedOperationException();
}
@Override
public void addIntHeader(String name, int value) {
throw new UnsupportedOperationException();
}
@Override
public String getCharacterEncoding() {
throw new UnsupportedOperationException();
}
@Override
public String getContentType() {
throw new UnsupportedOperationException();
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public PrintWriter getWriter() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void setCharacterEncoding(String charset) {
throw new UnsupportedOperationException();
}
@Override
public void setContentLength(int len) {
throw new UnsupportedOperationException();
}
@Override
public void setContentLengthLong(long len) {
throw new UnsupportedOperationException();
}
@Override
public void setContentType(String type) {
throw new UnsupportedOperationException();
}
@Override
public void setBufferSize(int size) {
throw new UnsupportedOperationException();
}
@Override
public int getBufferSize() {
throw new UnsupportedOperationException();
}
@Override
public void flushBuffer() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void resetBuffer() {
throw new UnsupportedOperationException();
}
@Override
public boolean isCommitted() {
throw new UnsupportedOperationException();
}
@Override
public void reset() {
throw new UnsupportedOperationException();
}
@Override
public void setLocale(Locale loc) {
throw new UnsupportedOperationException();
}
@Override
public Locale getLocale() {
throw new UnsupportedOperationException();
}
}
}
相关信息
相关文章
spring AbstractServerResponse 源码
spring ChangePathPatternParserVisitor 源码
spring DefaultAsyncServerResponse 源码
spring DefaultEntityResponseBuilder 源码
spring DefaultRenderingResponseBuilder 源码
spring DefaultServerRequestBuilder 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦