整体思路
重写所有接口,功能保持一致,完全按照新的项目模式来。
单独设置模块处理老接口的兼容,兼容老接口的请求参数和响应结果。
针对第二点,在头信息中指定 X-VERSION
,值为 1.0.0
的时候表示老接口,新接口用 2.0.0
,以后往上迭代。
请求参数转换
由于是针对接口的兼容,所以我们需要知道指定的控制器方法,以及针对该接口的参数转换。
遇到的问题
用拦截器方案,可以在拦截器中知道转发的控制器方法,但是无法改写inputStream。
用过滤器方案,可以改写请求参数,但是无法知道具体转发到的控制器方法。
最后利用spring的HandlerMethodArgumentResolver,可以自定义控制器参数的转换。
RequestParamResolver
首先我们定义一个特殊的参数注解,这个注解中包含一个参数handler,handler是我们最终处理参数转换的实体类。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface RequestParamResolver {
Class> handler();
}
然后在指定的控制器方法中给参数加上自定义的注解,并且指定一个对应的handler,表示我准备用这个handler去处理这个接口的参数兼容。
@PostMapping(value = "/ui")
public ResponseEntity> insert(HttpServletRequest request,
@RequestParamResolver(handler = AppUiBodyHandler.class) AppUiDTO appUiDTO)
throws EcarxException {
...
}
ParamsResolver
然后到我们的核心地带,实现一个HandlerMethodArgumentResolver去处理自定义的参数转换流程。
public class ParamsResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestParamResolver.class);
}
@Override
@Nullable
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
RequestParamResolver resolvedRequestParam = parameter.getParameterAnnotation(RequestParamResolver.class);
Class> paramType = parameter.getParameterType();
String body = getRequestBody(webRequest);
if(resolvedRequestParam != null) {
RequestParamHandler handler = (RequestParamHa