美文网首页
路径参数处理特殊字符&自定义参数注解处理器

路径参数处理特殊字符&自定义参数注解处理器

作者: GoddyWu | 来源:发表于2018-04-17 17:26 被阅读0次

    公司大佬说,restful API 的规范写法是通过路径参数(path variable)的方式获取请求参数。 但是常见一个问题,有些uid中包含特殊字符,例如:\, #, ,以及空格等等。所以采用base64加密解密的方式。
    所以后端需要encode uid去掉特殊字符后签发给前端,前端传输到后端后decode uid获取原始uid。
    因为前端需要频繁发送uid给后端,用工具方法来解析需要维护大量的代码,所以博主想到了通过自定义参数注解的方式。
    ⚠️注意:base64不支持中文。

    代码地址:https://gitlab.com/goddy-basic/basic_annotation

    Part 1 : 环境

    • spring boot 2.0 +
    • pom 包依赖
         <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!--小插件、非必要-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <!--切面-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
    
            <!--小插件-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
            <dependency>
                <groupId>commons-codec</groupId>
                <artifactId>commons-codec</artifactId>
                <version>1.10</version>
            </dependency>
        </dependencies>
    

    Part 2 : base64工具类的创建

    public class Base64Util {
    
        /**
         * 二进制数据编码为BASE64字符串
         * @param str 输入数据
         * @return
         */
        public static String encode(final String str) {
            try {
                return new String(Base64.encodeBase64(str.getBytes("UTF-8")), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 解密
         * @param str
         * @return
         */
        public static String decode(final String str) {
            try {
                return new String(Base64.decodeBase64(str.getBytes("UTF-8")), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    

    Part 3 : 注解声明 create annotation

    @Target({ElementType.PARAMETER})  #作用范围
    @Retention(RetentionPolicy.RUNTIME)  #生效时期
    @Documented  #文档化
    public @interface DecodeAnnotation {
    
    }
    

    Part 4 : 配置注解处理器 create annotation resolver

    @Slf4j  #非必要、lombok插件的注解
    @Component  
    public class DecodeResolver implements HandlerMethodArgumentResolver {
    
        /**
         * 用于判定是否需要处理该参数分解,返回true为需要,并会去调用下面的方法resolveArgument。
         * @param parameter
         * @return
         */
        @Override
        public boolean supportsParameter(MethodParameter parameter) {
    
            return parameter.hasParameterAnnotation(DecodeAnnotation.class);
        }
    
        /**
         * 真正用于处理参数分解的方法,返回的Object就是controller方法上的形参对象。
         * @param parameter
         * @param mavContainer
         * @param webRequest
         * @param binderFactory
         * @return
         * @throws Exception
         */
        @Nullable
        @Override
        public Object resolveArgument(MethodParameter parameter,
                                      @Nullable ModelAndViewContainer mavContainer,
                                      NativeWebRequest webRequest,
                                      @Nullable WebDataBinderFactory binderFactory) throws Exception {
    
            @SuppressWarnings("unchecked")
            Map<String, String> uriTemplateVars =
                    (Map<String, String>) webRequest.getAttribute(
                            HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
    
            LinkedHashMap hashMap = new LinkedHashMap<>(uriTemplateVars);
    
            # 获取到注解的值
            String value = hashMap.get( parameter.getParameterName() ).toString();
    
            return Base64Util.decode(value);
        }
    }
    

    Part 5 : 注册注解处理器 register resolver

    @Configuration
    public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    
        @Override
        protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    
            super.addArgumentResolvers(argumentResolvers);
    
            //注册decode的参数处理器
            argumentResolvers.add(new DecodeResolver());
        }
    }
    

    Part 6 : 验证

    • 通过Basic6Util的encode方法加密一段uid
      • 例如:wcm, a beautiful girl. r\ig/ht? =>
        d2NtLCBhIGJlYXV0aWZ1bCBnaXJsLiByXGlnL2h0PyA=
    • 测试controller
    • 解密结果

    酷不酷、?

    参考资料

    相关文章

      网友评论

          本文标题:路径参数处理特殊字符&自定义参数注解处理器

          本文链接:https://www.haomeiwen.com/subject/lykpkftx.html