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

公司大佬说,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 包依赖
     
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            org.projectlombok
            lombok
            true
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
        
            org.springframework.boot
            spring-boot-starter-aop
        

        
        
            org.projectlombok
            lombok
            true
        

        
        
            commons-codec
            commons-codec
            1.10
        
    

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 uriTemplateVars =
                (Map) 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 argumentResolvers) {

        super.addArgumentResolvers(argumentResolvers);

        //注册decode的参数处理器
        argumentResolvers.add(new DecodeResolver());
    }
}

Part 6 : 验证

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

酷不酷、?

参考资料

  • github - 官方 - PathVariableMapMethodArgumentResolver
  • 开源中国 - _Core的博客
  • csdn - ACMer_AK的博客
  • csdn - fabuler的博客 - 用Base64加密数据解决json传输数据中特殊字符问题

你可能感兴趣的:(路径参数处理特殊字符&自定义参数注解处理器)