【问题标题】:Create own class that transforms HTTP request to object in Spring?在 Spring 中创建自己的将 HTTP 请求转换为对象的类?
【发布时间】:2015-10-03 11:27:19
【问题描述】:

我想在我的 Spring MVC 应用程序中创建自己的类来转换 HTTP 请求并从这个 HTTP 请求初始化对象。我可以通过在方法中定义参数来创建对象,但我需要以自己的方式进行映射并手动进行。

如何使用我自己的实现来实现它,该实现将传递给 Spring 并无缝使用它?

更新1

提供Bohuslav Burghardt 的解决方案不起作用:

HTTP 状态 500 - 请求处理失败;嵌套异常是 java.lang.IllegalStateException:错误/BindingResult 参数是 预计在模型属性之后立即声明, @RequestBody 或它们适用的 @RequestPart 参数:public java.lang.String cz.deriva.derivis.api.oauth2.provider.controllers.OAuthController.authorize(api.oauth2.provider.domain.AuthorizationRequest,org.springframework.ui.Model,org.springframework.validation.BindingResult,javax.servlet.http. HttpServletRequest,javax.servlet.http.HttpServletResponse)

也许我应该提到我使用自己的验证器:

public class RequestValidator {

    public boolean supports(Class clazz) {
        return AuthorizationRequest.class.equals(clazz);
    }

    public void validate(Object obj, Errors e) {
        AuthorizationRequest request = (AuthorizationRequest) obj;
        if ("foobar".equals(request.getClientId())) {
            e.reject("clientId", "nomatch");
        }
    }

}

并在控制器中声明我的方法(请不要验证 - @Valid):

@RequestMapping(value = "/authorize", method = {RequestMethod.GET, RequestMethod.POST})
    public String authorize(
            @Valid AuthorizationRequest authorizationRequest,
            BindingResult result
    ) {

}

我的应用程序中有两个配置类。

@Configuration
@EnableAutoConfiguration
@EnableWebMvc
@PropertySource("classpath:/jdbc.properties")
public class ApplicationConfig {
}

@Configuration
@EnableWebMvc
public class WebappConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new AuthorizationRequestArgumentResolver());
    }

}

怎么了?

更新 2

问题在于参数BindingResult result,当我删除它时它可以工作。但是当出现一些错误时,我需要结果来处理它。

【问题讨论】:

  • 这个问题似乎是由于您不能将HandlerMethodArgumentResolver@Valid 注释一起使用。有关详细信息,请参阅this SO post。不幸的是,我从未在这种情况下亲自使用过它。也许该帖子中的一些信息会有所帮助。如果找到可行的解决方案,我将尝试对其进行调查并使用解决方案更新我的答案。
  • 是的,我可能不知道为什么我不能同时使用HandlerMethodArgumentResolver @Valid。迪基。
  • 您的代码中的authRequest 是什么?我假设将此代码添加到我的HandlerMethodArgumentResolver 实现中?
  • 删除了之前的评论。有关解决方法,请参阅更新的答案。 authRequest 应该是您的授权请求(从 foo 更新它以反映问题中的更改)。让我知道它是否有效

标签: spring spring-mvc httprequest


【解决方案1】:

如果我正确理解您的要求,您可以为此实施自定义 HandlerMethodArgumentResolver。有关实现细节,请参见下面的示例:


模型对象

public class AuthorizationRequestHolder {
    @Valid
    private AuthorizationRequest authorizationRequest;
    private BindingResult bindingResult;
    // Constructors, accessors omitted
}

解析器

public class AuthorizationRequestMethodArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return AuthorizationRequestHolder.class.isAssignableFrom(parameter.getParameterType());
    }

    @Override
    public Object resolveArgument(MethodParameter parameter,
                                  ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest,
                                  WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
        // Map the authorization request
        AuthorizationRequest authRequest = mapFromServletRequest(request);
        AuthorizationRequestHolder authRequestHolder = new AuthorizationRequestHolder(authRequest);
        // Validate the request
        if (parameter.hasParameterAnnotation(Valid.class)) {
            WebDataBinder binder = binderFactory.createBinder(webRequest, authRequestHolder, parameter.getParameterName());
            binder.validate();
            authRequestHolder.setBindingResult(binder.getBindingResult());
        }
        return authRequestHolder;
    }
}

配置

@Configuration
@EnableWebMvc
public class WebappConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new AuthorizationRequestMethodArgumentResolver());
    }
}

用法

@RequestMapping("/auth")
public void doSomething(@Valid AuthRequestHolder authRequestHolder) {
    if (authRequestHolder.getBindingResult().hasErrors()) {
        // Process errors
    }
    AuthorizationRequest authRequest = authRequestHolder.getAuthRequest();
    // Do something with the authorization request
}

编辑:更新了答案,解决了不支持使用 @ValidHandlerMethodArgumentResolver 参数的问题。

【讨论】:

  • 解析器类中的mapFromServletRequest(request) 是什么?这听起来像是解决这个问题的关键。
猜你喜欢
  • 1970-01-01
  • 2010-09-24
  • 2021-06-02
  • 1970-01-01
  • 2014-05-22
  • 1970-01-01
  • 2011-09-06
  • 2014-04-26
  • 2022-12-06
相关资源
最近更新 更多