Remove deprecated LastModified APIs

See gh-33809
This commit is contained in:
rstoyanchev
2025-01-16 10:42:04 +00:00
parent 65df3097e0
commit 5f6df35ec4
15 changed files with 14 additions and 307 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2025 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.
@@ -49,21 +49,12 @@ import jakarta.servlet.http.HttpServletResponse;
* return value gives a clearer signature to callers other than the
* DispatcherServlet, indicating that there will never be a view to render.
*
* <p>Note that HttpRequestHandlers may optionally implement the
* {@link org.springframework.web.servlet.mvc.LastModified} interface,
* just like Controllers can, <i>provided that they run within Spring's
* DispatcherServlet</i>. However, this is usually not necessary, since
* HttpRequestHandlers typically only support POST requests to begin with.
* Alternatively, a handler may implement the "If-Modified-Since" HTTP
* header processing manually within its {@code handle} method.
*
* @author Juergen Hoeller
* @since 2.0
* @see org.springframework.web.context.support.HttpRequestHandlerServlet
* @see org.springframework.web.servlet.DispatcherServlet
* @see org.springframework.web.servlet.ModelAndView
* @see org.springframework.web.servlet.mvc.Controller
* @see org.springframework.web.servlet.mvc.LastModified
* @see org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
*/
@FunctionalInterface

View File

