Package net.paoding.rose.web.paramresolver

Source Code of net.paoding.rose.web.paramresolver.ServletRequestDataBinder

/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.paoding.rose.web.paramresolver;

import java.util.Date;

import javax.servlet.ServletRequest;

import net.paoding.rose.web.paramresolver.ResolverFactoryImpl.DateEditor;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.PropertyValue;
import org.springframework.validation.AbstractPropertyBindingResult;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.util.WebUtils;

/**
* Special {@link org.springframework.validation.DataBinder} to perform
* data binding from servlet request parameters to JavaBeans, including
* support for multipart files.
*
* <p>
* See the DataBinder/WebDataBinder superclasses for customization options,
* which include specifying allowed/required fields, and registering custom
* property editors.
*
* <p>
* Used by Spring Web MVC's BaseCommandController and
* MultiActionController. Note that BaseCommandController and its
* subclasses allow for easy customization of the binder instances that
* they use through overriding <code>initBinder</code>.
*
* <p>
* Can also be used for manual data binding in custom web controllers: for
* example, in a plain Controller implementation or in a
* MultiActionController handler method. Simply instantiate a
* ServletRequestDataBinder for each binding process, and invoke
* <code>bind</code> with the current ServletRequest as argument:
*
* <pre class="code"> MyBean myBean = new MyBean(); // apply binder to
* custom target object ServletRequestDataBinder binder = new
* ServletRequestDataBinder(myBean); // register custom editors, if desired
* binder.registerCustomEditor(...); // trigger actual binding of request
* parameters binder.bind(request); // optionally evaluate binding errors
* Errors errors = binder.getErrors(); ...</pre>
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see #bind(javax.servlet.ServletRequest)
* @see #registerCustomEditor
* @see #setAllowedFields
* @see #setRequiredFields
* @see #setFieldMarkerPrefix
* @see org.springframework.web.servlet.mvc.BaseCommandController#initBinder
*/
public class ServletRequestDataBinder extends WebDataBinder {

    private String prefix;

    /**
     * Create a new ServletRequestDataBinder instance, with default object
     * name.
     *
     * @param target the target object to bind onto (or <code>null</code>
     *        if the binder is just used to convert a plain parameter
     *        value)
     * @see #DEFAULT_OBJECT_NAME
     */
    public ServletRequestDataBinder(Object target) {
        super(target);
    }

    /**
     * Create a new ServletRequestDataBinder instance.
     *
     * @param target the target object to bind onto (or <code>null</code>
     *        if the binder is just used to convert a plain parameter
     *        value)
     * @param objectName the name of the target object
     */
    public ServletRequestDataBinder(Object target, String objectName) {
        super(target, objectName);
        prefix = objectName + '.';
    }

    /**
     * Return the internal BindingResult held by this DataBinder, as
     * AbstractPropertyBindingResult.
     */
    @Override
    protected AbstractPropertyBindingResult getInternalBindingResult() {
        AbstractPropertyBindingResult bindingResult = super.getInternalBindingResult();

        // by rose
        PropertyEditorRegistry registry = bindingResult.getPropertyEditorRegistry();
        registry.registerCustomEditor(Date.class, new DateEditor(Date.class));
        registry.registerCustomEditor(java.sql.Date.class, new DateEditor(java.sql.Date.class));
        registry.registerCustomEditor(java.sql.Time.class, new DateEditor(java.sql.Time.class));
        registry.registerCustomEditor(java.sql.Timestamp.class, new DateEditor(
                java.sql.Timestamp.class));
        return bindingResult;
    }

    /**
     * Bind the parameters of the given request to this binder's target,
     * also binding multipart files in case of a multipart request.
     * <p>
     * This call can create field errors, representing basic binding errors
     * like a required field (code "required"), or type mismatch between
     * value and bean property (code "typeMismatch").
     * <p>
     * Multipart files are bound via their parameter name, just like normal
     * HTTP parameters: i.e. "uploadedFile" to an "uploadedFile" bean
     * property, invoking a "setUploadedFile" setter method.
     * <p>
     * The type of the target property for a multipart file can be
     * MultipartFile, byte[], or String. The latter two receive the
     * contents of the uploaded file; all metadata like original file name,
     * content type, etc are lost in those cases.
     *
     * @param request request with parameters to bind (can be multipart)
     * @see org.springframework.web.multipart.MultipartHttpServletRequest
     * @see org.springframework.web.multipart.MultipartFile
     * @see #bindMultipartFiles
     * @see #bind(org.springframework.beans.PropertyValues)
     */
    public void bind(ServletRequest request) {
        MutablePropertyValues mpvs = new MutablePropertyValues(WebUtils.getParametersStartingWith(
                request, prefix));
        if (request instanceof MultipartHttpServletRequest) {
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            bindMultipartFiles(multipartRequest.getFileMap(), mpvs);
        }
        doBind(mpvs);
    }

    @Override
    protected void doBind(MutablePropertyValues mpvs) {
        // book.author.name的设置要自动使book.author设置一个author进去
        PropertyValue[] pvArray = mpvs.getPropertyValues();
        MutablePropertyValues newMpvs = null;
        for (int i = 0; i < pvArray.length; i++) {
            PropertyValue pv = pvArray[i];
            String propertyName = pv.getName();
            int dot = propertyName.indexOf('.');
            while (dot != -1) {
                String field = propertyName.substring(0, dot);
                if (getPropertyAccessor().isWritableProperty(field) && !mpvs.contains(field)) {
                    Class<?> fieldType = getPropertyAccessor().getPropertyType(field);
                    if (newMpvs == null) {
                        newMpvs = new MutablePropertyValues();
                    }
                    newMpvs.addPropertyValue(field, BeanUtils.instantiateClass(fieldType));
                }
                dot = propertyName.indexOf('.', dot + 1);
            }
        }
        if (newMpvs == null) {
            super.doBind(mpvs);
        } else {
            newMpvs.addPropertyValues(mpvs);
            super.doBind(newMpvs);
        }
    }

    /**
     * Treats errors as fatal.
     * <p>
     * Use this method only if it's an error if the input isn't valid. This
     * might be appropriate if all input is from dropdowns, for example.
     *
     * @throws ServletRequestBindingException subclass of ServletException
     *         on any binding problem
     */
    public void closeNoCatch() throws ServletRequestBindingException {
        if (getBindingResult().hasErrors()) {
            throw new ServletRequestBindingException("Errors binding onto object '"
                    + getBindingResult().getObjectName() + "'", new BindException(
                    getBindingResult()));
        }
    }

}
TOP

Related Classes of net.paoding.rose.web.paramresolver.ServletRequestDataBinder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.