001/* 002 * Copyright 2002-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.bind; 018 019import javax.servlet.ServletRequest; 020 021import org.springframework.beans.MutablePropertyValues; 022import org.springframework.validation.BindException; 023import org.springframework.web.multipart.MultipartRequest; 024import org.springframework.web.util.WebUtils; 025 026/** 027 * Special {@link org.springframework.validation.DataBinder} to perform data binding 028 * from servlet request parameters to JavaBeans, including support for multipart files. 029 * 030 * <p>See the DataBinder/WebDataBinder superclasses for customization options, 031 * which include specifying allowed/required fields, and registering custom 032 * property editors. 033 * 034 * <p>Can also be used for manual data binding in custom web controllers: 035 * for example, in a plain Controller implementation or in a MultiActionController 036 * handler method. Simply instantiate a ServletRequestDataBinder for each binding 037 * process, and invoke {@code bind} with the current ServletRequest as argument: 038 * 039 * <pre class="code"> 040 * MyBean myBean = new MyBean(); 041 * // apply binder to custom target object 042 * ServletRequestDataBinder binder = new ServletRequestDataBinder(myBean); 043 * // register custom editors, if desired 044 * binder.registerCustomEditor(...); 045 * // trigger actual binding of request parameters 046 * binder.bind(request); 047 * // optionally evaluate binding errors 048 * Errors errors = binder.getErrors(); 049 * ...</pre> 050 * 051 * @author Rod Johnson 052 * @author Juergen Hoeller 053 * @see #bind(javax.servlet.ServletRequest) 054 * @see #registerCustomEditor 055 * @see #setAllowedFields 056 * @see #setRequiredFields 057 * @see #setFieldMarkerPrefix 058 */ 059public class ServletRequestDataBinder extends WebDataBinder { 060 061 /** 062 * Create a new ServletRequestDataBinder instance, with default object name. 063 * @param target the target object to bind onto (or {@code null} 064 * if the binder is just used to convert a plain parameter value) 065 * @see #DEFAULT_OBJECT_NAME 066 */ 067 public ServletRequestDataBinder(Object target) { 068 super(target); 069 } 070 071 /** 072 * Create a new ServletRequestDataBinder instance. 073 * @param target the target object to bind onto (or {@code null} 074 * if the binder is just used to convert a plain parameter value) 075 * @param objectName the name of the target object 076 */ 077 public ServletRequestDataBinder(Object target, String objectName) { 078 super(target, objectName); 079 } 080 081 082 /** 083 * Bind the parameters of the given request to this binder's target, 084 * also binding multipart files in case of a multipart request. 085 * <p>This call can create field errors, representing basic binding 086 * errors like a required field (code "required"), or type mismatch 087 * between value and bean property (code "typeMismatch"). 088 * <p>Multipart files are bound via their parameter name, just like normal 089 * HTTP parameters: i.e. "uploadedFile" to an "uploadedFile" bean property, 090 * invoking a "setUploadedFile" setter method. 091 * <p>The type of the target property for a multipart file can be MultipartFile, 092 * byte[], or String. The latter two receive the contents of the uploaded file; 093 * all metadata like original file name, content type, etc are lost in those cases. 094 * @param request request with parameters to bind (can be multipart) 095 * @see org.springframework.web.multipart.MultipartHttpServletRequest 096 * @see org.springframework.web.multipart.MultipartFile 097 * @see #bind(org.springframework.beans.PropertyValues) 098 */ 099 public void bind(ServletRequest request) { 100 MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request); 101 MultipartRequest multipartRequest = WebUtils.getNativeRequest(request, MultipartRequest.class); 102 if (multipartRequest != null) { 103 bindMultipart(multipartRequest.getMultiFileMap(), mpvs); 104 } 105 addBindValues(mpvs, request); 106 doBind(mpvs); 107 } 108 109 /** 110 * Extension point that subclasses can use to add extra bind values for a 111 * request. Invoked before {@link #doBind(MutablePropertyValues)}. 112 * The default implementation is empty. 113 * @param mpvs the property values that will be used for data binding 114 * @param request the current request 115 */ 116 protected void addBindValues(MutablePropertyValues mpvs, ServletRequest request) { 117 } 118 119 /** 120 * Treats errors as fatal. 121 * <p>Use this method only if it's an error if the input isn't valid. 122 * This might be appropriate if all input is from dropdowns, for example. 123 * @throws ServletRequestBindingException subclass of ServletException on any binding problem 124 */ 125 public void closeNoCatch() throws ServletRequestBindingException { 126 if (getBindingResult().hasErrors()) { 127 throw new ServletRequestBindingException( 128 "Errors binding onto object '" + getBindingResult().getObjectName() + "'", 129 new BindException(getBindingResult())); 130 } 131 } 132 133}