将请求参数转换为泛型类

Posted

技术标签:

【中文标题】将请求参数转换为泛型类【英文标题】:Convert request params to generic class 【发布时间】:2013-12-07 14:51:08 【问题描述】:

我正在寻找有关 Spring Controller 定义的帮助。我尝试了几次谷歌,但没有找到如何实现我的目标的直接解释。

我想定义通用控制器:

public abstract class AbstractController<E extends AbstractEntity, 
                                         P extends IRequestParams> 
  @RequestMapping(method = GET)
  public @ResponseBody
  abstract List<E> list(@RequestParam P params);

之后我会声明如下控制器:

public class CatController 
          extends AbstractController<Cat, ICatSearchParams> 
  @RequestMapping(method = GET)
  public @ResponseBody
  List<Cat> list(@RequestParam ICatSearchParams params) 
    // do something and return list of results
  

我有以通用方式将@RequestParam Map&lt;String, String[]&gt; params 转换为IRequestParams 的服务。我可以通过 Spring 解析泛型类型。

但我不知道如何插入 Spring 以自动将请求参数转换为我的参数接口并在方法调用中使用它。我希望这种转换在配置后对开发人员是透明的。

提前感谢您的帮助!

【问题讨论】:

我不确定完整的构造最终是否会起作用,因为我不知道spring ConverterWebArgrumentResolver 是否可以正确解析泛型类型。 【参考方案1】:

您可以实现HandlerMethodArgumentResolver,但您需要自己实现完整的对象映射。

注册很简单:

<mvc:annotation-driven>
      <mvc:argument-resolvers>
           <bean class="YourMethodArgumentResolver"/>         
      </mvc:argument-resolvers>
 </mvc:annotation-driven>

另一种方法是实现自定义Converter。主要问题是,转换器只能转换一个字符串/请求属性。但是,如果您的 IRequestParams 在 http-request 中有多个值,这将不起作用。 - 另一方面,如果您的转换器旨在通过其 ID 加载实体,那么 Converter 是要走的路。

如果您想构建一种自动注册转换器的方法,请查看此答案 https://***.com/a/13778502/280244

【讨论】:

【参考方案2】:

我已经完成了问题的目标。 @Ralph's 的回答非常非常很有帮助,但确切地说,我会写出更多需要的内容。

我创建了@987654321@,将其命名为CustomHandlerMethodArgumentResolver。要将所有请求参数映射到结果对象,我必须将控制器方法的参数标记为@RequestBody

这还不够,因为 Spring 的默认 HandlerMethodArgumentResolvers 尝试先映射它,而我的解析器没有执行。但是this 回答指出了如何为我的解析器设置优先级。

@PostConstruct 不起作用(不知道为什么),所以我修改了我的 @Configuration 类以实现 ApplicationListener&lt;ContextRefreshedEvent&gt;。代码如下:

@Override
public void onApplicationEvent(ContextRefreshedEvent event) 
  RequestMappingHandlerAdapter adapter = 
      event.getApplicationContext().getBean(
          RequestMappingHandlerAdapter.class);
  CustomHandlerMethodArgumentResolver resolver =
      event.getApplicationContext().getBean(
          CustomHandlerMethodArgumentResolver.class);

  List<HandlerMethodArgumentResolver> argumentResolvers = 
      new ArrayList<>(
          adapter.getArgumentResolvers().getResolvers());
  List<HandlerMethodArgumentResolver> customResolvers = 
      adapter.getCustomArgumentResolvers();
  argumentResolvers.remove(resolver);
  argumentResolvers.add(0, resolver);
  adapter.setArgumentResolvers(argumentResolvers);

当然CustomHandlerMethodArgumentResolver.supportsParameter(MethodParameter)会检查实际情况是否应该以自定义或默认方式处理 - 这取决于要求。

感谢@Ralph 闪电般的快速帮助!

【讨论】:

以上是关于将请求参数转换为泛型类的主要内容,如果未能解决你的问题,请参考以下文章

将返回值转换为泛型类型

使用反射为泛型类创建构造函数

将返回值转换为泛型类型

如何在 typescript 中为泛型类编写扩展作为 getter

如何将“任何不可为空的类型”指定为泛型类型参数约束?

JAVA中的泛型类是啥东西?