Support for Servlet 4.0 (PushBuilder argument, MockServletContext)

Issue: SPR-12674
This commit is contained in:
Juergen Hoeller 2017-02-13 15:06:59 +01:00
parent d44325ec91
commit 199aa776c9
32 changed files with 237 additions and 272 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -26,9 +26,7 @@ import javax.servlet.jsp.tagext.BodyContent;
/** /**
* Mock implementation of the {@link javax.servlet.jsp.tagext.BodyContent} class. * Mock implementation of the {@link javax.servlet.jsp.tagext.BodyContent} class.
* * Only necessary for testing applications when testing custom JSP tags.
* <p>Used for testing the web framework; only necessary for testing
* applications when testing custom JSP tags.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 2.5 * @since 2.5

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,14 +20,13 @@ import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext; import javax.servlet.jsp.PageContext;
import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* Mock implementation of the JSP 2.0 {@link javax.servlet.jsp.el.ExpressionEvaluator} * Mock implementation of the JSP 2.0 {@link javax.servlet.jsp.el.ExpressionEvaluator}
* interface, delegating to the Apache JSTL ExpressionEvaluatorManager. * interface, delegating to the Apache JSTL ExpressionEvaluatorManager.
* * Only necessary for testing applications when testing custom JSP tags.
* <p>Used for testing the web framework; only necessary for testing applications
* when testing custom JSP tags.
* *
* <p>Note that the Apache JSTL implementation (jstl.jar, standard.jar) has to be * <p>Note that the Apache JSTL implementation (jstl.jar, standard.jar) has to be
* available on the class path to use this expression evaluator. * available on the class path to use this expression evaluator.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -33,9 +33,7 @@ import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
/** /**
* <p>Mock implementation of the {@link javax.servlet.FilterChain} interface. Used * Mock implementation of the {@link javax.servlet.FilterChain} interface.
* for testing the web framework; also useful for testing custom
* {@link javax.servlet.Filter} implementations.
* *
* <p>A {@link MockFilterChain} can be configured with one or more filters and a * <p>A {@link MockFilterChain} can be configured with one or more filters and a
* Servlet to invoke. The first time the chain is called, it invokes all filters * Servlet to invoke. The first time the chain is called, it invokes all filters

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -70,7 +70,7 @@ import org.springframework.util.StringUtils;
* is {@link Locale#ENGLISH}. This value can be changed via {@link #addPreferredLocale} * is {@link Locale#ENGLISH}. This value can be changed via {@link #addPreferredLocale}
* or {@link #setPreferredLocales}. * or {@link #setPreferredLocales}.
* *
* <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 3.1 baseline. * <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Rod Johnson * @author Rod Johnson

View File

@ -45,7 +45,7 @@ import org.springframework.web.util.WebUtils;
/** /**
* Mock implementation of the {@link javax.servlet.http.HttpServletResponse} interface. * Mock implementation of the {@link javax.servlet.http.HttpServletResponse} interface.
* *
* <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 3.1 baseline. * <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Rod Johnson * @author Rod Johnson

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,10 +34,7 @@ import org.springframework.util.Assert;
/** /**
* Mock implementation of the {@link javax.servlet.http.HttpSession} interface. * Mock implementation of the {@link javax.servlet.http.HttpSession} interface.
* *
* <p>As of Spring 4.0, this set of mocks is designed on a Servlet 3.0 baseline. * <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
*
* <p>Used for testing the web framework; also useful for testing application
* controllers.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Rod Johnson * @author Rod Johnson
@ -72,7 +69,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Create a new MockHttpSession with a default {@link MockServletContext}. * Create a new MockHttpSession with a default {@link MockServletContext}.
*
* @see MockServletContext * @see MockServletContext
*/ */
public MockHttpSession() { public MockHttpSession() {
@ -81,7 +77,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Create a new MockHttpSession. * Create a new MockHttpSession.
*
* @param servletContext the ServletContext that the session runs in * @param servletContext the ServletContext that the session runs in
*/ */
public MockHttpSession(ServletContext servletContext) { public MockHttpSession(ServletContext servletContext) {
@ -90,7 +85,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Create a new MockHttpSession. * Create a new MockHttpSession.
*
* @param servletContext the ServletContext that the session runs in * @param servletContext the ServletContext that the session runs in
* @param id a unique identifier for this session * @param id a unique identifier for this session
*/ */
@ -99,6 +93,7 @@ public class MockHttpSession implements HttpSession {
this.id = (id != null ? id : Integer.toString(nextId++)); this.id = (id != null ? id : Integer.toString(nextId++));
} }
@Override @Override
public long getCreationTime() { public long getCreationTime() {
assertIsValid(); assertIsValid();
@ -111,8 +106,8 @@ public class MockHttpSession implements HttpSession {
} }
/** /**
* As of Servlet 3.1 the id of a session can be changed. * As of Servlet 3.1, the id of a session can be changed.
* @return the new session id. * @return the new session id
* @since 4.0.3 * @since 4.0.3
*/ */
public String changeSessionId() { public String changeSessionId() {
@ -227,7 +222,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Invalidates this session then unbinds any objects bound to it. * Invalidates this session then unbinds any objects bound to it.
*
* @throws IllegalStateException if this method is called on an already invalidated session * @throws IllegalStateException if this method is called on an already invalidated session
*/ */
@Override @Override
@ -244,7 +238,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Convenience method for asserting that this session has not been * Convenience method for asserting that this session has not been
* {@linkplain #invalidate() invalidated}. * {@linkplain #invalidate() invalidated}.
*
* @throws IllegalStateException if this session has been invalidated * @throws IllegalStateException if this session has been invalidated
*/ */
private void assertIsValid() { private void assertIsValid() {
@ -264,7 +257,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Serialize the attributes of this session into an object that can be * Serialize the attributes of this session into an object that can be
* turned into a byte array with standard Java serialization. * turned into a byte array with standard Java serialization.
*
* @return a representation of this session's serialized state * @return a representation of this session's serialized state
*/ */
public Serializable serializeState() { public Serializable serializeState() {
@ -291,7 +283,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Deserialize the attributes of this session from a state object created by * Deserialize the attributes of this session from a state object created by
* {@link #serializeState()}. * {@link #serializeState()}.
*
* @param state a representation of this session's serialized state * @param state a representation of this session's serialized state
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,9 +24,7 @@ import javax.servlet.jsp.JspWriter;
/** /**
* Mock implementation of the {@link javax.servlet.jsp.JspWriter} class. * Mock implementation of the {@link javax.servlet.jsp.JspWriter} class.
* * Only necessary for testing applications when testing custom JSP tags.
* <p>Used for testing the web framework; only necessary for testing
* applications when testing custom JSP tags.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 2.5 * @since 2.5

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -35,11 +35,10 @@ import org.springframework.web.multipart.MultipartHttpServletRequest;
* Mock implementation of the * Mock implementation of the
* {@link org.springframework.web.multipart.MultipartHttpServletRequest} interface. * {@link org.springframework.web.multipart.MultipartHttpServletRequest} interface.
* *
* <p>As of Spring 4.0, this set of mocks is designed on a Servlet 3.0 baseline. * <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* *
* <p>Useful for testing application controllers that access multipart uploads. * <p>Useful for testing application controllers that access multipart uploads.
* The {@link MockMultipartFile} can be used to populate these mock requests * {@link MockMultipartFile} can be used to populate these mock requests with files.
* with files.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Eric Crampton * @author Eric Crampton
@ -49,8 +48,7 @@ import org.springframework.web.multipart.MultipartHttpServletRequest;
*/ */
public class MockMultipartHttpServletRequest extends MockHttpServletRequest implements MultipartHttpServletRequest { public class MockMultipartHttpServletRequest extends MockHttpServletRequest implements MultipartHttpServletRequest {
private final MultiValueMap<String, MultipartFile> multipartFiles = private final MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<>();
new LinkedMultiValueMap<>();
/** /**

View File

@ -40,9 +40,7 @@ import org.springframework.util.Assert;
/** /**
* Mock implementation of the {@link javax.servlet.jsp.PageContext} interface. * Mock implementation of the {@link javax.servlet.jsp.PageContext} interface.
* * Only necessary for testing applications when testing custom JSP tags.
* <p>Used for testing the web framework; only necessary for testing
* applications when testing custom JSP tags.
* *
* <p>Note: Expects initialization via the constructor rather than via the * <p>Note: Expects initialization via the constructor rather than via the
* {@code PageContext.initialize} method. Does not support writing to a * {@code PageContext.initialize} method. Does not support writing to a

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,9 +29,6 @@ import org.springframework.util.Assert;
/** /**
* Mock implementation of the {@link javax.servlet.RequestDispatcher} interface. * Mock implementation of the {@link javax.servlet.RequestDispatcher} interface.
* *
* <p>Used for testing the web framework; typically not necessary for
* testing application controllers.
*
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen * @author Sam Brannen
@ -50,7 +47,7 @@ public class MockRequestDispatcher implements RequestDispatcher {
* particular path or given by a particular name * particular path or given by a particular name
*/ */
public MockRequestDispatcher(String resource) { public MockRequestDispatcher(String resource) {
Assert.notNull(resource, "resource must not be null"); Assert.notNull(resource, "Resource must not be null");
this.resource = resource; this.resource = resource;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,9 +28,6 @@ import org.springframework.util.Assert;
/** /**
* Mock implementation of the {@link javax.servlet.ServletConfig} interface. * Mock implementation of the {@link javax.servlet.ServletConfig} interface.
* *
* <p>Used for testing the web framework; typically not necessary for
* testing application controllers.
*
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 1.0.2 * @since 1.0.2

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -55,37 +55,21 @@ import org.springframework.web.util.WebUtils;
/** /**
* Mock implementation of the {@link javax.servlet.ServletContext} interface. * Mock implementation of the {@link javax.servlet.ServletContext} interface.
* *
* <p>As of Spring 4.0, this set of mocks is designed on a Servlet 3.0 baseline. * <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* *
* <p>Compatible with Servlet 3.0 but can be configured to expose a specific version * <p>Compatible with Servlet 3.1 but can be configured to expose a specific version
* through {@link #setMajorVersion}/{@link #setMinorVersion}; default is 3.0. * through {@link #setMajorVersion}/{@link #setMinorVersion}; default is 3.1.
* Note that Servlet 3.0 support is limited: servlet, filter and listener * Note that Servlet 3.1 support is limited: servlet, filter and listener
* registration methods are not supported; neither is JSP configuration. * registration methods are not supported; neither is JSP configuration.
* We generally do not recommend to unit test your ServletContainerInitializers and * We generally do not recommend to unit test your ServletContainerInitializers and
* WebApplicationInitializers which is where those registration methods would be used. * WebApplicationInitializers which is where those registration methods would be used.
* *
* <p>Used for testing the Spring web framework; only rarely necessary for testing * <p>For setting up a full {@code WebApplicationContext} in a test environment, you can
* application controllers. As long as application components don't explicitly * use {@code AnnotationConfigWebApplicationContext}, {@code XmlWebApplicationContext},
* access the {@code ServletContext}, {@code ClassPathXmlApplicationContext} or * or {@code GenericWebApplicationContext}, passing in a corresponding
* {@code FileSystemXmlApplicationContext} can be used to load the context files * {@code MockServletContext} instance. Consider configuring your
* for testing, even for {@code DispatcherServlet} context definitions. * {@code MockServletContext} with a {@code FileSystemResourceLoader} in order to
* * interpret resource paths as relative filesystem locations.
* <p>For setting up a full {@code WebApplicationContext} in a test environment,
* you can use {@code AnnotationConfigWebApplicationContext},
* {@code XmlWebApplicationContext}, or {@code GenericWebApplicationContext},
* passing in an appropriate {@code MockServletContext} instance. You might want
* to configure your {@code MockServletContext} with a {@code FileSystemResourceLoader}
* in that case to ensure that resource paths are interpreted as relative filesystem
* locations.
*
* <p>A common setup is to point your JVM working directory to the root of your
* web application directory, in combination with filesystem-based resource loading.
* This allows to load the context files as used in the web application, with
* relative paths getting interpreted correctly. Such a setup will work with both
* {@code FileSystemXmlApplicationContext} (which will load straight from the
* filesystem) and {@code XmlWebApplicationContext} with an underlying
* {@code MockServletContext} (as long as the {@code MockServletContext} has been
* configured with a {@code FileSystemResourceLoader}).
* *
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
@ -95,18 +79,15 @@ import org.springframework.web.util.WebUtils;
* @see org.springframework.web.context.support.AnnotationConfigWebApplicationContext * @see org.springframework.web.context.support.AnnotationConfigWebApplicationContext
* @see org.springframework.web.context.support.XmlWebApplicationContext * @see org.springframework.web.context.support.XmlWebApplicationContext
* @see org.springframework.web.context.support.GenericWebApplicationContext * @see org.springframework.web.context.support.GenericWebApplicationContext
* @see org.springframework.context.support.ClassPathXmlApplicationContext
* @see org.springframework.context.support.FileSystemXmlApplicationContext
*/ */
public class MockServletContext implements ServletContext { public class MockServletContext implements ServletContext {
/** Default Servlet name used by Tomcat, Jetty, JBoss, and GlassFish: {@value}. */ /** Default Servlet name used by Tomcat, Jetty, JBoss, and GlassFish: {@value} */
private static final String COMMON_DEFAULT_SERVLET_NAME = "default"; private static final String COMMON_DEFAULT_SERVLET_NAME = "default";
private static final String TEMP_DIR_SYSTEM_PROPERTY = "java.io.tmpdir"; private static final String TEMP_DIR_SYSTEM_PROPERTY = "java.io.tmpdir";
private static final Set<SessionTrackingMode> DEFAULT_SESSION_TRACKING_MODES = private static final Set<SessionTrackingMode> DEFAULT_SESSION_TRACKING_MODES = new LinkedHashSet<>(4);
new LinkedHashSet<>(3);
static { static {
DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.COOKIE); DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.COOKIE);
@ -127,11 +108,11 @@ public class MockServletContext implements ServletContext {
private int majorVersion = 3; private int majorVersion = 3;
private int minorVersion = 0; private int minorVersion = 1;
private int effectiveMajorVersion = 3; private int effectiveMajorVersion = 3;
private int effectiveMinorVersion = 0; private int effectiveMinorVersion = 1;
private final Map<String, RequestDispatcher> namedRequestDispatchers = new HashMap<>(); private final Map<String, RequestDispatcher> namedRequestDispatchers = new HashMap<>();
@ -149,6 +130,8 @@ public class MockServletContext implements ServletContext {
private final SessionCookieConfig sessionCookieConfig = new MockSessionCookieConfig(); private final SessionCookieConfig sessionCookieConfig = new MockSessionCookieConfig();
private int sessionTimeout;
/** /**
* Create a new {@code MockServletContext}, using no base path and a * Create a new {@code MockServletContext}, using no base path and a
@ -570,6 +553,16 @@ public class MockServletContext implements ServletContext {
return this.sessionCookieConfig; return this.sessionCookieConfig;
} }
// @Override - but only against Servlet 4.0
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
// @Override - but only against Servlet 4.0
public int getSessionTimeout() {
return this.sessionTimeout;
}
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Unsupported Servlet 3.0 registration methods // Unsupported Servlet 3.0 registration methods
@ -580,6 +573,11 @@ public class MockServletContext implements ServletContext {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
// @Override - but only against Servlet 4.0
public ServletRegistration.Dynamic addJspFile(String servletName, String jspFile) {
throw new UnsupportedOperationException();
}
@Override @Override
public ServletRegistration.Dynamic addServlet(String servletName, String className) { public ServletRegistration.Dynamic addServlet(String servletName, String className) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -97,16 +97,24 @@ public class MockServletContextTests {
@Test @Test
public void servletVersion() { public void servletVersion() {
assertEquals(3, sc.getMajorVersion()); assertEquals(3, sc.getMajorVersion());
assertEquals(0, sc.getMinorVersion());
sc.setMinorVersion(1);
assertEquals(1, sc.getMinorVersion()); assertEquals(1, sc.getMinorVersion());
assertEquals(3, sc.getEffectiveMajorVersion());
assertEquals(1, sc.getEffectiveMinorVersion());
sc.setMajorVersion(4);
sc.setMinorVersion(0);
sc.setEffectiveMajorVersion(4);
sc.setEffectiveMinorVersion(0);
assertEquals(4, sc.getMajorVersion());
assertEquals(0, sc.getMinorVersion());
assertEquals(4, sc.getEffectiveMajorVersion());
assertEquals(0, sc.getEffectiveMinorVersion());
} }
@Test @Test
public void registerAndUnregisterNamedDispatcher() throws Exception { public void registerAndUnregisterNamedDispatcher() throws Exception {
final String name = "test-servlet"; final String name = "test-servlet";
final String url = "/test"; final String url = "/test";
assertNull(sc.getNamedDispatcher(name)); assertNull(sc.getNamedDispatcher(name));
sc.registerNamedDispatcher(name, new MockRequestDispatcher(url)); sc.registerNamedDispatcher(name, new MockRequestDispatcher(url));

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -26,9 +26,7 @@ import javax.servlet.jsp.tagext.BodyContent;
/** /**
* Mock implementation of the {@link javax.servlet.jsp.tagext.BodyContent} class. * Mock implementation of the {@link javax.servlet.jsp.tagext.BodyContent} class.
* * Only necessary for testing applications when testing custom JSP tags.
* <p>Used for testing the web framework; only necessary for testing
* applications when testing custom JSP tags.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 2.5 * @since 2.5

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -21,12 +21,12 @@ import javax.servlet.jsp.PageContext;
import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;
import org.springframework.util.Assert;
/** /**
* Mock implementation of the JSP 2.0 {@link javax.servlet.jsp.el.ExpressionEvaluator} * Mock implementation of the JSP 2.0 {@link javax.servlet.jsp.el.ExpressionEvaluator}
* interface, delegating to the Apache JSTL ExpressionEvaluatorManager. * interface, delegating to the Apache JSTL ExpressionEvaluatorManager.
* * Only necessary for testing applications when testing custom JSP tags.
* <p>Used for testing the web framework; only necessary for testing applications
* when testing custom JSP tags.
* *
* <p>Note that the Apache JSTL implementation (jstl.jar, standard.jar) has to be * <p>Note that the Apache JSTL implementation (jstl.jar, standard.jar) has to be
* available on the class path to use this expression evaluator. * available on the class path to use this expression evaluator.
@ -68,9 +68,7 @@ public class MockExpressionEvaluator extends javax.servlet.jsp.el.ExpressionEval
public Object evaluate(String expression, Class expectedType, javax.servlet.jsp.el.VariableResolver variableResolver, public Object evaluate(String expression, Class expectedType, javax.servlet.jsp.el.VariableResolver variableResolver,
javax.servlet.jsp.el.FunctionMapper functionMapper) throws javax.servlet.jsp.el.ELException { javax.servlet.jsp.el.FunctionMapper functionMapper) throws javax.servlet.jsp.el.ELException {
if (variableResolver != null) { Assert.isNull(variableResolver, "Custom VariableResolver not supported");
throw new IllegalArgumentException("Custom VariableResolver not supported");
}
return doEvaluate(expression, expectedType, functionMapper); return doEvaluate(expression, expectedType, functionMapper);
} }
@ -78,9 +76,7 @@ public class MockExpressionEvaluator extends javax.servlet.jsp.el.ExpressionEval
protected Object doEvaluate(String expression, Class expectedType, javax.servlet.jsp.el.FunctionMapper functionMapper) protected Object doEvaluate(String expression, Class expectedType, javax.servlet.jsp.el.FunctionMapper functionMapper)
throws javax.servlet.jsp.el.ELException { throws javax.servlet.jsp.el.ELException {
if (functionMapper != null) { Assert.isNull(functionMapper, "Custom FunctionMapper not supported");
throw new IllegalArgumentException("Custom FunctionMapper not supported");
}
try { try {
return ExpressionEvaluatorManager.evaluate("JSP EL expression", expression, expectedType, this.pageContext); return ExpressionEvaluatorManager.evaluate("JSP EL expression", expression, expectedType, this.pageContext);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -33,9 +33,7 @@ import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
/** /**
* <p>Mock implementation of the {@link javax.servlet.FilterChain} interface. Used * Mock implementation of the {@link javax.servlet.FilterChain} interface.
* for testing the web framework; also useful for testing custom
* {@link javax.servlet.Filter} implementations.
* *
* <p>A {@link MockFilterChain} can be configured with one or more filters and a * <p>A {@link MockFilterChain} can be configured with one or more filters and a
* Servlet to invoke. The first time the chain is called, it invokes all filters * Servlet to invoke. The first time the chain is called, it invokes all filters
@ -120,10 +118,7 @@ public class MockFilterChain implements FilterChain {
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
Assert.notNull(request, "Request must not be null"); Assert.notNull(request, "Request must not be null");
Assert.notNull(response, "Response must not be null"); Assert.notNull(response, "Response must not be null");
Assert.state(this.request == null, "This FilterChain has already been called!");
if (this.request != null) {
throw new IllegalStateException("This FilterChain has already been called!");
}
if (this.iterator == null) { if (this.iterator == null) {
this.iterator = this.filters.iterator(); this.iterator = this.filters.iterator();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -70,7 +70,7 @@ import org.springframework.util.StringUtils;
* is {@link Locale#ENGLISH}. This value can be changed via {@link #addPreferredLocale} * is {@link Locale#ENGLISH}. This value can be changed via {@link #addPreferredLocale}
* or {@link #setPreferredLocales}. * or {@link #setPreferredLocales}.
* *
* <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 3.1 baseline. * <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Rod Johnson * @author Rod Johnson

View File

@ -45,7 +45,7 @@ import org.springframework.web.util.WebUtils;
/** /**
* Mock implementation of the {@link javax.servlet.http.HttpServletResponse} interface. * Mock implementation of the {@link javax.servlet.http.HttpServletResponse} interface.
* *
* <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 3.1 baseline. * <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Rod Johnson * @author Rod Johnson

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,10 +34,7 @@ import org.springframework.util.Assert;
/** /**
* Mock implementation of the {@link javax.servlet.http.HttpSession} interface. * Mock implementation of the {@link javax.servlet.http.HttpSession} interface.
* *
* <p>As of Spring 4.0, this set of mocks is designed on a Servlet 3.0 baseline. * <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
*
* <p>Used for testing the web framework; also useful for testing application
* controllers.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Rod Johnson * @author Rod Johnson
@ -72,7 +69,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Create a new MockHttpSession with a default {@link MockServletContext}. * Create a new MockHttpSession with a default {@link MockServletContext}.
*
* @see MockServletContext * @see MockServletContext
*/ */
public MockHttpSession() { public MockHttpSession() {
@ -81,7 +77,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Create a new MockHttpSession. * Create a new MockHttpSession.
*
* @param servletContext the ServletContext that the session runs in * @param servletContext the ServletContext that the session runs in
*/ */
public MockHttpSession(ServletContext servletContext) { public MockHttpSession(ServletContext servletContext) {
@ -90,7 +85,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Create a new MockHttpSession. * Create a new MockHttpSession.
*
* @param servletContext the ServletContext that the session runs in * @param servletContext the ServletContext that the session runs in
* @param id a unique identifier for this session * @param id a unique identifier for this session
*/ */
@ -99,6 +93,7 @@ public class MockHttpSession implements HttpSession {
this.id = (id != null ? id : Integer.toString(nextId++)); this.id = (id != null ? id : Integer.toString(nextId++));
} }
@Override @Override
public long getCreationTime() { public long getCreationTime() {
assertIsValid(); assertIsValid();
@ -111,8 +106,8 @@ public class MockHttpSession implements HttpSession {
} }
/** /**
* As of Servlet 3.1 the id of a session can be changed. * As of Servlet 3.1, the id of a session can be changed.
* @return the new session id. * @return the new session id
* @since 4.0.3 * @since 4.0.3
*/ */
public String changeSessionId() { public String changeSessionId() {
@ -227,7 +222,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Invalidates this session then unbinds any objects bound to it. * Invalidates this session then unbinds any objects bound to it.
*
* @throws IllegalStateException if this method is called on an already invalidated session * @throws IllegalStateException if this method is called on an already invalidated session
*/ */
@Override @Override
@ -244,13 +238,10 @@ public class MockHttpSession implements HttpSession {
/** /**
* Convenience method for asserting that this session has not been * Convenience method for asserting that this session has not been
* {@linkplain #invalidate() invalidated}. * {@linkplain #invalidate() invalidated}.
*
* @throws IllegalStateException if this session has been invalidated * @throws IllegalStateException if this session has been invalidated
*/ */
private void assertIsValid() { private void assertIsValid() {
if (isInvalid()) { Assert.state(!isInvalid(), "The session has already been invalidated");
throw new IllegalStateException("The session has already been invalidated");
}
} }
public void setNew(boolean value) { public void setNew(boolean value) {
@ -266,7 +257,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Serialize the attributes of this session into an object that can be * Serialize the attributes of this session into an object that can be
* turned into a byte array with standard Java serialization. * turned into a byte array with standard Java serialization.
*
* @return a representation of this session's serialized state * @return a representation of this session's serialized state
*/ */
public Serializable serializeState() { public Serializable serializeState() {
@ -293,7 +283,6 @@ public class MockHttpSession implements HttpSession {
/** /**
* Deserialize the attributes of this session from a state object created by * Deserialize the attributes of this session from a state object created by
* {@link #serializeState()}. * {@link #serializeState()}.
*
* @param state a representation of this session's serialized state * @param state a representation of this session's serialized state
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,9 +24,7 @@ import javax.servlet.jsp.JspWriter;
/** /**
* Mock implementation of the {@link javax.servlet.jsp.JspWriter} class. * Mock implementation of the {@link javax.servlet.jsp.JspWriter} class.
* * Only necessary for testing applications when testing custom JSP tags.
* <p>Used for testing the web framework; only necessary for testing
* applications when testing custom JSP tags.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 2.5 * @since 2.5

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -35,11 +35,10 @@ import org.springframework.web.multipart.MultipartHttpServletRequest;
* Mock implementation of the * Mock implementation of the
* {@link org.springframework.web.multipart.MultipartHttpServletRequest} interface. * {@link org.springframework.web.multipart.MultipartHttpServletRequest} interface.
* *
* <p>As of Spring 4.0, this set of mocks is designed on a Servlet 3.0 baseline. * <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* *
* <p>Useful for testing application controllers that access multipart uploads. * <p>Useful for testing application controllers that access multipart uploads.
* The {@link MockMultipartFile} can be used to populate these mock requests * {@link MockMultipartFile} can be used to populate these mock requests with files.
* with files.
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Eric Crampton * @author Eric Crampton
@ -49,8 +48,7 @@ import org.springframework.web.multipart.MultipartHttpServletRequest;
*/ */
public class MockMultipartHttpServletRequest extends MockHttpServletRequest implements MultipartHttpServletRequest { public class MockMultipartHttpServletRequest extends MockHttpServletRequest implements MultipartHttpServletRequest {
private final MultiValueMap<String, MultipartFile> multipartFiles = private final MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<>();
new LinkedMultiValueMap<>();
/** /**

View File

@ -40,9 +40,7 @@ import org.springframework.util.Assert;
/** /**
* Mock implementation of the {@link javax.servlet.jsp.PageContext} interface. * Mock implementation of the {@link javax.servlet.jsp.PageContext} interface.
* * Only necessary for testing applications when testing custom JSP tags.
* <p>Used for testing the web framework; only necessary for testing
* applications when testing custom JSP tags.
* *
* <p>Note: Expects initialization via the constructor rather than via the * <p>Note: Expects initialization via the constructor rather than via the
* {@code PageContext.initialize} method. Does not support writing to a * {@code PageContext.initialize} method. Does not support writing to a

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,9 +29,6 @@ import org.springframework.util.Assert;
/** /**
* Mock implementation of the {@link javax.servlet.RequestDispatcher} interface. * Mock implementation of the {@link javax.servlet.RequestDispatcher} interface.
* *
* <p>Used for testing the web framework; typically not necessary for
* testing application controllers.
*
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen * @author Sam Brannen
@ -50,7 +47,7 @@ public class MockRequestDispatcher implements RequestDispatcher {
* particular path or given by a particular name * particular path or given by a particular name
*/ */
public MockRequestDispatcher(String resource) { public MockRequestDispatcher(String resource) {
Assert.notNull(resource, "resource must not be null"); Assert.notNull(resource, "Resource must not be null");
this.resource = resource; this.resource = resource;
} }
@ -59,9 +56,7 @@ public class MockRequestDispatcher implements RequestDispatcher {
public void forward(ServletRequest request, ServletResponse response) { public void forward(ServletRequest request, ServletResponse response) {
Assert.notNull(request, "Request must not be null"); Assert.notNull(request, "Request must not be null");
Assert.notNull(response, "Response must not be null"); Assert.notNull(response, "Response must not be null");
if (response.isCommitted()) { Assert.state(!response.isCommitted(), "Cannot perform forward - response is already committed");
throw new IllegalStateException("Cannot perform forward - response is already committed");
}
getMockHttpServletResponse(response).setForwardedUrl(this.resource); getMockHttpServletResponse(response).setForwardedUrl(this.resource);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("MockRequestDispatcher: forwarding to [" + this.resource + "]"); logger.debug("MockRequestDispatcher: forwarding to [" + this.resource + "]");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,9 +28,6 @@ import org.springframework.util.Assert;
/** /**
* Mock implementation of the {@link javax.servlet.ServletConfig} interface. * Mock implementation of the {@link javax.servlet.ServletConfig} interface.
* *
* <p>Used for testing the web framework; typically not necessary for
* testing application controllers.
*
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 1.0.2 * @since 1.0.2

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -55,37 +55,21 @@ import org.springframework.web.util.WebUtils;
/** /**
* Mock implementation of the {@link javax.servlet.ServletContext} interface. * Mock implementation of the {@link javax.servlet.ServletContext} interface.
* *
* <p>As of Spring 4.0, this set of mocks is designed on a Servlet 3.0 baseline. * <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
* *
* <p>Compatible with Servlet 3.0 but can be configured to expose a specific version * <p>Compatible with Servlet 3.1 but can be configured to expose a specific version
* through {@link #setMajorVersion}/{@link #setMinorVersion}; default is 3.0. * through {@link #setMajorVersion}/{@link #setMinorVersion}; default is 3.1.
* Note that Servlet 3.0 support is limited: servlet, filter and listener * Note that Servlet 3.1 support is limited: servlet, filter and listener
* registration methods are not supported; neither is JSP configuration. * registration methods are not supported; neither is JSP configuration.
* We generally do not recommend to unit test your ServletContainerInitializers and * We generally do not recommend to unit test your ServletContainerInitializers and
* WebApplicationInitializers which is where those registration methods would be used. * WebApplicationInitializers which is where those registration methods would be used.
* *
* <p>Used for testing the Spring web framework; only rarely necessary for testing * <p>For setting up a full {@code WebApplicationContext} in a test environment, you can
* application controllers. As long as application components don't explicitly * use {@code AnnotationConfigWebApplicationContext}, {@code XmlWebApplicationContext},
* access the {@code ServletContext}, {@code ClassPathXmlApplicationContext} or * or {@code GenericWebApplicationContext}, passing in a corresponding
* {@code FileSystemXmlApplicationContext} can be used to load the context files * {@code MockServletContext} instance. Consider configuring your
* for testing, even for {@code DispatcherServlet} context definitions. * {@code MockServletContext} with a {@code FileSystemResourceLoader} in order to
* * interpret resource paths as relative filesystem locations.
* <p>For setting up a full {@code WebApplicationContext} in a test environment,
* you can use {@code AnnotationConfigWebApplicationContext},
* {@code XmlWebApplicationContext}, or {@code GenericWebApplicationContext},
* passing in an appropriate {@code MockServletContext} instance. You might want
* to configure your {@code MockServletContext} with a {@code FileSystemResourceLoader}
* in that case to ensure that resource paths are interpreted as relative filesystem
* locations.
*
* <p>A common setup is to point your JVM working directory to the root of your
* web application directory, in combination with filesystem-based resource loading.
* This allows to load the context files as used in the web application, with
* relative paths getting interpreted correctly. Such a setup will work with both
* {@code FileSystemXmlApplicationContext} (which will load straight from the
* filesystem) and {@code XmlWebApplicationContext} with an underlying
* {@code MockServletContext} (as long as the {@code MockServletContext} has been
* configured with a {@code FileSystemResourceLoader}).
* *
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
@ -95,18 +79,15 @@ import org.springframework.web.util.WebUtils;
* @see org.springframework.web.context.support.AnnotationConfigWebApplicationContext * @see org.springframework.web.context.support.AnnotationConfigWebApplicationContext
* @see org.springframework.web.context.support.XmlWebApplicationContext * @see org.springframework.web.context.support.XmlWebApplicationContext
* @see org.springframework.web.context.support.GenericWebApplicationContext * @see org.springframework.web.context.support.GenericWebApplicationContext
* @see org.springframework.context.support.ClassPathXmlApplicationContext
* @see org.springframework.context.support.FileSystemXmlApplicationContext
*/ */
public class MockServletContext implements ServletContext { public class MockServletContext implements ServletContext {
/** Default Servlet name used by Tomcat, Jetty, JBoss, and GlassFish: {@value}. */ /** Default Servlet name used by Tomcat, Jetty, JBoss, and GlassFish: {@value} */
private static final String COMMON_DEFAULT_SERVLET_NAME = "default"; private static final String COMMON_DEFAULT_SERVLET_NAME = "default";
private static final String TEMP_DIR_SYSTEM_PROPERTY = "java.io.tmpdir"; private static final String TEMP_DIR_SYSTEM_PROPERTY = "java.io.tmpdir";
private static final Set<SessionTrackingMode> DEFAULT_SESSION_TRACKING_MODES = private static final Set<SessionTrackingMode> DEFAULT_SESSION_TRACKING_MODES = new LinkedHashSet<>(4);
new LinkedHashSet<>(3);
static { static {
DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.COOKIE); DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.COOKIE);
@ -127,11 +108,11 @@ public class MockServletContext implements ServletContext {
private int majorVersion = 3; private int majorVersion = 3;
private int minorVersion = 0; private int minorVersion = 1;
private int effectiveMajorVersion = 3; private int effectiveMajorVersion = 3;
private int effectiveMinorVersion = 0; private int effectiveMinorVersion = 1;
private final Map<String, RequestDispatcher> namedRequestDispatchers = new HashMap<>(); private final Map<String, RequestDispatcher> namedRequestDispatchers = new HashMap<>();
@ -149,6 +130,8 @@ public class MockServletContext implements ServletContext {
private final SessionCookieConfig sessionCookieConfig = new MockSessionCookieConfig(); private final SessionCookieConfig sessionCookieConfig = new MockSessionCookieConfig();
private int sessionTimeout;
/** /**
* Create a new {@code MockServletContext}, using no base path and a * Create a new {@code MockServletContext}, using no base path and a
@ -425,13 +408,13 @@ public class MockServletContext implements ServletContext {
@Override @Override
@Deprecated @Deprecated
public Enumeration<Servlet> getServlets() { public Enumeration<Servlet> getServlets() {
return Collections.enumeration(Collections.<Servlet>emptySet()); return Collections.enumeration(Collections.emptySet());
} }
@Override @Override
@Deprecated @Deprecated
public Enumeration<String> getServletNames() { public Enumeration<String> getServletNames() {
return Collections.enumeration(Collections.<String>emptySet()); return Collections.enumeration(Collections.emptySet());
} }
@Override @Override
@ -570,6 +553,16 @@ public class MockServletContext implements ServletContext {
return this.sessionCookieConfig; return this.sessionCookieConfig;
} }
// @Override - but only against Servlet 4.0
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
// @Override - but only against Servlet 4.0
public int getSessionTimeout() {
return this.sessionTimeout;
}
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Unsupported Servlet 3.0 registration methods // Unsupported Servlet 3.0 registration methods
@ -580,6 +573,11 @@ public class MockServletContext implements ServletContext {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
// @Override - but only against Servlet 4.0
public ServletRegistration.Dynamic addJspFile(String servletName, String jspFile) {
throw new UnsupportedOperationException();
}
@Override @Override
public ServletRegistration.Dynamic addServlet(String servletName, String className) { public ServletRegistration.Dynamic addServlet(String servletName, String className) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();

View File

@ -16,8 +16,10 @@
package org.springframework.web.servlet.mvc.method.annotation; package org.springframework.web.servlet.mvc.method.annotation;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.lang.reflect.Method;
import java.security.Principal; import java.security.Principal;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.Locale; import java.util.Locale;
@ -28,6 +30,8 @@ import javax.servlet.http.HttpSession;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.WebRequest; import org.springframework.web.context.request.WebRequest;
@ -43,13 +47,14 @@ import org.springframework.web.servlet.support.RequestContextUtils;
* <li>{@link ServletRequest} * <li>{@link ServletRequest}
* <li>{@link MultipartRequest} * <li>{@link MultipartRequest}
* <li>{@link HttpSession} * <li>{@link HttpSession}
* <li>{@link PushBuilder} (as of Spring 5.0 on Servlet 4.0)
* <li>{@link Principal} * <li>{@link Principal}
* <li>{@link InputStream} * <li>{@link InputStream}
* <li>{@link Reader} * <li>{@link Reader}
* <li>{@link HttpMethod} (as of Spring 4.0)</li> * <li>{@link HttpMethod} (as of Spring 4.0)
* <li>{@link Locale} * <li>{@link Locale}
* <li>{@link TimeZone} (as of Spring 4.0) * <li>{@link TimeZone} (as of Spring 4.0)
* <li>{@link java.time.ZoneId} (as of Spring 4.0 and Java 8)</li> * <li>{@link java.time.ZoneId} (as of Spring 4.0 and Java 8)
* </ul> * </ul>
* *
* @author Arjen Poutsma * @author Arjen Poutsma
@ -59,6 +64,10 @@ import org.springframework.web.servlet.support.RequestContextUtils;
*/ */
public class ServletRequestMethodArgumentResolver implements HandlerMethodArgumentResolver { public class ServletRequestMethodArgumentResolver implements HandlerMethodArgumentResolver {
private static final Method getPushBuilderMethod =
ClassUtils.getMethodIfAvailable(HttpServletRequest.class, "getPushBuilder");
@Override @Override
public boolean supportsParameter(MethodParameter parameter) { public boolean supportsParameter(MethodParameter parameter) {
Class<?> paramType = parameter.getParameterType(); Class<?> paramType = parameter.getParameterType();
@ -66,6 +75,7 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
ServletRequest.class.isAssignableFrom(paramType) || ServletRequest.class.isAssignableFrom(paramType) ||
MultipartRequest.class.isAssignableFrom(paramType) || MultipartRequest.class.isAssignableFrom(paramType) ||
HttpSession.class.isAssignableFrom(paramType) || HttpSession.class.isAssignableFrom(paramType) ||
(getPushBuilderMethod != null && getPushBuilderMethod.getReturnType().isAssignableFrom(paramType)) ||
Principal.class.isAssignableFrom(paramType) || Principal.class.isAssignableFrom(paramType) ||
InputStream.class.isAssignableFrom(paramType) || InputStream.class.isAssignableFrom(paramType) ||
Reader.class.isAssignableFrom(paramType) || Reader.class.isAssignableFrom(paramType) ||
@ -80,6 +90,8 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Class<?> paramType = parameter.getParameterType(); Class<?> paramType = parameter.getParameterType();
// WebRequest / NativeWebRequest / ServletWebRequest
if (WebRequest.class.isAssignableFrom(paramType)) { if (WebRequest.class.isAssignableFrom(paramType)) {
if (!paramType.isInstance(webRequest)) { if (!paramType.isInstance(webRequest)) {
throw new IllegalStateException( throw new IllegalStateException(
@ -88,16 +100,26 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
return webRequest; return webRequest;
} }
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); // ServletRequest / HttpServletRequest / MultipartRequest / MultipartHttpServletRequest
if (ServletRequest.class.isAssignableFrom(paramType) || MultipartRequest.class.isAssignableFrom(paramType)) { if (ServletRequest.class.isAssignableFrom(paramType) || MultipartRequest.class.isAssignableFrom(paramType)) {
Object nativeRequest = webRequest.getNativeRequest(paramType); return resolveNativeRequest(webRequest, paramType);
if (nativeRequest == null) {
throw new IllegalStateException(
"Current request is not of type [" + paramType.getName() + "]: " + request);
}
return nativeRequest;
} }
else if (HttpSession.class.isAssignableFrom(paramType)) {
// HttpServletRequest required for all further argument types
return resolveArgument(paramType, resolveNativeRequest(webRequest, HttpServletRequest.class));
}
private <T> T resolveNativeRequest(NativeWebRequest webRequest, Class<T> requiredType) {
T nativeRequest = webRequest.getNativeRequest(requiredType);
if (nativeRequest == null) {
throw new IllegalStateException(
"Current request is not of type [" + requiredType.getName() + "]: " + webRequest);
}
return nativeRequest;
}
private Object resolveArgument(Class<?> paramType, HttpServletRequest request) throws IOException {
if (HttpSession.class.isAssignableFrom(paramType)) {
HttpSession session = request.getSession(); HttpSession session = request.getSession();
if (!paramType.isInstance(session)) { if (!paramType.isInstance(session)) {
throw new IllegalStateException( throw new IllegalStateException(
@ -105,6 +127,14 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
} }
return session; return session;
} }
else if (getPushBuilderMethod != null && getPushBuilderMethod.getReturnType().isAssignableFrom(paramType)) {
Object pushBuilder = ReflectionUtils.invokeMethod(getPushBuilderMethod, request);
if (!paramType.isInstance(pushBuilder)) {
throw new IllegalStateException(
"Current push builder is not of type [" + paramType.getName() + "]: " + pushBuilder);
}
return pushBuilder;
}
else if (InputStream.class.isAssignableFrom(paramType)) { else if (InputStream.class.isAssignableFrom(paramType)) {
InputStream inputStream = request.getInputStream(); InputStream inputStream = request.getInputStream();
if (!paramType.isInstance(inputStream)) { if (!paramType.isInstance(inputStream)) {
@ -143,11 +173,9 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
TimeZone timeZone = RequestContextUtils.getTimeZone(request); TimeZone timeZone = RequestContextUtils.getTimeZone(request);
return (timeZone != null ? timeZone.toZoneId() : ZoneId.systemDefault()); return (timeZone != null ? timeZone.toZoneId() : ZoneId.systemDefault());
} }
else {
// Should never happen... // Should never happen...
throw new UnsupportedOperationException( throw new UnsupportedOperationException("Unknown parameter type: " + paramType.getName());
"Unknown parameter type [" + paramType.getName() + "] in " + parameter.getMethod());
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,11 +16,10 @@
package org.springframework.web.servlet.mvc.method.annotation; package org.springframework.web.servlet.mvc.method.annotation;
import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.Writer; import java.io.Writer;
import java.lang.reflect.Method;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.bind.support.WebDataBinderFactory;
@ -38,6 +37,7 @@ import org.springframework.web.method.support.ModelAndViewContainer;
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 3.1 * @since 3.1
*/ */
public class ServletResponseMethodArgumentResolver implements HandlerMethodArgumentResolver { public class ServletResponseMethodArgumentResolver implements HandlerMethodArgumentResolver {
@ -64,28 +64,36 @@ public class ServletResponseMethodArgumentResolver implements HandlerMethodArgum
mavContainer.setRequestHandled(true); mavContainer.setRequestHandled(true);
} }
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
Class<?> paramType = parameter.getParameterType(); Class<?> paramType = parameter.getParameterType();
// ServletResponse, HttpServletResponse
if (ServletResponse.class.isAssignableFrom(paramType)) { if (ServletResponse.class.isAssignableFrom(paramType)) {
Object nativeResponse = webRequest.getNativeResponse(paramType); return resolveNativeResponse(webRequest, paramType);
if (nativeResponse == null) {
throw new IllegalStateException(
"Current response is not of type [" + paramType.getName() + "]: " + response);
}
return nativeResponse;
} }
else if (OutputStream.class.isAssignableFrom(paramType)) {
// ServletResponse required for all further argument types
return resolveArgument(paramType, resolveNativeResponse(webRequest, ServletResponse.class));
}
private <T> T resolveNativeResponse(NativeWebRequest webRequest, Class<T> requiredType) {
T nativeResponse = webRequest.getNativeResponse(requiredType);
if (nativeResponse == null) {
throw new IllegalStateException(
"Current response is not of type [" + requiredType.getName() + "]: " + webRequest);
}
return nativeResponse;
}
private Object resolveArgument(Class<?> paramType, ServletResponse response) throws IOException {
if (OutputStream.class.isAssignableFrom(paramType)) {
return response.getOutputStream(); return response.getOutputStream();
} }
else if (Writer.class.isAssignableFrom(paramType)) { else if (Writer.class.isAssignableFrom(paramType)) {
return response.getWriter(); return response.getWriter();
} }
else {
// should not happen // Should never happen...
Method method = parameter.getMethod(); throw new UnsupportedOperationException("Unknown parameter type: " + paramType);
throw new UnsupportedOperationException("Unknown parameter type: " + paramType + " in method: " + method);
}
} }
} }

View File

@ -75,11 +75,9 @@ public class ServletRequestMethodArgumentResolverTests {
@Test @Test
public void servletRequest() throws Exception { public void servletRequest() throws Exception {
MethodParameter servletRequestParameter = new MethodParameter(method, 0); MethodParameter servletRequestParameter = new MethodParameter(method, 0);
assertTrue("ServletRequest not supported", resolver.supportsParameter(servletRequestParameter));
boolean isSupported = resolver.supportsParameter(servletRequestParameter);
Object result = resolver.resolveArgument(servletRequestParameter, mavContainer, webRequest, null); Object result = resolver.resolveArgument(servletRequestParameter, mavContainer, webRequest, null);
assertTrue("ServletRequest not supported", isSupported);
assertSame("Invalid result", servletRequest, result); assertSame("Invalid result", servletRequest, result);
assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled()); assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
} }
@ -88,12 +86,11 @@ public class ServletRequestMethodArgumentResolverTests {
public void session() throws Exception { public void session() throws Exception {
MockHttpSession session = new MockHttpSession(); MockHttpSession session = new MockHttpSession();
servletRequest.setSession(session); servletRequest.setSession(session);
MethodParameter sessionParameter = new MethodParameter(method, 2); MethodParameter sessionParameter = new MethodParameter(method, 2);
assertTrue("Session not supported", resolver.supportsParameter(sessionParameter));
boolean isSupported = resolver.supportsParameter(sessionParameter);
Object result = resolver.resolveArgument(sessionParameter, mavContainer, webRequest, null); Object result = resolver.resolveArgument(sessionParameter, mavContainer, webRequest, null);
assertTrue("Session not supported", isSupported);
assertSame("Invalid result", session, result); assertSame("Invalid result", session, result);
assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled()); assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
} }
@ -107,8 +104,8 @@ public class ServletRequestMethodArgumentResolverTests {
} }
}; };
servletRequest.setUserPrincipal(principal); servletRequest.setUserPrincipal(principal);
MethodParameter principalParameter = new MethodParameter(method, 3);
MethodParameter principalParameter = new MethodParameter(method, 3);
assertTrue("Principal not supported", resolver.supportsParameter(principalParameter)); assertTrue("Principal not supported", resolver.supportsParameter(principalParameter));
Object result = resolver.resolveArgument(principalParameter, null, webRequest, null); Object result = resolver.resolveArgument(principalParameter, null, webRequest, null);
@ -119,8 +116,8 @@ public class ServletRequestMethodArgumentResolverTests {
public void locale() throws Exception { public void locale() throws Exception {
Locale locale = Locale.ENGLISH; Locale locale = Locale.ENGLISH;
servletRequest.addPreferredLocale(locale); servletRequest.addPreferredLocale(locale);
MethodParameter localeParameter = new MethodParameter(method, 4);
MethodParameter localeParameter = new MethodParameter(method, 4);
assertTrue("Locale not supported", resolver.supportsParameter(localeParameter)); assertTrue("Locale not supported", resolver.supportsParameter(localeParameter));
Object result = resolver.resolveArgument(localeParameter, null, webRequest, null); Object result = resolver.resolveArgument(localeParameter, null, webRequest, null);
@ -132,8 +129,8 @@ public class ServletRequestMethodArgumentResolverTests {
Locale locale = Locale.ENGLISH; Locale locale = Locale.ENGLISH;
servletRequest.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, servletRequest.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE,
new FixedLocaleResolver(locale)); new FixedLocaleResolver(locale));
MethodParameter localeParameter = new MethodParameter(method, 4);
MethodParameter localeParameter = new MethodParameter(method, 4);
assertTrue("Locale not supported", resolver.supportsParameter(localeParameter)); assertTrue("Locale not supported", resolver.supportsParameter(localeParameter));
Object result = resolver.resolveArgument(localeParameter, null, webRequest, null); Object result = resolver.resolveArgument(localeParameter, null, webRequest, null);
@ -143,7 +140,6 @@ public class ServletRequestMethodArgumentResolverTests {
@Test @Test
public void timeZone() throws Exception { public void timeZone() throws Exception {
MethodParameter timeZoneParameter = new MethodParameter(method, 8); MethodParameter timeZoneParameter = new MethodParameter(method, 8);
assertTrue("TimeZone not supported", resolver.supportsParameter(timeZoneParameter)); assertTrue("TimeZone not supported", resolver.supportsParameter(timeZoneParameter));
Object result = resolver.resolveArgument(timeZoneParameter, null, webRequest, null); Object result = resolver.resolveArgument(timeZoneParameter, null, webRequest, null);
@ -155,8 +151,8 @@ public class ServletRequestMethodArgumentResolverTests {
TimeZone timeZone = TimeZone.getTimeZone("America/Los_Angeles"); TimeZone timeZone = TimeZone.getTimeZone("America/Los_Angeles");
servletRequest.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, servletRequest.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE,
new FixedLocaleResolver(Locale.US, timeZone)); new FixedLocaleResolver(Locale.US, timeZone));
MethodParameter timeZoneParameter = new MethodParameter(method, 8);
MethodParameter timeZoneParameter = new MethodParameter(method, 8);
assertTrue("TimeZone not supported", resolver.supportsParameter(timeZoneParameter)); assertTrue("TimeZone not supported", resolver.supportsParameter(timeZoneParameter));
Object result = resolver.resolveArgument(timeZoneParameter, null, webRequest, null); Object result = resolver.resolveArgument(timeZoneParameter, null, webRequest, null);
@ -166,7 +162,6 @@ public class ServletRequestMethodArgumentResolverTests {
@Test @Test
public void zoneId() throws Exception { public void zoneId() throws Exception {
MethodParameter zoneIdParameter = new MethodParameter(method, 9); MethodParameter zoneIdParameter = new MethodParameter(method, 9);
assertTrue("ZoneId not supported", resolver.supportsParameter(zoneIdParameter)); assertTrue("ZoneId not supported", resolver.supportsParameter(zoneIdParameter));
Object result = resolver.resolveArgument(zoneIdParameter, null, webRequest, null); Object result = resolver.resolveArgument(zoneIdParameter, null, webRequest, null);
@ -189,7 +184,6 @@ public class ServletRequestMethodArgumentResolverTests {
@Test @Test
public void inputStream() throws Exception { public void inputStream() throws Exception {
MethodParameter inputStreamParameter = new MethodParameter(method, 5); MethodParameter inputStreamParameter = new MethodParameter(method, 5);
assertTrue("InputStream not supported", resolver.supportsParameter(inputStreamParameter)); assertTrue("InputStream not supported", resolver.supportsParameter(inputStreamParameter));
Object result = resolver.resolveArgument(inputStreamParameter, null, webRequest, null); Object result = resolver.resolveArgument(inputStreamParameter, null, webRequest, null);
@ -199,7 +193,6 @@ public class ServletRequestMethodArgumentResolverTests {
@Test @Test
public void reader() throws Exception { public void reader() throws Exception {
MethodParameter readerParameter = new MethodParameter(method, 6); MethodParameter readerParameter = new MethodParameter(method, 6);
assertTrue("Reader not supported", resolver.supportsParameter(readerParameter)); assertTrue("Reader not supported", resolver.supportsParameter(readerParameter));
Object result = resolver.resolveArgument(readerParameter, null, webRequest, null); Object result = resolver.resolveArgument(readerParameter, null, webRequest, null);
@ -209,7 +202,6 @@ public class ServletRequestMethodArgumentResolverTests {
@Test @Test
public void webRequest() throws Exception { public void webRequest() throws Exception {
MethodParameter webRequestParameter = new MethodParameter(method, 7); MethodParameter webRequestParameter = new MethodParameter(method, 7);
assertTrue("WebRequest not supported", resolver.supportsParameter(webRequestParameter)); assertTrue("WebRequest not supported", resolver.supportsParameter(webRequestParameter));
Object result = resolver.resolveArgument(webRequestParameter, null, webRequest, null); Object result = resolver.resolveArgument(webRequestParameter, null, webRequest, null);
@ -219,7 +211,6 @@ public class ServletRequestMethodArgumentResolverTests {
@Test @Test
public void httpMethod() throws Exception { public void httpMethod() throws Exception {
MethodParameter httpMethodParameter = new MethodParameter(method, 10); MethodParameter httpMethodParameter = new MethodParameter(method, 10);
assertTrue("HttpMethod not supported", resolver.supportsParameter(httpMethodParameter)); assertTrue("HttpMethod not supported", resolver.supportsParameter(httpMethodParameter));
Object result = resolver.resolveArgument(httpMethodParameter, null, webRequest, null); Object result = resolver.resolveArgument(httpMethodParameter, null, webRequest, null);
@ -241,4 +232,4 @@ public class ServletRequestMethodArgumentResolverTests {
HttpMethod p10) { HttpMethod p10) {
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -33,7 +33,7 @@ import org.springframework.web.method.support.ModelAndViewContainer;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
* Test fixture with {@link org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver}. * Test fixture with {@link ServletResponseMethodArgumentResolver}.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
*/ */
@ -49,6 +49,7 @@ public class ServletResponseMethodArgumentResolverTests {
private MockHttpServletResponse servletResponse; private MockHttpServletResponse servletResponse;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
resolver = new ServletResponseMethodArgumentResolver(); resolver = new ServletResponseMethodArgumentResolver();
@ -58,10 +59,10 @@ public class ServletResponseMethodArgumentResolverTests {
webRequest = new ServletWebRequest(new MockHttpServletRequest(), servletResponse); webRequest = new ServletWebRequest(new MockHttpServletRequest(), servletResponse);
} }
@Test @Test
public void servletResponse() throws Exception { public void servletResponse() throws Exception {
MethodParameter servletResponseParameter = new MethodParameter(method, 0); MethodParameter servletResponseParameter = new MethodParameter(method, 0);
assertTrue("ServletResponse not supported", resolver.supportsParameter(servletResponseParameter)); assertTrue("ServletResponse not supported", resolver.supportsParameter(servletResponseParameter));
Object result = resolver.resolveArgument(servletResponseParameter, mavContainer, webRequest, null); Object result = resolver.resolveArgument(servletResponseParameter, mavContainer, webRequest, null);
@ -69,8 +70,7 @@ public class ServletResponseMethodArgumentResolverTests {
assertTrue(mavContainer.isRequestHandled()); assertTrue(mavContainer.isRequestHandled());
} }
// SPR-8983 @Test // SPR-8983
public void servletResponseNoMavContainer() throws Exception { public void servletResponseNoMavContainer() throws Exception {
MethodParameter servletResponseParameter = new MethodParameter(method, 0); MethodParameter servletResponseParameter = new MethodParameter(method, 0);
assertTrue("ServletResponse not supported", resolver.supportsParameter(servletResponseParameter)); assertTrue("ServletResponse not supported", resolver.supportsParameter(servletResponseParameter));
@ -82,7 +82,6 @@ public class ServletResponseMethodArgumentResolverTests {
@Test @Test
public void outputStream() throws Exception { public void outputStream() throws Exception {
MethodParameter outputStreamParameter = new MethodParameter(method, 1); MethodParameter outputStreamParameter = new MethodParameter(method, 1);
assertTrue("OutputStream not supported", resolver.supportsParameter(outputStreamParameter)); assertTrue("OutputStream not supported", resolver.supportsParameter(outputStreamParameter));
Object result = resolver.resolveArgument(outputStreamParameter, mavContainer, webRequest, null); Object result = resolver.resolveArgument(outputStreamParameter, mavContainer, webRequest, null);
@ -93,7 +92,6 @@ public class ServletResponseMethodArgumentResolverTests {
@Test @Test
public void writer() throws Exception { public void writer() throws Exception {
MethodParameter writerParameter = new MethodParameter(method, 2); MethodParameter writerParameter = new MethodParameter(method, 2);
assertTrue("Writer not supported", resolver.supportsParameter(writerParameter)); assertTrue("Writer not supported", resolver.supportsParameter(writerParameter));
Object result = resolver.resolveArgument(writerParameter, mavContainer, webRequest, null); Object result = resolver.resolveArgument(writerParameter, mavContainer, webRequest, null);
@ -101,7 +99,9 @@ public class ServletResponseMethodArgumentResolverTests {
assertTrue(mavContainer.isRequestHandled()); assertTrue(mavContainer.isRequestHandled());
} }
public void supportedParams(ServletResponse p0, OutputStream p1, Writer p2) {
@SuppressWarnings("unused")
public void supportedParams(ServletResponse p0, OutputStream p1, Writer p2) {
} }
}
}

View File

@ -476,11 +476,9 @@ abstract way, which enables you to create a wide variety of controllers.
Spring 2.5 introduced an annotation-based programming model for MVC controllers that Spring 2.5 introduced an annotation-based programming model for MVC controllers that
uses annotations such as `@RequestMapping`, `@RequestParam`, `@ModelAttribute`, and so uses annotations such as `@RequestMapping`, `@RequestParam`, `@ModelAttribute`, and so
on. This annotation support is available for both Servlet MVC and Portlet MVC. on. Controllers implemented in this style do not have to extend specific base classes or
Controllers implemented in this style do not have to extend specific base classes or
implement specific interfaces. Furthermore, they do not usually have direct dependencies implement specific interfaces. Furthermore, they do not usually have direct dependencies
on Servlet or Portlet APIs, although you can easily configure access to Servlet or on Servlet APIs, although you can easily configure access to Servlet facilities if needed.
Portlet facilities.
[TIP] [TIP]
==== ====
@ -1293,8 +1291,13 @@ neither.
==== Supported method argument types ==== Supported method argument types
The following are the supported method arguments: The following are the supported method arguments:
* `org.springframework.web.context.request.WebRequest` or
`org.springframework.web.context.request.NativeWebRequest`. Allows for generic
request parameter access as well as request/session attribute access, without ties
to the native Servlet API.
* Request or response objects (Servlet API). Choose any specific request or response * Request or response objects (Servlet API). Choose any specific request or response
type, for example `ServletRequest` or `HttpServletRequest`. type, for example `ServletRequest` or `HttpServletRequest` or Spring's
`MultipartRequest`/`MultipartHttpServletRequest`.
* Session object (Servlet API) of type `HttpSession`. An argument of this type enforces * Session object (Servlet API) of type `HttpSession`. An argument of this type enforces
the presence of a corresponding session. As a consequence, such an argument is never the presence of a corresponding session. As a consequence, such an argument is never
`null`. `null`.
@ -1306,21 +1309,21 @@ setting the ``RequestMappingHandlerAdapter``'s "synchronizeOnSession" flag to "t
multiple requests are allowed to access a session concurrently. multiple requests are allowed to access a session concurrently.
==== ====
* `org.springframework.web.context.request.WebRequest` or * `java.servlet.http.PushBuilder` for the associated Servlet 4.0 push builder API,
`org.springframework.web.context.request.NativeWebRequest`. Allows for generic allowing for programmatic HTTP/2 resource pushes.
request parameter access as well as request/session attribute access, without ties * `java.security.Principal` (or a specific `Principal` implementation class if known),
to the native Servlet/Portlet API. containing the currently authenticated user.
* `org.springframework.http.HttpMethod` for the HTTP request method, represented as
Spring's `HttpMethod` enum.
* `java.util.Locale` for the current request locale, determined by the most specific * `java.util.Locale` for the current request locale, determined by the most specific
locale resolver available, in effect, the configured `LocaleResolver` / locale resolver available, in effect, the configured `LocaleResolver` /
`LocaleContextResolver` in an MVC environment. `LocaleContextResolver` in an MVC environment.
* `java.util.TimeZone` (Java 6+) / `java.time.ZoneId` (on Java 8) for the time zone * `java.util.TimeZone` (Java 6+) / `java.time.ZoneId` (Java 8+) for the time zone
associated with the current request, as determined by a `LocaleContextResolver`. associated with the current request, as determined by a `LocaleContextResolver`.
* `java.io.InputStream` / `java.io.Reader` for access to the request's content. * `java.io.InputStream` / `java.io.Reader` for access to the request's content.
This value is the raw InputStream/Reader as exposed by the Servlet API. This value is the raw InputStream/Reader as exposed by the Servlet API.
* `java.io.OutputStream` / `java.io.Writer` for generating the response's content. * `java.io.OutputStream` / `java.io.Writer` for generating the response's content.
This value is the raw OutputStream/Writer as exposed by the Servlet API. This value is the raw OutputStream/Writer as exposed by the Servlet API.
* `org.springframework.http.HttpMethod` for the HTTP request method.
* `java.security.Principal` containing the currently authenticated user.
* `@PathVariable` annotated parameters for access to URI template variables. See * `@PathVariable` annotated parameters for access to URI template variables. See
<<mvc-ann-requestmapping-uri-templates>>. <<mvc-ann-requestmapping-uri-templates>>.
* `@MatrixVariable` annotated parameters for access to name-value pairs located in * `@MatrixVariable` annotated parameters for access to name-value pairs located in
@ -2000,9 +2003,6 @@ The following code sample demonstrates how to get the value of the `JSESSIONID`
Type conversion is applied automatically if the target method parameter type is not Type conversion is applied automatically if the target method parameter type is not
`String`. See <<mvc-ann-typeconversion>>. `String`. See <<mvc-ann-typeconversion>>.
This annotation is supported for annotated handler methods in Servlet and Portlet
environments.
[[mvc-ann-requestheader]] [[mvc-ann-requestheader]]
==== Mapping request header attributes with the @RequestHeader annotation ==== Mapping request header attributes with the @RequestHeader annotation
@ -2050,9 +2050,6 @@ example a method parameter annotated with `@RequestHeader("Accept")` may be of t
`String` but also `String[]` or `List<String>`. `String` but also `String[]` or `List<String>`.
==== ====
This annotation is supported for annotated handler methods in Servlet and Portlet
environments.
[[mvc-ann-typeconversion]] [[mvc-ann-typeconversion]]
==== Method Parameters And Type Conversion ==== Method Parameters And Type Conversion
@ -3968,11 +3965,10 @@ the exception types listed as method arguments are used.
Much like standard controller methods annotated with a `@RequestMapping` annotation, the Much like standard controller methods annotated with a `@RequestMapping` annotation, the
method arguments and return values of `@ExceptionHandler` methods can be flexible. For method arguments and return values of `@ExceptionHandler` methods can be flexible. For
example, the `HttpServletRequest` can be accessed in Servlet environments and the example, the `HttpServletRequest` can be accessed in Servlet environments. The return
`PortletRequest` in Portlet environments. The return type can be a `String`, which is type can be a `String`, which is interpreted as a view name, a `ModelAndView` object,
interpreted as a view name, a `ModelAndView` object, a `ResponseEntity`, or you can also a `ResponseEntity`, or you can also add the `@ResponseBody` to have the method return
add the `@ResponseBody` to have the method return value converted with message value converted with message converters and written to the response stream.
converters and written to the response stream.