@@ -49,14 +49,12 @@ import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.core.log.LogFormatUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
import org.springframework.web.multipart.MultipartException;
@@ -933,7 +931,6 @@ public class DispatcherServlet extends FrameworkServlet {
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
@SuppressWarnings("deprecation")
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
@@ -956,24 +953,12 @@ public class DispatcherServlet extends FrameworkServlet {
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// Determine handler adapter and invoke the handler.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2025 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.
@@ -75,16 +75,4 @@ public interface HandlerAdapter {
*/
@Nullable ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
/**
* Same contract as for HttpServlet's {@code getLastModified} method.
* Can simply return -1 if there's no support in the handler class.
* @param request current HTTP request
* @param handler the handler to use
* @return the lastModified value for the given handler
* @deprecated as of 5.3.9 along with
* {@link org.springframework.web.servlet.mvc.LastModified}.
*/
@Deprecated
long getLastModified(HttpServletRequest request, Object handler);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -171,12 +171,6 @@ public class HandlerFunctionAdapter implements HandlerAdapter, Ordered {
}
}
@Override
@SuppressWarnings("deprecation")
public long getLastModified(HttpServletRequest request, Object handler) {
return -1L;
}
private static class ServerRequestContext implements ServerResponse.Context {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2025 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.
@@ -67,10 +67,4 @@ public class SimpleServletHandlerAdapter implements HandlerAdapter {
return null;
}
@Override
@SuppressWarnings("deprecation")
public long getLastModified(HttpServletRequest request, Object handler) {
return -1;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@@ -27,7 +27,6 @@ import org.springframework.web.servlet.ModelAndView;
/**
* Adapter to use the plain {@link org.springframework.web.HttpRequestHandler}
* interface with the generic {@link org.springframework.web.servlet.DispatcherServlet}.
* Supports handlers that implement the {@link LastModified} interface.
*
* <p>This is an SPI class, not used directly by application code.
*
@@ -52,13 +51,4 @@ public class HttpRequestHandlerAdapter implements HandlerAdapter {
return null;
}
@Override
@SuppressWarnings("deprecation")
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified lastModified) {
return lastModified.getLastModified(request);
}
return -1L;
}
}

View File

@@ -1,65 +0,0 @@
/*
* Copyright 2002-2021 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.mvc;
import jakarta.servlet.http.HttpServletRequest;
/**
* Supports last-modified HTTP requests to facilitate content caching.
* Same contract as for the Servlet API's {@code getLastModified} method.
*
* <p>Delegated to by a {@link org.springframework.web.servlet.HandlerAdapter#getLastModified}
* implementation. By default, any Controller or HttpRequestHandler within Spring's
* default framework can implement this interface to enable last-modified checking.
*
* <p><b>Note:</b> Alternative handler implementation approaches have different
* last-modified handling styles. For example, Spring 2.5's annotated controller
* approach (using {@code @RequestMapping}) provides last-modified support
* through the {@link org.springframework.web.context.request.WebRequest#checkNotModified}
* method, allowing for last-modified checking within the main handler method.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see jakarta.servlet.http.HttpServlet#getLastModified
* @see Controller
* @see SimpleControllerHandlerAdapter
* @see org.springframework.web.HttpRequestHandler
* @see HttpRequestHandlerAdapter
* @deprecated as of 5.3.9 in favor of using the {@code checkNotModified} methods
* in {@link org.springframework.web.context.request.WebRequest}, or from an
* annotated controller method, returning a
* {@link org.springframework.http.ResponseEntity} with an "ETag" and/or
* "Last-Modified" headers set.
*/
@Deprecated
public interface LastModified {
/**
* Same contract as for HttpServlet's {@code getLastModified} method.
* Invoked <b>before</b> request processing.
* <p>The return value will be sent to the HTTP client as Last-Modified header,
* and compared with If-Modified-Since headers that the client sends back.
* The content will only get regenerated if there has been a modification.
* @param request current HTTP request
* @return the time the underlying resource was last modified, or -1
* meaning that the content must always be regenerated
* @see org.springframework.web.servlet.HandlerAdapter#getLastModified
* @see jakarta.servlet.http.HttpServlet#getLastModified
*/
long getLastModified(HttpServletRequest request);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@@ -26,7 +26,6 @@ import org.springframework.web.servlet.ModelAndView;
/**
* Adapter to use the plain {@link Controller} workflow interface with
* the generic {@link org.springframework.web.servlet.DispatcherServlet}.
* Supports handlers that implement the {@link LastModified} interface.
*
* <p>This is an SPI class, not used directly by application code.
*
@@ -50,13 +49,4 @@ public class SimpleControllerHandlerAdapter implements HandlerAdapter {
return ((Controller) handler).handleRequest(request, response);
}
@Override
@SuppressWarnings("deprecation")
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified lastModified) {
return lastModified.getLastModified(request);
}
return -1L;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@@ -99,24 +99,4 @@ public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator i
protected abstract @Nullable ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;
/**
* This implementation expects the handler to be an {@link HandlerMethod}.
*/
@Override
@SuppressWarnings("deprecation")
public final long getLastModified(HttpServletRequest request, Object handler) {
return getLastModifiedInternal(request, (HandlerMethod) handler);
}
/**
* Same contract as for {@link jakarta.servlet.http.HttpServlet#getLastModified(HttpServletRequest)}.
* @param request current HTTP request
* @param handlerMethod handler method to use
* @return the lastModified value for the given handler
* @deprecated as of 5.3.9 along with
* {@link org.springframework.web.servlet.mvc.LastModified}.
*/
@Deprecated
protected abstract long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod);
}

View File

@@ -72,7 +72,6 @@ import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.async.AsyncWebRequest;
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;
@@ -861,17 +860,6 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
return mav;
}
/**
* This implementation always returns -1. An {@code @RequestMapping} method can
* calculate the lastModified value, call {@link WebRequest#checkNotModified(long)},
* and return {@code null} if the result of that call is {@code true}.
*/
@Override
@SuppressWarnings("deprecation")
protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) {
return -1;
}
/**
* Return the {@link SessionAttributesHandler} instance for the given handler type
@@ -889,7 +877,6 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
* @since 4.2
* @see #createInvocableHandlerMethod(HandlerMethod)
*/
@SuppressWarnings("deprecation")
protected @Nullable ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -334,24 +334,6 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
applyCacheControl(response, cControl);
}
/**
* Check and prepare the given request and response according to the settings
* of this generator.
* @see #checkRequest(HttpServletRequest)
* @see #applyCacheSeconds(HttpServletResponse, int)
* @deprecated as of 4.2, since the {@code lastModified} flag is effectively ignored,
* with a must-revalidate header only generated if explicitly configured
*/
@Deprecated
protected final void checkAndPrepare(
HttpServletRequest request, HttpServletResponse response, int cacheSeconds, boolean lastModified)
throws ServletException {
checkRequest(request);
applyCacheSeconds(response, cacheSeconds);
}
private Collection<String> getVaryRequestHeadersToAdd(HttpServletResponse response, String[] varyByRequestHeaders) {
if (!response.containsHeader(HttpHeaders.VARY)) {
return Arrays.asList(varyByRequestHeaders);

View File

@@ -261,12 +261,6 @@ public class ComplexWebApplicationContext extends StaticWebApplicationContext {
((MyHandler) delegate).doSomething(request);
return null;
}
@Deprecated
@Override
public long getLastModified(HttpServletRequest request, Object delegate) {
return ((MyHandler) delegate).lastModified();
}
}
@@ -282,12 +276,6 @@ public class ComplexWebApplicationContext extends StaticWebApplicationContext {
throws IOException, ServletException {
throw new ServletException("dummy");
}
@Deprecated
@Override
public long getLastModified(HttpServletRequest request, Object delegate) {
return -1;
}
}

View File

@@ -40,6 +40,7 @@ import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.RequestPath;
import org.springframework.web.HttpRequestHandler;
@@ -72,6 +73,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -196,7 +198,6 @@ class DispatcherServletTests {
MockHttpServletResponse response = new MockHttpServletResponse();
simpleDispatcherServlet.service(request, response);
assertThat(response.getForwardedUrl()).as("Not forwarded").isNull();
assertThat(response.getHeader("Last-Modified")).isEqualTo("Wed, 01 Apr 2015 00:00:00 GMT");
}
@Test
@@ -226,7 +227,6 @@ class DispatcherServletTests {
assertThat(request.getAttribute("test3")).isNotNull();
assertThat(request.getAttribute("test3x")).isNotNull();
assertThat(request.getAttribute("test3y")).isNotNull();
assertThat(response.getHeader("Last-Modified")).isEqualTo("Wed, 01 Apr 2015 00:00:01 GMT");
}
@Test
@@ -789,8 +789,7 @@ class DispatcherServletTests {
ConfigurableEnvironment env1 = new StandardServletEnvironment();
servlet.setEnvironment(env1); // should succeed
assertThat(servlet.getEnvironment()).isSameAs(env1);
assertThatIllegalArgumentException().as("non-configurable Environment").isThrownBy(() ->
servlet.setEnvironment(new DummyEnvironment()));
assertThatIllegalArgumentException().isThrownBy(() -> servlet.setEnvironment(mock(Environment.class)));
class CustomServletEnvironment extends StandardServletEnvironment { }
DispatcherServlet custom = new DispatcherServlet() {
@Override

View File

@@ -1,90 +0,0 @@
/*
* Copyright 2002-2019 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;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
class DummyEnvironment implements Environment {
@Override
public boolean containsProperty(String key) {
return false;
}
@Override
public String getProperty(String key) {
return null;
}
@Override
public String getProperty(String key, String defaultValue) {
return null;
}
@Override
public <T> T getProperty(String key, Class<T> targetType) {
return null;
}
@Override
public <T> T getProperty(String key, Class<T> targetType, T defaultValue) {
return null;
}
@Override
public String getRequiredProperty(String key) throws IllegalStateException {
return null;
}
@Override
public <T> T getRequiredProperty(String key, Class<T> targetType) throws IllegalStateException {
return null;
}
@Override
public String resolvePlaceholders(String text) {
return null;
}
@Override
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
return null;
}
@Override
public String[] getActiveProfiles() {
return null;
}
@Override
public String[] getDefaultProfiles() {
return null;
}
@Deprecated
@Override
public boolean acceptsProfiles(String... profiles) {
return false;
}
@Override
public boolean acceptsProfiles(Profiles profiles) {
return false;
}
}

View File

@@ -53,8 +53,7 @@ public class SimpleWebApplicationContext extends StaticWebApplicationContext {
}
@SuppressWarnings("deprecation")
public static class LocaleChecker implements Controller, org.springframework.web.servlet.mvc.LastModified {
public static class LocaleChecker implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
@@ -71,11 +70,6 @@ public class SimpleWebApplicationContext extends StaticWebApplicationContext {
}
return null;
}
@Override
public long getLastModified(HttpServletRequest request) {
return 1427846400000L;
}
}
}