Spring @Controller和RequestMapping根据给定的参数调用不同的服务

时间:2014-04-01 16:32:12

标签: java spring

我们假设我有这段代码:

@Controller
@RequestMapping("/something")
public class SomeController {
    @Autowired
    private SomeService aService;

    @RequestMapping("/doStuff")
    public void doStuff(@RequestParam("type") String type) {
        aService.doStuff();
    }
}

在我的应用程序中,我需要根据指定的类型调用特定服务。所有服务都实现相同的接口。如果我理解正确SomeService不能是一个接口。我可以使用服务工厂并在每次新请求完成时根据类型实例化服务,但这看起来效率不高。

或者,我可以为每种不同类型的服务使用不同的控制器(并在REST URI中对类型进行编码),但这意味着大量的代码重复,因为所有服务基本上都实现了相同的接口。

我的问题是,假设被调用的服务依赖于传递的参数,这种情况采用的最佳模式是什么?

3 个答案:

答案 0 :(得分:3)

与RC。的答案类似,不是使用Map并添加值,而是让Spring BeanFactory为您处理:

@Controller
@RequestMapping("/something")
public class SomeController {
    @Autowired
    private BeanFactory beanFactory;

    @RequestMapping("/doStuff")
    public void login(@RequestParam("type") String type) {
        SomeService aService = (SomeService)beanFactory.getBean(type);
        aService.doStuff();
    }
}

答案 1 :(得分:1)

你可以在这里使用地图,其中包括:

@Controller
@RequestMapping("/something")
public class SomeController {
    @Autowired
    private SomeService someService;

    @Autowired
    private SomeOtherService someOtherService;

    // ...

    private final Map<String, ServiceCommonInterface> serviceMap = new HashMap<>();

    @PostConstruct
    private void postConstruct() {
        serviceMap.put(typeForSomeService, someService);
        serviceMap.put(typeForSomeOtherService, someOtherService);
    }

    @RequestMapping("/doStuff")
    public void login(@RequestParam("type") String type) {
        // TODO: ensure type is correct (an enum might be handy here)
        serviceMap.get(type).doStuff();
    }
}

或者更好,正如评论中所述,您可以利用限定词:

@Controller
@RequestMapping("/something")
public class SomeController {
    @Autowired
    private ApplicationContext applicationContext;

    @RequestMapping("/doStuff")
    public void login(@RequestParam("type") String type) {
        // TODO: ensure type is a correct bean name
        applicationContext.getBean(type, ServiceCommonInterface.class).doStuff();
    }
}

答案 2 :(得分:0)

根据您希望支持的类型数量,我看到了两个选项。

1)如您所述,在工厂中自动装配,并根据需要懒洋洋地创建每项服务。如果服务是无状态的,您可以在创建后保留对该对象的引用,因此每个类型只需要创建一次。

2)在Spring Map中自动装配,其中键是您的类型,值是正确的服务。然后,当您收到类型时,可以为您的地图检索正确的服务impl。

例如,对于地图:http://www.mkyong.com/spring/spring-collections-list-set-map-and-properties-example/或参见How to inject a Map<String, List> in java springs?

这两个都要求您为您的服务创建一个您认为可能的界面。