我的目的是在REST方法中使用自定义批注,该批注会自动以某种所需的形式转换参数。类似于:
Response get(@StringNormalizer(UPPERCASE) String myparam)
我知道有一个HttpServletRequestWrapper类,可用于拦截和修改输入URI:
@WebFilter(urlPatterns="/*")
public class ApiOriginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
HttpServletRequest wrappedRequest = new MyWrappedRequest(request);
chain.doFilter(wrappedRequest, response);
}
}
public class MyWrappedRequest extends HttpServletRequestWrapper
{
@Override
public String getQueryString() {
// return modified query
}
}
但是我不知道如何检索方法参数的注释(在上面的示例中为StringNormalizer类)。
任何提示?
您有两种方法可以做到这一点。首先,对我来说最好的解决方法是使用Argument Resolver
。
参数解析器是实现HandlerMethodArgumentResolver
接口的类。您必须实现的抽象方法使您可以获取参数类型和参数可选注释,并通过访问原始数据来构建它。
然后,您应该扩展实现WebMvcConfigurer
的Configuration类,并重写addArgumentResolvers
以将新创建的类包含在声明为形式参数的列表中。
通过这种配置,Spring将为所有控制器自动拦截所有声明的参数,这些参数与您在Argument Resolver类中编写的条件相匹配,并将应用您开发的变换逻辑。
实现目标的第二个解决方案是实施面向方面的编程,这种情况在这种情况下结构过度,但非常适合此类目的。Spring使您可以使用AspectJ实现Aspects。正如我之前所说,我认为对您来说最好的解决方案是使用参数解析器。
这在标准JAX-RS中非常简单。您需要一个ContainerRequestFilter可以转换您的参数。类似于:
@Provider
@Priority(Priorities.USER)
public class RequestLoggingFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
UriInfo uriInfo = requestContext.getUriInfo();
MultivaluedMap<String, String> pathParameters = uriInfo.getPathParameters();
for( String nextKey: pathParameters.keySet() ) {
List<String> oldValues = pathParameters.get(nextKey);
List<String> newValues = new ArrayList<>();
for (String nextValue : oldValues) {
newValues.add(nextValue.toUpperCase());
}
// replace old parameters with new
pathParameters.put(nextKey, newValues);
}
}
}
请注意,此大写字母每个路径参数。如果这不是您想要的,则需要检查密钥。因此,例如,如果您用于REST服务的URL模式类似@Path("getCustomer/{customerId}")
,则密钥将为customerId
,而值将是URL所具有的值。
最后,如果您也想处理查询参数,则可以使用getQueryParameters
复制此循环,并在其中获得MultivaluedMap
。