【问题标题】:Choose @ResponsBody Model in @RestController dependent on @RequestParam在依赖于@RequestParam 的@RestController 中选择@ResponsBody 模型
【发布时间】:2016-11-22 09:54:35
【问题描述】:

我们的 Spring Boot RestController 中有以下方法:

@RequestMapping(value = USER_LOGIN_URL, method = { RequestMethod.POST })
    public ResponseEntity<TokenResponse> localAuth(
            @Validated @RequestBody(required = true) AuthRequest authRequest,
            @RequestParam(required = true) String provider) {
        // ... voodoo magic ...
        return ResponseEntity.status(HttpStatus.OK).body(new TokenResponse("abc"));
    }

我们想使用不同的请求模型(这里@RequestBody 包含一个自定义的AuthRequest 对象),具体取决于在我们的例子中名为provider@RequestParam 的值。 Spring MVC 有 option to forward requests 不幸的是这不适用于 @RestController :(

有什么想法吗?

编辑 - 也许这能更好地展示我们想要实现的目标:

if (provider.equals("providerA")) {
    @Validated @RequestBody(required = true) AuthRequest authRequest
} else {
   @Validated @RequestBody(required = true) SomeSpecialAuthRequest authRequest
}

【问题讨论】:

  • “我们想使用不同的请求模型”请详细说明。
  • 我自己发现的。答案贴在下面。

标签: spring spring-mvc spring-boot


【解决方案1】:

@RequestMapping 注释有一个params 属性,在这种情况下可以非常方便,正如您在我的示例中看到的那样。

这里你看到当提供者查询字符串等于"someProvider"时触发的控制器方法:

@RequestMapping(value = "/auth/login", method = { RequestMethod.POST }, 
params = "provider=someProvider")
    public ResponseEntity<TokenResponse> localAuth(
            @Validated @RequestBody(required = true) AuthRequest authRequest,
            @RequestParam(required = true) String provider)  { ... }

这里是当查询参数等于"someOtherProvider" 时调用的控制器方法。在这种情况下,我正在使用另一个名为 SomeSpecialAuthRequest 的请求模型。

@RequestMapping(value = "/auth/login", method = { RequestMethod.POST }, 
params = "provider=someOtherProvider")
    public ResponseEntity<TokenResponse> localAuth(
            @Validated @RequestBody(required = true) SomeSpecialAuthRequest authRequest,
            @RequestParam(required = true) String provider)  { ... }

【讨论】:

  • 第二个例子还有AuthRequestrequired = true 无论如何都是默认值。您是否在新方法中使用provider
  • 参数是如何传递的?它是标题的一部分吗?
  • @Srikanta 这是一个类似http://example.com/auth?provider=someProvider的查询字符串
【解决方案2】:

如果只是为了登录,你可以再做一件事

创建一个过滤器,它将拦截 url 并决定要执行哪种类型的身份验证。

在 Filter 的 doFilter() 方法中,您可以根据您的自定义提供程序截取 url 并重定向。

@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        if (httpServletRequest.getRequestURI().equals("/login") && httpServletRequest.getParameter("provider").equals("provider1")) {
            httpServletResponse.sendRedirect("auth/login1");
        } else if (httpServletRequest.getRequestURI().equals("/login") && httpServletRequest.getParameter("provider").equals("provider2")) {
            httpServletResponse.sendRedirect("auth/login2");
        }else {
            chain.doFilter(request,response);
        }
    }

并制作不同的控制器方法来处理身份验证。

还记得将@Order(1) 添加到您的过滤器中。

【讨论】:

  • httpServletResponse.sendRedirect("auth/login1");result 会产生新的 GET 请求吗?
  • 是的,但它会解决你的问题,这也是spring security成功和失败处理程序的工作方式
  • 谢谢。我会看看这个。
猜你喜欢
  • 2016-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-23
  • 2016-10-30
  • 1970-01-01
  • 1970-01-01
  • 2012-04-01
相关资源
最近更新 更多