我目前正在开发一个基于弹簧的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的限制,这是不切实际的。 有没有办法如何自定义这种行为或某个方向可以指向我寻找?或者也许某人有另一个想法如何实现这一目标。我们将非常感激。 谢谢!
答案 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.com
,companytwo.mydomain.com
修改强>
如你所知, @RequestMapping
可以添加到控制器级别,所以你应该能够做到
@Controller
@RequestMapping("/controller/{companyId}")
作为基本网址,如果这是一个更好的选择。
答案 2 :(得分:0)
我能够通过使用自定义RequestCondition来满足要求。通过定义您自己的注释,可以放置在控制器的类型和方法级别。通过您自己的实现扩展RequestMappingHandlerMapping并覆盖getCustomTypeCondition()和getCustomMethodCondition()方法将控制器注释转换为您自己的RequestCondition。
当请求进入时,将评估自定义RequestCondition,然后将调用带注释的控制器(方法)来提供请求。但是这有缺点,需要删除servlet-context.xml文件并转而使用WebMvcConfigurationSupport类,以便能够使用自定义的RequestMappingHandlerMapping类。
还讨论了这个问题here。
编辑: 使用此功能的一个很好的示例可以找到here。