为了账号安全,请及时绑定邮箱和手机立即绑定

如何为带请求参数和不带请求参数的请求定义不同的 Spring MVC 请求处理程序?

如何为带请求参数和不带请求参数的请求定义不同的 Spring MVC 请求处理程序?

天涯尽头无女友 2023-03-31 17:05:58
Spring MVC 有没有办法为没有请求参数的请求和有请求参数的请求定义不同的处理程序?有一个简单的控制器:@RestController@RequestMapping("/strategies")public class StrategyController {    ...    @GetMapping    public List<Strategy> getAll() {        return service.getBeans().stream()            .map(mapper::toDto)            .collect(toList());    }    @GetMapping    public List<Strategy> search(StrategyFilter filter) {        return service.search(new StrategySearchSpecification(                filter.getCode(),                filter.getName(),                filter.getType()            )).stream()            .map(mapper::toDto)            .collect(toList());    }}我想要getAll()方法来处理没有请求参数的请求: /strategies我想要search(StrategyFilter filter)方法来处理带有请求参数的请求: /strategies?name=SomeName&type=SomeType似乎无法通过params属性来区分这种情况,因为可以省略@GetMapping任何属性。StrategyFilter在此配置中,我得到一个明显的错误:Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'strategyController' method public List<Strategy> StrategyController.getAll() to {[/strategies],methods=[GET]}: There is already 'strategyController' bean method public List<Strategy> StrategyController.search(StrategyFilter) mapped.当然也可以这样写:@GetMappingpublic List<Strategy> get(StrategyFilter filter) {    return noFilterProvided(filter) ? getAll() : search(filter);}但是每次过滤器的属性数量发生变化时,都需要更改“noFilterProvided(StrategyFilter filter)”。
查看完整描述

2 回答

?
翻过高山走不出你

TA贡献1875条经验 获得超3个赞

Spring 框架使用基于点的匹配。它从可用的匹配中选择最高的匹配。通过标准越多的人得分越高。如果您在一个匹配中定义了请求的查询参数,那么当参数存在时它将被接受。其他情况另说。


要定义请求的参数,请将它们作为直接属性传递,而不是作为 StrategyFilter 属性传递。在缺少参数的情况下,这样的实例初始化也成功(这些属性不会被初始化,它们保持默认状态:“”/0/false)。所以会出现模棱两可的匹配错误。


最后:使用直接属性而不是 StrategyFilter。


您设计的其他问题是直接 StrategySearchSpecification 实例化。它不是以这种方式进行单元测试的。将其定义为 Spring 组件。


@Component

@Getter // Lombok annotation to generate getter methods

@Setter // Lombok annotation to generate setter methods

public class StrategySearchSpecification

{

  private CODE_TYPE code;

  private String name;

  private TYPE_TYPE type;

}

并将其作为参数注入(正确的实现/模拟)并使用它的设置方法。


@RestController

@RequestMapping("/strategies")

public class StrategyController {

    ...


    @GetMapping

    public List<Strategy> getAll() {

        return service.getBeans().stream()

            .map(mapper::toDto)

            .collect(toList());

    }


    @GetMapping

    public List<Strategy> search(@RequestParam CODE_TYPE code, @RequestParam String name, @RequestParam TYPE_TYPE type, StrategySearchSpecification specification ) {

        specification.setCode( code );

        specification.setName( name );

        specification.setType( type );

        return service.search( specification

            )).stream()

            .map(mapper::toDto)

            .collect(toList());

    }

}


查看完整回答
反对 回复 2023-03-31
?
心有法竹

TA贡献1866条经验 获得超5个赞

如果StrategyFilter具有属性nameand type,这应该有效:


@RestController

@RequestMapping("/strategies")

public class StrategyController {

    ...


    @GetMapping

    public List<Strategy> getAll() {

        return service.getBeans().stream()

            .map(mapper::toDto)

            .collect(toList());

    }


    @GetMapping("{name}/{type}")

    public List<Strategy> search(StrategyFilter filter) {

        return service.search(new StrategySearchSpecification(

                filter.getCode(),

                filter.getName(),

                filter.getType()

            )).stream()

            .map(mapper::toDto)

            .collect(toList());

    }

}


查看完整回答
反对 回复 2023-03-31
  • 2 回答
  • 0 关注
  • 107 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信