All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cc.shacocloud.mirage.web.HandleMethodArgumentResolverComposite Maven / Gradle / Ivy

package cc.shacocloud.mirage.web;

import cc.shacocloud.mirage.utils.SelfSortList;
import cc.shacocloud.mirage.web.bind.WebDataBinderFactory;
import io.vertx.core.Future;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.OrderUtils;
import org.springframework.core.log.LogFormatUtils;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 通过委派给已注册 {@link HandleMethodArgumentResolver}的列表来解析方法参数。
 * 先前解析的方法参数将被缓存,以加快查找速度。
 */
public class HandleMethodArgumentResolverComposite implements HandleMethodArgumentResolver {

    private static final Log logger = LogFactory.getLog(HandleMethodArgumentResolverComposite.class);

    private final List argumentResolvers
            = new SelfSortList<>(n -> OrderUtils.getOrder(n.getClass(), Ordered.LOWEST_PRECEDENCE));

    private final Map argumentResolverCache =
            new ConcurrentHashMap<>(256);


    /**
     * 添加 {@link HandleMethodArgumentResolver}.
     */
    public HandleMethodArgumentResolverComposite addResolver(HandleMethodArgumentResolver resolver) {
        this.argumentResolvers.add(resolver);
        return this;
    }

    /**
     * 添加 {@link HandleMethodArgumentResolver HandlerMethodArgumentResolvers}.
     */
    public HandleMethodArgumentResolverComposite addResolvers(
            @Nullable HandleMethodArgumentResolver... resolvers) {

        if (resolvers != null) {
            Collections.addAll(this.argumentResolvers, resolvers);
        }
        return this;
    }

    /**
     * 添加 {@link HandleMethodArgumentResolver HandlerMethodArgumentResolvers}.
     */
    public HandleMethodArgumentResolverComposite addResolvers(
            @Nullable List resolvers) {

        if (resolvers != null && !resolvers.isEmpty()) {
            this.argumentResolvers.addAll(resolvers);
        }
        return this;
    }

    /**
     * 返回所有的解析程序的只读列表,或者返回空列表。
     */
    public List getResolvers() {
        return Collections.unmodifiableList(this.argumentResolvers);
    }

    /**
     * 清除已配置解析器的列表
     */
    public void clear() {
        this.argumentResolvers.clear();
    }


    /**
     * 循环已注册的 {@link HandleMethodArgumentResolver}
     * 寻找支持给定的 {@linkplain MethodParameter } 方法参数的处理器
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return getArgumentResolver(parameter) != null;
    }

    /**
     * 循环已注册的 {@link HandleMethodArgumentResolver}
     * 寻找支持给定的 {@linkplain MethodParameter } 方法参数的处理器处理执行
     *
     * @throws IllegalArgumentException 如果找不到合适的参数解析器则抛出例外!
     */
    @Override
    public Future resolveArgument(HttpRequest request,
                                          MethodParameter parameter,
                                          @Nullable WebDataBinderFactory binderFactory) {
        if (logger.isDebugEnabled()) {
            logger.debug("待解析的方法参数 : " + parameter.getParameterName());
        }

        HandleMethodArgumentResolver resolver = getArgumentResolver(parameter);
        if (resolver == null) {
            return Future.failedFuture(new IllegalArgumentException("不支持解析参数类型 [" + parameter.getParameterType().getName() + "]。" +
                    " 获取应该调用 supportsParameter 来判断是否支持!"));
        }

        if (logger.isDebugEnabled()) {
            logger.debug("匹配到参数解析处理器:" + resolver);
        }

        return resolver.resolveArgument(request, parameter, binderFactory)
                .onSuccess(body -> {
                    if (logger.isDebugEnabled()) {
                        logger.debug("方法参数 '" + parameter.getParameterName() + "' 解析数据为: [" + LogFormatUtils.formatValue(body, false) + "]");
                    }
                });
    }

    /**
     * 查找支持给定方法参数的注册{@link HandleMethodArgumentResolver}
     */
    @Nullable
    private HandleMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
        HandleMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
        if (result == null) {
            for (HandleMethodArgumentResolver resolver : this.argumentResolvers) {
                if (resolver.supportsParameter(parameter)) {
                    result = resolver;
                    this.argumentResolverCache.put(parameter, result);
                    break;
                }
            }
        }
        return result;
    }

}