如何将路径映射到多个控制器?

时间:2013-04-26 19:27:36

标签: spring spring-mvc

我目前正在开发一个基于弹簧的Web应用程序,并且有一个特殊的要求,似乎没有(至少不是开箱即用)由spring MVC提供。该应用程序为每个组织在他们自己的“公司”中的多个用户提供数据。一旦用户登录,我就能够确定他所属的公司。

应用程序本身由多个“模块”构建,每个模块都有自己的域对象,DAO,服务和控制器类。这个概念背后的想法是,我可以根据用户扩展某个控制器类(假设使用不同的服务类),这是我的问题。

由于我不想更改某些用户的请求路径,因此我正在寻找一种方法,如何根据发出请求的用户,使用控制器的不同实例来处理在某个请求路径上发出的请求。 我想出了为公司附加HTTP标头字段的想法 例如:

X-Company:12345

并让我的控制器配置如下:

@Controller
@RequestMapping(value="/foo/")
public class FooController { 
 // ...
}

@Controller
@RequestMapping(value="/foo" headers="X-Company=12345")
public class SpecialFooController extends FooController {
 // ...
}

然而这是不可能的,因为spring MVC将每个头文件(Content-Type和Accept除外)视为一种限制,因此在我的情况下,它将使用FooController而不是SpecialFooController处理所有请求,除非我添加“标题“对FooController的限制,这是不切实际的。 有没有办法如何自定义这种行为或某个方向可以指向我寻找?或者也许某人有另一个想法如何实现这一目标。我们将非常感激。 谢谢!

3 个答案:

答案 0 :(得分:0)

我不确定,但我认为您可以使用HandlerMapping执行此操作。看看documentation

答案 1 :(得分:0)

要采用您自己的建议,您可以在控制器方法中使用@RequestHeader注释:

@Controller
public class MyController {

    @RequestMapping("/someAction")
    public void myControllerMethod(@RequestHeader('X-Company-Id') String companyId) {

    }
}

或者您可以使用@PathVariable

@Controller
public class MyController {

    @RequestMapping("/{companyId}/someAction")
    public void myControllerMethod(@PathVariable("companyId") String companyId) {

    }
}

使用这种方法意味着每个公司实际上都是不同的网址,但如果您可以设置公司ID标头,我猜您也可以使用公司ID对URL进行后缀。

但也有其他可能性。您可以编写一个拦截器,将公司ID放在会话或请求变量中。然后,您不必将注释添加到每个控制器方法。您还可以为每个公司使用子域,但如果公司ID是随机字母数字字符串,那么这看起来不会太漂亮。例如:companyone.mydomain.comcompanytwo.mydomain.com

修改

如你所知,

@RequestMapping可以添加到控制器级别,所以你应该能够做到

@Controller
@RequestMapping("/controller/{companyId}")

作为基本网址,如果这是一个更好的选择。

答案 2 :(得分:0)

我能够通过使用自定义RequestCondition来满足要求。通过定义您自己的注释,可以放置在控制器的类型和方法级别。通过您自己的实现扩展RequestMappingHandlerMapping并覆盖getCustomTypeCondition()和getCustomMethodCondition()方法将控制器注释转换为您自己的RequestCondition。

当请求进入时,将评估自定义RequestCondition,然后将调用带注释的控制器(方法)来提供请求。但是这有缺点,需要删除servlet-context.xml文件并转而使用WebMvcConfigurationSupport类,以便能够使用自定义的RequestMappingHandlerMapping类。

还讨论了这个问题here

编辑: 使用此功能的一个很好的示例可以找到here