DATACMNS-353 - Make Spring HATEOAS purely optional.
Extracted the implementation of UriComponentsContributor from PageableHandlerMethoArgumentResolver and SortHandlerMethodArgumentResolver into dedicated subclasses so that we can really make Spring HATEOAS an optional dependency. The integration tests are now guarded with an assumption to run on Spring 3.2 as Spring 3.1 has issues with JavaConfig and configuration method overrides. We've upgraded to Spring Data Build 1.2 snapshots so that the tests can be run with -Pspring32. This effectively means that the Spring Data Web support can only be used with a current Spring 3.2. Added a note on that in the reference docs and JavaDoc of @EnableSpringDataWebSupport. Original pull request: #39.
This commit is contained in:
committed by
Oliver Gierke
parent
9843447a58
commit
eb4b801dc9
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2013 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 org.springframework.data.web;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.hateoas.mvc.UriComponentsContributor;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Extension of {@link PageableHandlerMethodArgumentResolver} that also supports enhancing URIs using Spring HATEOAS
|
||||
* support.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Oliver Gierke
|
||||
* @author Nick Williams
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class HateoasPageableHandlerMethodArgumentResolver extends PageableHandlerMethodArgumentResolver implements
|
||||
UriComponentsContributor {
|
||||
|
||||
/**
|
||||
* A {@link HateoasPageableHandlerMethodArgumentResolver} preconfigured to the setup of
|
||||
* {@link PageableArgumentResolver}. Use that if you need to stick to the former request parameters an 1-indexed
|
||||
* behavior. This will be removed in the next major version (1.7). So consider migrating to the new way of exposing
|
||||
* request parameters.
|
||||
*/
|
||||
@Deprecated public static final HateoasPageableHandlerMethodArgumentResolver LEGACY;
|
||||
private static final HateoasSortHandlerMethodArgumentResolver DEFAULT_SORT_RESOLVER = new HateoasSortHandlerMethodArgumentResolver();
|
||||
|
||||
static {
|
||||
|
||||
HateoasSortHandlerMethodArgumentResolver LEGACY_SORT = new HateoasSortHandlerMethodArgumentResolver();
|
||||
LEGACY_SORT.setLegacyMode(true);
|
||||
LEGACY_SORT.setSortParameter("page.sort");
|
||||
|
||||
LEGACY = new HateoasPageableHandlerMethodArgumentResolver(LEGACY_SORT);
|
||||
LEGACY.setPageParameterName("page.page");
|
||||
LEGACY.setSizeParameterName("page.size");
|
||||
LEGACY.setFallbackPageable(new PageRequest(1, 10));
|
||||
LEGACY.setOneIndexedParameters(true);
|
||||
}
|
||||
|
||||
private final HateoasSortHandlerMethodArgumentResolver sortResolver;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this resolver with a default {@link HateoasSortHandlerMethodArgumentResolver}.
|
||||
*/
|
||||
public HateoasPageableHandlerMethodArgumentResolver() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link HateoasPageableHandlerMethodArgumentResolver} using the given
|
||||
* {@link HateoasSortHandlerMethodArgumentResolver}..
|
||||
*
|
||||
* @param sortResolver
|
||||
*/
|
||||
public HateoasPageableHandlerMethodArgumentResolver(HateoasSortHandlerMethodArgumentResolver sortResolver) {
|
||||
|
||||
super(getDefaultedSortResolver(sortResolver));
|
||||
this.sortResolver = getDefaultedSortResolver(sortResolver);
|
||||
}
|
||||
|
||||
private static HateoasSortHandlerMethodArgumentResolver getDefaultedSortResolver(
|
||||
HateoasSortHandlerMethodArgumentResolver sortResolver) {
|
||||
return sortResolver == null ? DEFAULT_SORT_RESOLVER : sortResolver;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.mvc.UriComponentsContributor#enhance(org.springframework.web.util.UriComponentsBuilder, org.springframework.core.MethodParameter, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void enhance(UriComponentsBuilder builder, MethodParameter parameter, Object value) {
|
||||
|
||||
if (!(value instanceof Pageable)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Pageable pageable = (Pageable) value;
|
||||
|
||||
String pagePropertyName = getParameterNameToUse(getPageParameterName(), parameter);
|
||||
String sizePropertyName = getParameterNameToUse(getSizeParameterName(), parameter);
|
||||
|
||||
int pageNumber = pageable.getPageNumber();
|
||||
|
||||
builder.replaceQueryParam(pagePropertyName, isOneIndexedParameters() ? pageNumber + 1 : pageNumber);
|
||||
builder.replaceQueryParam(sizePropertyName, pageable.getPageSize() <= getMaxPageSize() ? pageable.getPageSize()
|
||||
: getMaxPageSize());
|
||||
|
||||
this.sortResolver.enhance(builder, parameter, pageable.getSort());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2013 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 org.springframework.data.web;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.hateoas.mvc.UriComponentsContributor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Extension of {@link SortHandlerMethodArgumentResolver} that also supports enhancing URIs using Spring HATEOAS
|
||||
* support.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Nick Williams
|
||||
*/
|
||||
public class HateoasSortHandlerMethodArgumentResolver extends SortHandlerMethodArgumentResolver
|
||||
implements UriComponentsContributor {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.mvc.UriComponentsContributor#enhance(org.springframework.web.util.UriComponentsBuilder, org.springframework.core.MethodParameter, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void enhance(UriComponentsBuilder builder, MethodParameter parameter, Object value) {
|
||||
|
||||
if (!(value instanceof Sort)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Sort sort = (Sort) value;
|
||||
|
||||
if (legacyMode) {
|
||||
|
||||
List<String> expressions = legacyFoldExpressions(sort);
|
||||
Assert.isTrue(expressions.size() == 2,
|
||||
String.format("Expected 2 sort expressions (fields, direction) but got %d!", expressions.size()));
|
||||
builder.queryParam(getSortParameter(parameter), expressions.get(0));
|
||||
builder.queryParam(getLegacyDirectionParameter(parameter), expressions.get(1));
|
||||
|
||||
} else {
|
||||
|
||||
for (String expression : foldIntoExpressions(sort)) {
|
||||
builder.queryParam(getSortParameter(parameter), expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,25 +22,24 @@ import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.hateoas.mvc.UriComponentsContributor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Extracts paging information from web requests and thus allows injecting {@link Pageable} instances into controller
|
||||
* methods. Request properties to be parsed can be configured. Default configuration uses request properties beginning
|
||||
* with {@link #PAGE_PROPERTY}{@link #DEFAULT_SEPARATOR}.
|
||||
* methods. Request properties to be parsed can be configured. Default configuration uses request parameters beginning
|
||||
* with {@link #DEFAULT_PAGE_PARAMETER}{@link #DEFAULT_QUALIFIER_DELIMITER}.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Oliver Gierke
|
||||
* @author Nick Williams
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver, UriComponentsContributor {
|
||||
public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
/**
|
||||
* A {@link PageableHandlerMethodArgumentResolver} preconfigured to the setup of {@link PageableArgumentResolver}. Use
|
||||
@@ -60,21 +59,37 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
|
||||
}
|
||||
|
||||
private static final Pageable DEFAULT_PAGE_REQUEST = new PageRequest(0, 20);
|
||||
private static final String DEFAULT_PAGE_PROPERTY = "page";
|
||||
private static final String DEFAULT_SIZE_PROPERTY = "size";
|
||||
private static final String DEFAULT_PAGE_PARAMETER = "page";
|
||||
private static final String DEFAULT_SIZE_PARAMETER = "size";
|
||||
private static final String DEFAULT_PREFIX = "";
|
||||
private static final String DEFAULT_QUALIFIER_DELIMITER = "_";
|
||||
private static final int DEFAULT_MAX_PAGE_SIZE = 2000;
|
||||
|
||||
private Pageable fallbackPageable = DEFAULT_PAGE_REQUEST;
|
||||
private SortHandlerMethodArgumentResolver sortResolver = new SortHandlerMethodArgumentResolver();
|
||||
private String pageParameterName = DEFAULT_PAGE_PROPERTY;
|
||||
private String sizeParameterName = DEFAULT_SIZE_PROPERTY;
|
||||
private SortHandlerMethodArgumentResolver sortResolver;
|
||||
private String pageParameterName = DEFAULT_PAGE_PARAMETER;
|
||||
private String sizeParameterName = DEFAULT_SIZE_PARAMETER;
|
||||
private String prefix = DEFAULT_PREFIX;
|
||||
private String qualifierDelimiter = DEFAULT_QUALIFIER_DELIMITER;
|
||||
private int maxPageSize = DEFAULT_MAX_PAGE_SIZE;
|
||||
private boolean oneIndexedParameters = false;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this resolved with a default {@link SortHandlerMethodArgumentResolver}.
|
||||
*/
|
||||
public PageableHandlerMethodArgumentResolver() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of this resolver with the specified {@link SortHandlerMethodArgumentResolver}.
|
||||
*
|
||||
* @param sortResolver The sort resolver to use
|
||||
*/
|
||||
public PageableHandlerMethodArgumentResolver(SortHandlerMethodArgumentResolver sortResolver) {
|
||||
this.sortResolver = sortResolver == null ? new SortHandlerMethodArgumentResolver() : sortResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link Pageable} to be used as fallback in case no {@link PageableDefault} or
|
||||
* {@link PageableDefaults} (the latter only supported in legacy mode) can be found at the method parameter to be
|
||||
@@ -99,6 +114,16 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
|
||||
this.maxPageSize = maxPageSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the maximum page size to be accepted. This allows to put an upper boundary of the page size to prevent
|
||||
* potential attacks trying to issue an {@link OutOfMemoryError}. Defaults to {@link #DEFAULT_MAX_PAGE_SIZE}.
|
||||
*
|
||||
* @return the maximum page size allowed.
|
||||
*/
|
||||
protected int getMaxPageSize() {
|
||||
return this.maxPageSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the parameter name to be used to find the page number in the request. Defaults to {@code page}.
|
||||
*
|
||||
@@ -110,6 +135,15 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
|
||||
this.pageParameterName = pageParameterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the parameter name to be used to find the page number in the request. Defaults to {@code page}.
|
||||
*
|
||||
* @return the parameter name to be used, never {@literal null} or empty.
|
||||
*/
|
||||
protected String getPageParameterName() {
|
||||
return this.pageParameterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the parameter name to be used to find the page size in the request. Defaults to {@code size}.
|
||||
*
|
||||
@@ -121,6 +155,15 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
|
||||
this.sizeParameterName = sizeParameterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the parameter name to be used to find the page size in the request. Defaults to {@code size}.
|
||||
*
|
||||
* @return the parameter name to be used, never {@literal null} or empty.
|
||||
*/
|
||||
protected String getSizeParameterName() {
|
||||
return this.sizeParameterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a general prefix to be prepended to the page number and page size parameters. Useful to namespace the
|
||||
* property names used in case they are clashing with ones used by your application. By default, no prefix is used.
|
||||
@@ -141,17 +184,6 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
|
||||
this.qualifierDelimiter = qualifierDelimiter == null ? DEFAULT_QUALIFIER_DELIMITER : qualifierDelimiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link SortHandlerMethodArgumentResolver} to be used with the
|
||||
* {@link PageableHandlerMethodArgumentResolver}.
|
||||
*
|
||||
* @param sortResolver the {@link SortHandlerMethodArgumentResolver} to be used ot {@literal null} to reset it to the
|
||||
* default one.
|
||||
*/
|
||||
public void setSortResolver(SortHandlerMethodArgumentResolver sortResolver) {
|
||||
this.sortResolver = sortResolver == null ? new SortHandlerMethodArgumentResolver() : sortResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures whether to expose and assume 1-based page number indexes in the request parameters. Defaults to
|
||||
* {@literal false}, meaning a page number of 0 in the request equals the first page. If this is set to
|
||||
@@ -163,42 +195,31 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
|
||||
this.oneIndexedParameters = oneIndexedParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether to expose and assume 1-based page number indexes in the request parameters. Defaults to
|
||||
* {@literal false}, meaning a page number of 0 in the request equals the first page. If this is set to
|
||||
* {@literal true}, a page number of 1 in the request will be considered the first page.
|
||||
*
|
||||
* @return whether to assume 1-based page number indexes in the request parameters.
|
||||
*/
|
||||
protected boolean isOneIndexedParameters() {
|
||||
return this.oneIndexedParameters;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.web.method.support.HandlerMethodArgumentResolver#supportsParameter(org.springframework.core.MethodParameter)
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return Pageable.class.equals(parameter.getParameterType());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.mvc.UriComponentsContributor#enhance(org.springframework.web.util.UriComponentsBuilder, org.springframework.core.MethodParameter, java.lang.Object)
|
||||
*/
|
||||
public void enhance(UriComponentsBuilder builder, MethodParameter parameter, Object value) {
|
||||
|
||||
if (!(value instanceof Pageable)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Pageable pageable = (Pageable) value;
|
||||
|
||||
String pagePropertyName = getParameterNameToUse(pageParameterName, parameter);
|
||||
String sizePropertyName = getParameterNameToUse(sizeParameterName, parameter);
|
||||
|
||||
int pageNumber = pageable.getPageNumber();
|
||||
|
||||
builder.replaceQueryParam(pagePropertyName, oneIndexedParameters ? pageNumber + 1 : pageNumber);
|
||||
builder.replaceQueryParam(sizePropertyName, pageable.getPageSize() <= maxPageSize ? pageable.getPageSize()
|
||||
: maxPageSize);
|
||||
|
||||
sortResolver.enhance(builder, parameter, pageable.getSort());
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.web.method.support.HandlerMethodArgumentResolver#resolveArgument(org.springframework.core.MethodParameter, org.springframework.web.method.support.ModelAndViewContainer, org.springframework.web.context.request.NativeWebRequest, org.springframework.web.bind.support.WebDataBinderFactory)
|
||||
*/
|
||||
@Override
|
||||
public Pageable resolveArgument(MethodParameter methodParameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
|
||||
|
||||
@@ -225,9 +246,9 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
|
||||
*
|
||||
* @param source the basic parameter name.
|
||||
* @param parameter the {@link MethodParameter} potentially qualified.
|
||||
* @return
|
||||
* @return the name of the request parameter.
|
||||
*/
|
||||
private String getParameterNameToUse(String source, MethodParameter parameter) {
|
||||
protected String getParameterNameToUse(String source, MethodParameter parameter) {
|
||||
|
||||
StringBuilder builder = new StringBuilder(prefix);
|
||||
|
||||
|
||||
@@ -38,10 +38,11 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Oliver Gierke
|
||||
* @author Nick Williams
|
||||
*/
|
||||
public class PagedResourcesAssembler<T> implements ResourceAssembler<Page<T>, PagedResources<Resource<T>>> {
|
||||
|
||||
private final PageableHandlerMethodArgumentResolver pageableResolver;
|
||||
private final HateoasPageableHandlerMethodArgumentResolver pageableResolver;
|
||||
private final UriComponents baseUri;
|
||||
|
||||
/**
|
||||
@@ -52,9 +53,9 @@ public class PagedResourcesAssembler<T> implements ResourceAssembler<Page<T>, Pa
|
||||
* @param resolver
|
||||
* @param baseUri
|
||||
*/
|
||||
public PagedResourcesAssembler(PageableHandlerMethodArgumentResolver resolver, UriComponents baseUri) {
|
||||
public PagedResourcesAssembler(HateoasPageableHandlerMethodArgumentResolver resolver, UriComponents baseUri) {
|
||||
|
||||
this.pageableResolver = resolver == null ? new PageableHandlerMethodArgumentResolver() : resolver;
|
||||
this.pageableResolver = resolver == null ? new HateoasPageableHandlerMethodArgumentResolver() : resolver;
|
||||
this.baseUri = baseUri;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,10 +32,11 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Oliver Gierke
|
||||
* @author Nick Williams
|
||||
*/
|
||||
public class PagedResourcesAssemblerArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
private final PageableHandlerMethodArgumentResolver resolver;
|
||||
private final HateoasPageableHandlerMethodArgumentResolver resolver;
|
||||
private final MethodLinkBuilderFactory<?> linkBuilderFactory;
|
||||
|
||||
/**
|
||||
@@ -45,7 +46,7 @@ public class PagedResourcesAssemblerArgumentResolver implements HandlerMethodArg
|
||||
* @param resolver can be {@literal null}.
|
||||
* @param linkBuilderFactory can be {@literal null}, will be defaulted to a {@link ControllerLinkBuilderFactory}.
|
||||
*/
|
||||
public PagedResourcesAssemblerArgumentResolver(PageableHandlerMethodArgumentResolver resolver,
|
||||
public PagedResourcesAssemblerArgumentResolver(HateoasPageableHandlerMethodArgumentResolver resolver,
|
||||
MethodLinkBuilderFactory<?> linkBuilderFactory) {
|
||||
|
||||
this.resolver = resolver;
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
import org.springframework.data.web.SortDefault.SortDefaults;
|
||||
import org.springframework.hateoas.mvc.UriComponentsContributor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
@@ -33,7 +32,6 @@ import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* {@link HandlerMethodArgumentResolver} to automatically create {@link Sort} instances from request parameters or
|
||||
@@ -42,8 +40,9 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
* @since 1.6
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Nick Williams
|
||||
*/
|
||||
public class SortHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver, UriComponentsContributor {
|
||||
public class SortHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
private static final String DEFAULT_PARAMETER = "sort";
|
||||
private static final String DEFAULT_PROPERTY_DELIMITER = ",";
|
||||
@@ -76,10 +75,10 @@ public class SortHandlerMethodArgumentResolver implements HandlerMethodArgumentR
|
||||
*
|
||||
* @param sortParameter must not be {@literal null} or empty.
|
||||
*/
|
||||
public void setSortParameter(String parameter) {
|
||||
public void setSortParameter(String sortParameter) {
|
||||
|
||||
Assert.hasText(parameter);
|
||||
this.sortParameter = parameter;
|
||||
Assert.hasText(sortParameter);
|
||||
this.sortParameter = sortParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,42 +107,16 @@ public class SortHandlerMethodArgumentResolver implements HandlerMethodArgumentR
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.web.method.support.HandlerMethodArgumentResolver#supportsParameter(org.springframework.core.MethodParameter)
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return Sort.class.equals(parameter.getParameterType());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.mvc.UriComponentsContributor#enhance(org.springframework.web.util.UriComponentsBuilder, org.springframework.core.MethodParameter, java.lang.Object)
|
||||
*/
|
||||
public void enhance(UriComponentsBuilder builder, MethodParameter parameter, Object value) {
|
||||
|
||||
if (!(value instanceof Sort)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Sort sort = (Sort) value;
|
||||
|
||||
if (legacyMode) {
|
||||
|
||||
List<String> expressions = legacyFoldExpressions(sort);
|
||||
Assert.isTrue(expressions.size() == 2,
|
||||
String.format("Expected 2 sort expressions (fields, direction) but got %d!", expressions.size()));
|
||||
builder.queryParam(getSortParameter(parameter), expressions.get(0));
|
||||
builder.queryParam(getLegacyDirectionParameter(parameter), expressions.get(1));
|
||||
|
||||
} else {
|
||||
|
||||
for (String expression : foldIntoExpressions(sort)) {
|
||||
builder.queryParam(getSortParameter(parameter), expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.web.method.support.HandlerMethodArgumentResolver#resolveArgument(org.springframework.core.MethodParameter, org.springframework.web.method.support.ModelAndViewContainer, org.springframework.web.context.request.NativeWebRequest, org.springframework.web.bind.support.WebDataBinderFactory)
|
||||
*/
|
||||
@Override
|
||||
public Sort resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
|
||||
|
||||
@@ -218,7 +191,7 @@ public class SortHandlerMethodArgumentResolver implements HandlerMethodArgumentR
|
||||
* @param parameter will never be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private String getSortParameter(MethodParameter parameter) {
|
||||
protected String getSortParameter(MethodParameter parameter) {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
@@ -246,7 +219,7 @@ public class SortHandlerMethodArgumentResolver implements HandlerMethodArgumentR
|
||||
return new Sort(Direction.fromStringOrNull(directions), fields.split(","));
|
||||
}
|
||||
|
||||
private String getLegacyDirectionParameter(MethodParameter parameter) {
|
||||
protected String getLegacyDirectionParameter(MethodParameter parameter) {
|
||||
return getSortParameter(parameter) + ".dir";
|
||||
}
|
||||
|
||||
@@ -292,7 +265,7 @@ public class SortHandlerMethodArgumentResolver implements HandlerMethodArgumentR
|
||||
* @param sort must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private List<String> foldIntoExpressions(Sort sort) {
|
||||
protected List<String> foldIntoExpressions(Sort sort) {
|
||||
|
||||
List<String> expressions = new ArrayList<String>();
|
||||
ExpressionBuilder builder = null;
|
||||
@@ -322,7 +295,7 @@ public class SortHandlerMethodArgumentResolver implements HandlerMethodArgumentR
|
||||
* @param sort must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private List<String> legacyFoldExpressions(Sort sort) {
|
||||
protected List<String> legacyFoldExpressions(Sort sort) {
|
||||
|
||||
List<String> expressions = new ArrayList<String>();
|
||||
ExpressionBuilder builder = null;
|
||||
|
||||
@@ -27,6 +27,8 @@ import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.support.DomainClassConverter;
|
||||
import org.springframework.data.web.HateoasPageableHandlerMethodArgumentResolver;
|
||||
import org.springframework.data.web.HateoasSortHandlerMethodArgumentResolver;
|
||||
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
|
||||
import org.springframework.data.web.PagedResourcesAssembler;
|
||||
import org.springframework.data.web.PagedResourcesAssemblerArgumentResolver;
|
||||
@@ -37,7 +39,8 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
|
||||
/**
|
||||
* Annotation to automatically register the following beans for usage with Spring MVC.
|
||||
* Annotation to automatically register the following beans for usage with Spring MVC. Note that using this annotation
|
||||
* will require Spring 3.2.
|
||||
* <ul>
|
||||
* <li>{@link DomainClassConverter} - to allow usage of domain types managed by Spring Data repositories as controller
|
||||
* method arguments bound with {@link PathVariable} or {@link RequestParam}.</li>
|
||||
@@ -46,8 +49,10 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupp
|
||||
* <li>{@link SortHandlerMethodArgumentResolver} - to allow injection of {@link Sort} instances into controller methods
|
||||
* automatically created from request parameters.</li>
|
||||
* </ul>
|
||||
* If Spring HATEOAS is present on the classpath we will additionall register the following beans:
|
||||
* If Spring HATEOAS is present on the classpath we will register the following beans:
|
||||
* <ul>
|
||||
* <li>{@link HateoasPageableHandlerMethodArgumentResolver} - instead of {@link PageableHandlerMethodArgumentResolver}</li>
|
||||
* <li>{@link HateoasSortHandlerMethodArgumentResolver} - instead of {@link SortHandlerMethodArgumentResolver}</li>
|
||||
* <li>{@link PagedResourcesAssembler} - for injection into web components</li>
|
||||
* <li>{@link PagedResourcesAssemblerArgumentResolver} - for injection of {@link PagedResourcesAssembler} into
|
||||
* controller methods</li>
|
||||
|
||||
@@ -19,6 +19,8 @@ import java.util.List;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.web.HateoasPageableHandlerMethodArgumentResolver;
|
||||
import org.springframework.data.web.HateoasSortHandlerMethodArgumentResolver;
|
||||
import org.springframework.data.web.PagedResourcesAssembler;
|
||||
import org.springframework.data.web.PagedResourcesAssemblerArgumentResolver;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
@@ -28,10 +30,31 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Oliver Gierke
|
||||
* @author Nick Williams
|
||||
*/
|
||||
@Configuration
|
||||
public class HateoasAwareSpringDataWebConfiguration extends SpringDataWebConfiguration {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.web.config.SpringDataWebConfiguration#pageableResolver()
|
||||
*/
|
||||
@Bean
|
||||
@Override
|
||||
public HateoasPageableHandlerMethodArgumentResolver pageableResolver() {
|
||||
return new HateoasPageableHandlerMethodArgumentResolver(sortResolver());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.web.config.SpringDataWebConfiguration#sortResolver()
|
||||
*/
|
||||
@Bean
|
||||
@Override
|
||||
public HateoasSortHandlerMethodArgumentResolver sortResolver() {
|
||||
return new HateoasSortHandlerMethodArgumentResolver();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PagedResourcesAssembler<Object> pagedResourcesAssembler() {
|
||||
return new PagedResourcesAssembler<Object>(pageableResolver(), null);
|
||||
|
||||
@@ -41,11 +41,19 @@ public class SpringDataWebConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Autowired private ApplicationContext context;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.web.config.SpringDataWebConfiguration#pageableResolver()
|
||||
*/
|
||||
@Bean
|
||||
public PageableHandlerMethodArgumentResolver pageableResolver() {
|
||||
return new PageableHandlerMethodArgumentResolver();
|
||||
return new PageableHandlerMethodArgumentResolver(sortResolver());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.web.config.SpringDataWebConfiguration#sortResolver()
|
||||
*/
|
||||
@Bean
|
||||
public SortHandlerMethodArgumentResolver sortResolver() {
|
||||
return new SortHandlerMethodArgumentResolver();
|
||||
@@ -79,7 +87,7 @@ public class SpringDataWebConfiguration extends WebMvcConfigurerAdapter {
|
||||
@Override
|
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
|
||||
argumentResolvers.add(pageableResolver());
|
||||
argumentResolvers.add(sortResolver());
|
||||
argumentResolvers.add(pageableResolver());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user