【问题标题】:How to create request scoped web service port?如何创建请求范围的 Web 服务端口?
【发布时间】:2013-07-17 12:20:50
【问题描述】:

我有基于 Spring MVC 的 Web 应用程序,它调用 Web 服务。 Web 服务每次调用都需要基于 http 的身份验证。我在 applicationContext.xml 中保存 Web 服务代理配置:

<beans...

<bean id="paymentWebService"
      class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
    <property name="customProperties">
        <ref local="jaxwsCustomProperties"/>
    </property>
    <property name="serviceInterface" value="com.azercell.paymentgateway.client.PaymentGatewayWebService"/>
    <property name="wsdlDocumentUrl"
              value="#{config.wsdlDocumentUrl}"/>
    <property name="namespaceUri" value="http://webservice.paymentgateway.azercell.com/"/>
    <property name="serviceName" value="PaymentGatewayWebServiceImplService"/>
    <property name="portName" value="PaymentGatewayWebServiceImplPort"/>
</bean>

我的控制器中有 Web 服务端口的实例字段:

@Controller
public class PaymentController {

@Resource(name = "paymentWebService")
private PaymentGatewayWebService paymentPort;

@ModelAttribute
public void ajaxAttribute(WebRequest request, Model model) {
    UtilMethods.authenticationWebServicePort(paymentPort);
    ...
}
...

@RequestMapping(value = "/massPayment", method = RequestMethod.POST)
public String massPayment(@RequestParam String amount, @RequestParam MultipartFile file, Model model, Locale locale) {
    ...

    WebServiceResponse response = paymentPort.massPayment(UtilMethods.getNewRequestId()
             , fileUploader, UtilMethods.getAmountInCoins(amountBigDecimal), null);

    ...      

    return SpringView.MASS_PAYMENT.toString(ajaxRequest);
   }
}

UtilMethods.authenticationWebServicePort 的代码:

public static void authenticationWebServicePort(PaymentGatewayWebService paymentPort) {
    String username = (String) RequestContextHolder.currentRequestAttributes().getAttribute(USERNAME_SESSION_VARIABLE_NAME, RequestAttributes.SCOPE_SESSION);
    String password = (String) RequestContextHolder.currentRequestAttributes().getAttribute(PASSWORD_SESSION_VARIABLE_NAME, RequestAttributes.SCOPE_SESSION);
    BindingProvider prov = (BindingProvider) paymentPort;
    prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
    prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
}

由于控制器是单例对象,每次请求重叠时都会出现问题,如果错误地恰好是一个用户,可以使用属于另一个用户的用户名和密码的Web方法。

为了防止这种情况,我尝试在配置范围内设置 Web 服务端口请求,如下所示:

<bean id="paymentWebService"
  class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean" scope="request">

在这种情况下我得到了错误:

    SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChains': Cannot resolve reference to bean 'org.springframework.security.web.DefaultSecurityFilterChain#0' while setting bean property 'sourceList' with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.DefaultSecurityFilterChain#0': Cannot resolve reference to bean 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0' while setting constructor argument with key [2]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0': Cannot resolve reference to bean 'org.springframework.security.authentication.ProviderManager#0' while setting bean property 'authenticationManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.authentication.ProviderManager#0': Cannot resolve reference to bean 'org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0': FactoryBean threw exception on object creation; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.authenticationManager': Cannot resolve reference to bean 'myAuthenticationProvider' while setting constructor argument with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myAuthenticationProvider': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paymentWebService': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

如何创建请求范围的 Web 服务端口?

【问题讨论】:

    标签: java spring web-services spring-mvc jax-ws


    【解决方案1】:

    尝试将当前的http请求暴露给spring。只需在您的web.xml 中添加RequestContextListener

    <web-app>
    ...
    <listener>
      <listener-class>
          org.springframework.web.context.request.RequestContextListener
      </listener-class>
    </listener>
    ...
    </web-app>
    

    有关更多详细信息/选项,请参阅官方文档中的this entry

    编辑。 想想控制器和paymentPort 依赖之间的生命周期差异。控制器始终相同,但必须为每个新请求刷新 paymentPort。所以你不能继续直接注入它。您需要为每个请求获取新实例。您可以使用javax.inject.Provider 接口来完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-26
      • 2019-07-12
      • 2017-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-03
      • 2021-08-03
      相关资源
      最近更新 更多