1. 程式人生 > 其它 >SpringBoot自定義逗號分隔轉集合註解

SpringBoot自定義逗號分隔轉集合註解

註解

package com.ccsa.common.core.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author hsn
 * 2021/10/13
 * SpiltList
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface SpiltList {
    //分割符
    String value() default ",";
}

自定義解析器

package com.ccsa.common.data.resolver;

import cn.hutool.core.util.StrUtil;
import com.ccsa.common.core.annotation.SpiltList;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Get方法裡將逗號轉成list
 * 1,2,3 ----> [1,2,3]
 * @author hsn
 * 2021/10/13
 * SplitListHandlerMethodArgumentResolver
 */
@Slf4j
public class SplitListHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
    /**
     * Whether the given {@linkplain MethodParameter method parameter} is
     * supported by this resolver.
     * 當引數裡有SpiltList註解則呼叫該解析器
     * @param parameter the method parameter to check
     * @return {@code true} if this resolver supports the supplied parameter;
     * {@code false} otherwise
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(SpiltList.class);
    }

    /**
     * Resolves a method parameter into an argument value from a given request.
     * A {@link ModelAndViewContainer} provides access to the model for the
     * request. A {@link WebDataBinderFactory} provides a way to create
     * a {@link WebDataBinder} instance when needed for data binding and
     * type conversion purposes.
     * 解析過程
     * @param parameter     the method parameter to resolve. This parameter must
     *                      have previously been passed to {@link #supportsParameter} which must
     *                      have returned {@code true}.
     * @param mavContainer  the ModelAndViewContainer for the current request
     * @param webRequest    the current request
     * @param binderFactory a factory for creating {@link WebDataBinder} instances
     * @return the resolved argument value, or {@code null} if not resolvable
     * @throws Exception in case of errors with the preparation of argument values
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        String requestParameter = webRequest.getParameter(Objects.requireNonNull(parameter.getParameterName()));
        SpiltList spiltList = parameter.getParameterAnnotation(SpiltList.class);
        assert requestParameter != null;
        assert spiltList != null;
        //獲取list裡的泛型
        ParameterizedType parameterizedType = (ParameterizedType) parameter.getParameter().getParameterizedType();
        if (parameterizedType.getActualTypeArguments().length == 0){
            throw new RuntimeException("not found parameterizedType in List<>");
        }
        Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];
        if (!(actualTypeArgument instanceof Class)){
            throw new RuntimeException("get class fail");
        }
        if (StrUtil.isBlank(requestParameter)){
            return Collections.emptyList();
        }
        Class<?> type =(Class<?>) actualTypeArgument;
        String[] split = requestParameter.split(spiltList.value());
        //呼叫泛型的valueOf方法,所以只支援基本的包裝型別,這裡也可以根據自己的需要進行處理
        Method valueOfMethod = type.getMethod("valueOf", String.class);
        return Arrays.stream(split).map(item -> {
            try {
                return valueOfMethod.invoke(null, item);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }).collect(Collectors.toList());
    }

}

配置

package com.ccsa.common.data.mvc;

import com.ccsa.common.data.resolver.SplitListHandlerMethodArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * @author hsn
 * 2021/10/13
 * WebConfig
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new SplitListHandlerMethodArgumentResolver());
    }
}

使用

    @GetMapping("analyze")
    public R analyze(@Size(min = 1,message = "專業id不能為空") @SpiltList List<Integer> majors) {
        return R.ok(reviewService.analyse(majors));
    }