【问题标题】:Injecting HttpRequest into SOAP Endpoint将 HttpRequest 注入 SOAP 端点
【发布时间】:2013-06-08 09:50:35
【问题描述】:

我正在寻找一种将 http 标头信息与 SOAP 消息一起转发到 Spring Endpoint 的方法,以便访问 IP 地址等详细信息。

相关web.xml:

<servlet>
    <servlet-name>SoapHost</servlet-name>
    <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
    <init-param>
        <param-name>transformWsdlLocations</param-name>
        <param-value>true</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>SoapHost</servlet-name>
    <url-pattern>/ws/*</url-pattern>
</servlet-mapping>

SoapHost-servlet.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:sws="http://www.springframework.org/schema/web-services"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/web-services                       
       http://www.springframework.org/schema/web-services/web-services-2.0.xsd">

    <!-- To detect @Endpoint -->
    <sws:annotation-driven />

    <!-- To detect @Service, @Component etc -->
    <context:component-scan base-package="za.co.mycee.soaphost" />

    <!-- To generate dynamic wsdl for SoapHost Services -->
    <sws:dynamic-wsdl 
        id="SoapHost"
        portTypeName="SoapHost" 
        locationUri="/ws/SoapHost"
        targetNamespace="http://www.mycee.co.za/SoapHost"> 
        <sws:xsd location="/WEB-INF/SoapHost.xsd" />
    </sws:dynamic-wsdl>

    <!-- Validate Request and Response -->
    <sws:interceptors>
        <bean id="MyCeeSoapHost" class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
            <property name="schema" value="/WEB-INF/SoapHost.xsd" />
            <property name="validateRequest" value="true" />
            <property name="validateResponse" value="true" />
        </bean>
    </sws:interceptors> 
</beans>

端点:

@Endpoint
public class ...Endpoint {

    @Autowired
    ...Service ...Service;

    @Autowired
    ...Service ...Service;

    @Autowired
    ...Service ...Service;

    @ResponsePayload
    @PayloadRoot(localPart = "...Request", namespace = "http://www.mycee.co.za/SoapHost")
    public ...Response do...(@RequestPayload ...Request request) {

        ...

        // get IP address here
            // get some other info from headers here

        ...


    }
}

我已尝试将其添加为参数之一:

    @ResponsePayload
    @PayloadRoot(localPart = "...Request", namespace = "http://www.mycee.co.za/SoapHost")
public ...Response do...(
        @RequestPayload ...Request request,  
        HttpServletRequest httpServletRequest) {

但这会在 XML 响应中返回错误:“没有端点适配器”和“您的端点是否使用 @Endpoint 注释,或者它是否实现了受支持的接口,如 MessageHandler 或 PayloadEndpoint”

【问题讨论】:

    标签: java spring jaxb jaxb2


    【解决方案1】:

    很抱歉没有直接回答你的问题,但是你为什么不把过滤器放在 servlet 之前呢?在此过滤器中,您可以将 IP 或任何其他信息存储在某个上下文对象中,例如 ThreadLocal 或类似对象。

    我相信,SOAP 应该对 IP 地址一无所知。这些是不同的抽象层。如果需要某些元信息,则 SOAP 根据设计在 SOAP 标头上运行。

    从 topic-starter 回复评论

    不,它不会破坏 Spring-WS 流程,因为将 servlet 放在过滤器后面是绝对正常的。过滤器是一个普通的javax.servlet.Filter

    按要求提供示例:

    对 Spring 示例稍作修改的端点

    @Endpoint
    public class FilteredEndpoint {
        @ResponsePayload
        @PayloadRoot(localPart = "HolidayRequest", namespace = "http://mycompany.com/hr/schemas")
        public void doRespose(@RequestPayload Element request) {
            System.out.println(Context.ip.get());
        }
    }
    

    信息存储在 Context 对象中。 Context 使用 ThreadLocal 来保存数据。它之所以有效,是因为每个请求都由单独的线程处理

    public class Context {
        public static ThreadLocal<String> ip = new ThreadLocal<String>();
    }
    

    最后过滤

    public class MyHttpFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {}
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            Context.ip.set(request.getRemoteAddr());
            chain.doFilter(request, response);
        }
    
        @Override
        public void destroy() {}
    }
    

    还有 web.xml

    <filter>
        <filter-name>httpfilter</filter-name>
        <filter-class>so.example.MyHttpFilter</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>httpfilter</filter-name>
        <url-pattern>/ws/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>SoapHost</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
        <init-param>
            <param-name>transformWsdlLocations</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>SoapHost</servlet-name>
        <url-pattern>/ws/*</url-pattern>
    </servlet-mapping>
    

    【讨论】:

    • 您如何建议我在不破坏 Spring-WS 流程的情况下设置过滤器?这个过滤器是 Spring 功能还是我可以在 servlet 级别实现的功能?一些示例代码/文档链接将不胜感激。
    猜你喜欢
    • 1970-01-01
    • 2014-04-15
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    相关资源
    最近更新 更多