all @SessionAttributes get exposed to the model before handler method execution; MultipartRequest is available as a mixin interface on (Native)WebRequest as well
This commit is contained in:
parent
e49869ea78
commit
9cb1338b94
|
|
@ -102,6 +102,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
import org.springframework.web.bind.support.WebArgumentResolver;
|
||||
import org.springframework.web.bind.support.WebBindingInitializer;
|
||||
|
|
@ -117,7 +118,6 @@ import org.springframework.web.servlet.mvc.AbstractController;
|
|||
import org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver;
|
||||
import org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping;
|
||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
import org.springframework.web.util.NestedServletException;
|
||||
|
||||
/**
|
||||
|
|
@ -293,6 +293,39 @@ public class ServletAnnotationControllerTests {
|
|||
assertEquals("", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionAttributeExposure() throws Exception {
|
||||
@SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
|
||||
@Override
|
||||
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
|
||||
GenericWebApplicationContext wac = new GenericWebApplicationContext();
|
||||
wac.registerBeanDefinition("controller", new RootBeanDefinition(MySessionAttributesController.class));
|
||||
wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(ModelExposingViewResolver.class));
|
||||
wac.refresh();
|
||||
return wac;
|
||||
}
|
||||
};
|
||||
servlet.init(new MockServletConfig());
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPage");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
HttpSession session = request.getSession();
|
||||
assertTrue(session.getAttribute("object1") != null);
|
||||
assertTrue(session.getAttribute("object2") != null);
|
||||
assertTrue(((Map) session.getAttribute("model")).containsKey("object1"));
|
||||
assertTrue(((Map) session.getAttribute("model")).containsKey("object2"));
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/myPage");
|
||||
request.setSession(session);
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertTrue(session.getAttribute("object1") != null);
|
||||
assertTrue(session.getAttribute("object2") != null);
|
||||
assertTrue(((Map) session.getAttribute("model")).containsKey("object1"));
|
||||
assertTrue(((Map) session.getAttribute("model")).containsKey("object2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void adaptedHandleMethods() throws Exception {
|
||||
doTestAdaptedHandleMethods(MyAdaptedController.class);
|
||||
|
|
@ -1029,16 +1062,6 @@ public class ServletAnnotationControllerTests {
|
|||
assertEquals(201, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseStatusRedirect() throws ServletException, IOException {
|
||||
initServlet(ResponseStatusRedirectController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/something");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals(201, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mavResolver() throws ServletException, IOException {
|
||||
@SuppressWarnings("serial") DispatcherServlet servlet = new DispatcherServlet() {
|
||||
|
|
@ -1248,6 +1271,25 @@ public class ServletAnnotationControllerTests {
|
|||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/myPage")
|
||||
@SessionAttributes({"object1", "object2"})
|
||||
public static class MySessionAttributesController {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public String get(Model model) {
|
||||
model.addAttribute("object1", new Object());
|
||||
model.addAttribute("object2", new Object());
|
||||
return "myPage";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public String post(@ModelAttribute("object1") Object object1) {
|
||||
//do something with object1
|
||||
return "myPage";
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class MyFormController {
|
||||
|
||||
|
|
@ -1592,6 +1634,20 @@ public class ServletAnnotationControllerTests {
|
|||
}
|
||||
}
|
||||
|
||||
private static class ModelExposingViewResolver implements ViewResolver {
|
||||
|
||||
public View resolveViewName(String viewName, Locale locale) throws Exception {
|
||||
return new View() {
|
||||
public String getContentType() {
|
||||
return null;
|
||||
}
|
||||
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) {
|
||||
request.getSession().setAttribute("model", model);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static class ParentController {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
|
|
@ -1769,17 +1825,6 @@ public class ServletAnnotationControllerTests {
|
|||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class ResponseStatusRedirectController {
|
||||
|
||||
@RequestMapping("/something")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public RedirectView handle(Writer writer) throws IOException {
|
||||
return new RedirectView("somelocation.html", false, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
public static class ModelAndViewResolverController {
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ import org.springframework.web.bind.support.WebBindingInitializer;
|
|||
import org.springframework.web.bind.support.WebRequestDataBinder;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.multipart.MultipartRequest;
|
||||
|
||||
/**
|
||||
* Support class for invoking an annotated handler method. Operates on the introspection results of a
|
||||
|
|
@ -127,21 +126,32 @@ public class HandlerMethodInvoker {
|
|||
Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
|
||||
try {
|
||||
boolean debug = logger.isDebugEnabled();
|
||||
for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
|
||||
Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
|
||||
if (attrValue != null) {
|
||||
implicitModel.addAttribute(attrName, attrValue);
|
||||
}
|
||||
}
|
||||
for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
|
||||
Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
|
||||
Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
|
||||
if (debug) {
|
||||
logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
|
||||
}
|
||||
Object attrValue = doInvokeMethod(attributeMethodToInvoke, handler, args);
|
||||
String attrName = AnnotationUtils.findAnnotation(attributeMethodToInvoke, ModelAttribute.class).value();
|
||||
if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
|
||||
continue;
|
||||
}
|
||||
Object attrValue = doInvokeMethod(attributeMethodToInvoke, handler, args);
|
||||
if ("".equals(attrName)) {
|
||||
Class resolvedType = GenericTypeResolver.resolveReturnType(
|
||||
attributeMethodToInvoke, handler.getClass());
|
||||
attrName = Conventions.getVariableNameForReturnType(
|
||||
attributeMethodToInvoke, resolvedType, attrValue);
|
||||
}
|
||||
implicitModel.addAttribute(attrName, attrValue);
|
||||
if (!implicitModel.containsAttribute(attrName)) {
|
||||
implicitModel.addAttribute(attrName, attrValue);
|
||||
}
|
||||
}
|
||||
Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
|
||||
if (debug) {
|
||||
|
|
@ -394,15 +404,15 @@ public class HandlerMethodInvoker {
|
|||
if (paramName.length() == 0) {
|
||||
paramName = getRequiredParameterName(methodParam);
|
||||
}
|
||||
Object paramValue = null;
|
||||
if (webRequest.getNativeRequest() instanceof MultipartRequest) {
|
||||
paramValue = ((MultipartRequest) webRequest.getNativeRequest()).getFile(paramName);
|
||||
}
|
||||
Object paramValue = webRequest.getFile(paramName);
|
||||
if (paramValue == null) {
|
||||
String[] paramValues = webRequest.getParameterValues(paramName);
|
||||
if (paramValues != null) {
|
||||
if (paramValues != null && !paramType.isArray()) {
|
||||
paramValue = (paramValues.length == 1 ? paramValues[0] : paramValues);
|
||||
}
|
||||
else {
|
||||
paramValue = paramValues;
|
||||
}
|
||||
}
|
||||
if (paramValue == null) {
|
||||
if (StringUtils.hasText(defaultValue)) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -19,7 +19,6 @@ package org.springframework.web.bind.support;
|
|||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.multipart.MultipartRequest;
|
||||
|
||||
|
|
@ -100,12 +99,8 @@ public class WebRequestDataBinder extends WebDataBinder {
|
|||
*/
|
||||
public void bind(WebRequest request) {
|
||||
MutablePropertyValues mpvs = new MutablePropertyValues(request.getParameterMap());
|
||||
if (request instanceof NativeWebRequest) {
|
||||
Object nativeRequest = ((NativeWebRequest) request).getNativeRequest();
|
||||
if (nativeRequest instanceof MultipartRequest) {
|
||||
MultipartRequest multipartRequest = (MultipartRequest) request;
|
||||
bindMultipartFiles(multipartRequest.getFileMap(), mpvs);
|
||||
}
|
||||
if (request instanceof MultipartRequest) {
|
||||
bindMultipartFiles(((MultipartRequest) request).getFileMap(), mpvs);
|
||||
}
|
||||
doBind(mpvs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -17,14 +17,19 @@
|
|||
package org.springframework.web.context.request;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.faces.context.ExternalContext;
|
||||
import javax.faces.context.FacesContext;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartRequest;
|
||||
|
||||
/**
|
||||
* {@link WebRequest} adapter for a JSF {@link javax.faces.context.FacesContext}.
|
||||
|
|
@ -34,6 +39,9 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
public class FacesWebRequest extends FacesRequestAttributes implements NativeWebRequest {
|
||||
|
||||
private MultipartRequest multipartRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new FacesWebRequest adapter for the given FacesContext.
|
||||
* @param facesContext the current FacesContext
|
||||
|
|
@ -41,6 +49,9 @@ public class FacesWebRequest extends FacesRequestAttributes implements NativeWeb
|
|||
*/
|
||||
public FacesWebRequest(FacesContext facesContext) {
|
||||
super(facesContext);
|
||||
if (facesContext.getExternalContext().getRequest() instanceof MultipartRequest) {
|
||||
this.multipartRequest = (MultipartRequest) facesContext.getExternalContext().getRequest();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -105,7 +116,6 @@ public class FacesWebRequest extends FacesRequestAttributes implements NativeWeb
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
public String getDescription(boolean includeClientInfo) {
|
||||
ExternalContext externalContext = getExternalContext();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
|
@ -123,6 +133,44 @@ public class FacesWebRequest extends FacesRequestAttributes implements NativeWeb
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator<String> getFileNames() {
|
||||
if (this.multipartRequest == null) {
|
||||
return (Iterator<String>) Collections.EMPTY_SET.iterator();
|
||||
}
|
||||
return this.multipartRequest.getFileNames();
|
||||
}
|
||||
|
||||
public MultipartFile getFile(String name) {
|
||||
if (this.multipartRequest == null) {
|
||||
return null;
|
||||
}
|
||||
return this.multipartRequest.getFile(name);
|
||||
}
|
||||
|
||||
public List<MultipartFile> getFiles(String name) {
|
||||
if (this.multipartRequest == null) {
|
||||
return null;
|
||||
}
|
||||
return this.multipartRequest.getFiles(name);
|
||||
}
|
||||
|
||||
public Map<String, MultipartFile> getFileMap() {
|
||||
if (this.multipartRequest == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return this.multipartRequest.getFileMap();
|
||||
}
|
||||
|
||||
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
|
||||
if (this.multipartRequest == null) {
|
||||
return new LinkedMultiValueMap<String, MultipartFile>();
|
||||
}
|
||||
return this.multipartRequest.getMultiFileMap();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FacesWebRequest: " + getDescription(true);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.springframework.web.context.request;
|
||||
|
||||
import org.springframework.web.multipart.MultipartRequest;
|
||||
|
||||
/**
|
||||
* Extension of the {@link WebRequest} interface, exposing the
|
||||
* native request and response objects in a generic fashion.
|
||||
|
|
@ -26,7 +28,7 @@ package org.springframework.web.context.request;
|
|||
* @author Juergen Hoeller
|
||||
* @since 2.5.2
|
||||
*/
|
||||
public interface NativeWebRequest extends WebRequest {
|
||||
public interface NativeWebRequest extends WebRequest, MultipartRequest {
|
||||
|
||||
/**
|
||||
* Return the underlying native request object, if available.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -17,7 +17,9 @@
|
|||
package org.springframework.web.context.request;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
|
@ -25,8 +27,12 @@ import javax.servlet.http.HttpServletResponse;
|
|||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartRequest;
|
||||
|
||||
/**
|
||||
* {@link WebRequest} adapter for an {@link javax.servlet.http.HttpServletRequest}.
|
||||
|
|
@ -41,6 +47,8 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
|||
private static final String HEADER_LAST_MODIFIED = "Last-Modified";
|
||||
|
||||
|
||||
private MultipartRequest multipartRequest;
|
||||
|
||||
private HttpServletResponse response;
|
||||
|
||||
private boolean notModified = false;
|
||||
|
|
@ -52,6 +60,9 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
|||
*/
|
||||
public ServletWebRequest(HttpServletRequest request) {
|
||||
super(request);
|
||||
if (request instanceof MultipartRequest) {
|
||||
this.multipartRequest = (MultipartRequest) request;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -60,7 +71,7 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
|||
* @param response current HTTP response (for automatic last-modified handling)
|
||||
*/
|
||||
public ServletWebRequest(HttpServletRequest request, HttpServletResponse response) {
|
||||
super(request);
|
||||
this(request);
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +144,6 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
|||
return getRequest().isSecure();
|
||||
}
|
||||
|
||||
|
||||
public boolean checkNotModified(long lastModifiedTimestamp) {
|
||||
if (lastModifiedTimestamp >= 0 && !this.notModified &&
|
||||
(this.response == null || !this.response.containsHeader(HEADER_LAST_MODIFIED))) {
|
||||
|
|
@ -155,7 +165,6 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
|||
return this.notModified;
|
||||
}
|
||||
|
||||
|
||||
public String getDescription(boolean includeClientInfo) {
|
||||
HttpServletRequest request = getRequest();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
|
@ -177,6 +186,44 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator<String> getFileNames() {
|
||||
if (this.multipartRequest == null) {
|
||||
return (Iterator<String>) Collections.EMPTY_SET.iterator();
|
||||
}
|
||||
return this.multipartRequest.getFileNames();
|
||||
}
|
||||
|
||||
public MultipartFile getFile(String name) {
|
||||
if (this.multipartRequest == null) {
|
||||
return null;
|
||||
}
|
||||
return this.multipartRequest.getFile(name);
|
||||
}
|
||||
|
||||
public List<MultipartFile> getFiles(String name) {
|
||||
if (this.multipartRequest == null) {
|
||||
return null;
|
||||
}
|
||||
return this.multipartRequest.getFiles(name);
|
||||
}
|
||||
|
||||
public Map<String, MultipartFile> getFileMap() {
|
||||
if (this.multipartRequest == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return this.multipartRequest.getFileMap();
|
||||
}
|
||||
|
||||
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
|
||||
if (this.multipartRequest == null) {
|
||||
return new LinkedMultiValueMap<String, MultipartFile>();
|
||||
}
|
||||
return this.multipartRequest.getMultiFileMap();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ServletWebRequest: " + getDescription(true);
|
||||
|
|
|
|||
Loading…
Reference in New Issue