Site Overlay

创建自定义注解映射自定义参数

一般从前台接收到的参数都是JSON之类的通用格式,或者通过@RequestBody自动映射实体类。但是如果想要将拿到的数据直接自动转换成一个非普通类实体,而不是拿到以后自己再封装。这时候最好就自定义一个注解,针对所需要的格式自动封装。

实现方法如下:

首先声明一个注解:(Dson为一个基于JSON格式的自定义二次封装类,对JSON格式进行空参判断,忽略引号,可以简易方法直接取值)

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestDson {
}

接下来写一个映射器,相当于上面自定义注解的实现方法。继承 AbstractMessageReaderArgumentResolver 类,实现其中两个方法,supportsParameter是判断该注解是否可以生效,true的话进入下面实现方法中进行实现,实现方法中resolveArgument进行处理后就传到@RequestBody中过一遍后传到Controller中进行逻辑处理。

package com.miracle.qaodo.config;


import com.miracle.dson.Dson;
import com.miracle.qaodo.annotation.RequestDson;Q
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.BindingContext;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.result.method.annotation.AbstractMessageReaderArgumentResolver;
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author Diuut
 * @Date 2020/4/28  14:45
 */
@Configuration
@EnableWebFlux
@Slf4j
public class WebConfig implements WebFluxConfigurer {

    @Override
    public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
        List<HttpMessageReader<?>> readers = new ArrayList<HttpMessageReader<?>>();
        //添加Http消息编解码器
        readers.add(new DecoderHttpMessageReader<>(new Jackson2JsonDecoder()));
        //消息编解码器与Resolver绑定
        configurer.addCustomResolver(new DsonHandlerArgumentResolver(readers));
    }

    static class DsonHandlerArgumentResolver extends AbstractMessageReaderArgumentResolver {


        public DsonHandlerArgumentResolver(List<HttpMessageReader<?>> readers) {

            super(readers);
        }

        protected DsonHandlerArgumentResolver(List<HttpMessageReader<?>> messageReaders, ReactiveAdapterRegistry adapterRegistry) {
            super(messageReaders, adapterRegistry);
        }

        @Override
        public boolean supportsParameter(MethodParameter parameter) {
            boolean hasParameterAnnotation = parameter.hasParameterAnnotation(RequestDson.class);
//            log.info("supportsParameter: {}", hasParameterAnnotation);
            return hasParameterAnnotation;//绑定注解
        }

        @Override
        public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange) {
            RequestDson annotation = parameter.getParameterAnnotation(RequestDson.class);
            Assert.state(annotation != null, "No KIMBody annotation");
            ServerHttpRequest request = exchange.getRequest();

            if ("POST".equals(request.getMethodValue())) {
                return request.getBody()
                        .collectList()
                        .map(list -> {
                            StringBuffer str = new StringBuffer();
                            for (DataBuffer buf : list) {
                                str.append(buf.toString(StandardCharsets.UTF_8));
                                DataBufferUtils.release(buf);
                            }
                            log.info("post请求 request:{}", str);
                            String decode = "";
                            try {
                                int flag = 5;       //decode重试解码次数
                                String decodeStr = "";
                                String temp=str.toString();
                                do {
                                    flag--;
                                    decodeStr=decode;
                                    decode = URLDecoder.decode(temp, "UTF-8");
//                                    log.info("post请求 decode:{}", decode);
                                    temp=decode;
                                    if (decode.contains("+")) {
                                        break;
                                    }
                                } while (!StringUtils.pathEquals(decodeStr, decode) && flag > 0);
                                //URLDecoder.decode会导致+ 转为 空格
                            } catch (Exception e) {
                                log.warn(str+"url转码失败");
                            }
                            log.info("post请求 decode:{}", decode);
                            return Dson.fromString(decode);
                        });

            } else if ("GET".equals(request.getMethodValue())) {
                MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
//                log.info("queryParams:{}", queryParams);
                Map<String, String> map = queryParams.toSingleValueMap();
                log.info("get请求 request:{}", map);
                Dson dson = null;
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    if (entry.getKey().startsWith("{")) {
                        Dson tmp = Dson.fromMap(entry.getKey());
                        if (dson == null) {
                            dson = Dson.fromMap("{}");
                        }
                        dson.putAll(tmp._Value());
                    } else if (entry.getKey().startsWith("[")) {
                        Dson tmp = Dson.fromArray(entry.getKey());
                        if (dson == null) {
                            dson = Dson.fromArray("[]");
                        }
                        dson.addAll(tmp._Value());
                    } else {
                        if (dson == null) {
                            dson = Dson.fromMap("{}");
                        }
                        dson.put(entry.getKey(), entry.getValue());
                    }
                }
                if (dson == null) {
                    dson = Dson.fromMap("{}");
                }
                return Mono.just(dson);
            }
            return null;
        }
    }

}

使用方法的话同在@RequestBody的位置替换为@RequestDson,即可从前台直接传Dson格式的数据到后台中直接使用。 以上。

发表回复

您的电子邮箱地址不会被公开。

A beliving heart is your magic My heart
欢迎来到Diuut的个人博客,这里是我的一些零零碎碎的知识汇总,希望有能帮到你的内容。 | 蜀ICP备2021011635号-1 | Copyright © 2024 Diuut. All Rights Reserved.