如何在Spring Remoting中设置动态头

时间:2019-01-08 14:02:34

标签: java spring-remoting

我们需要使用Spring Remoting调用Bean类,并在调用中设置动态标头。我们可以在HttpInvokerRequestExecutor中设置自定义HttpInvokerProxyFactoryBean并添加标题,但是如何设置为请求动态生成的动态标题?

In the Config class, declaring the HttpInvokerProxyFactoryBean
@Bean
@Qualifier("service")
public HttpInvokerProxyFactoryBean invoker() {
    HttpInvokerProxyFactoryBean invoker = new HttpInvokerProxyFactoryBean();
    invoker.setServiceUrl(url);
    invoker.setServiceInterface(Service.class);
    return invoker;
}

In the invoker class
@Autowired
Service service;

public void invoke(Bean bean) {
    service.process(bean);
}

1 个答案:

答案 0 :(得分:0)

使用弹簧远程处理已经有很长时间了,但是据我所知,我通过子类化SimpleHttpInvokerRequestExecutor找到了解决方案,当您未将任何自定义请求执行程序设置为HttpInvokerProxyFactoryBean时,这是默认设置。

恕我直言,您可以编写一个自定义请求执行程序,它可以设置自定义标头值,以及一个简单的帮助程序组件,该组件可以在下一个请求之前为执行程序设置动态提供的值。

CustomHttpInvokerRequestExecutor:

public class CustomHttpInvokerRequestExecutor extends SimpleHttpInvokerRequestExecutor {

private Map<String, String> headers;

public void setHeaders(Map<String, String> headers) {
    this.headers = headers;
}

@Override
protected void prepareConnection(HttpURLConnection connection, int contentLength) throws IOException {
    super.prepareConnection(connection, contentLength);

    if (headers != null) {
        // adding our custom headers
        for (String headerName : headers.keySet()) {
            connection.setRequestProperty(headerName, headers.get(headerName));
        }
        // do not want to persist headers for another request!
        headers.clear();
    }
}
}

CustomRemoteExecutor:

@Component
public class CustomRemoteExecutor {

@Autowired
private HttpInvokerProxyFactoryBean factoryBean;

/*
 * May be you should need a synchronized modifier here if there is possibility
 * of multiple threads access here at the same time
 */
public void executeInTemplate(Map<String, String> headers, Runnable task) {
    CustomHttpInvokerRequestExecutor executor = (CustomHttpInvokerRequestExecutor) factoryBean.getHttpInvokerRequestExecutor();
    executor.setHeaders(headers);
    task.run();
}

}

然后您可以通过以下方式使用它:

@Bean
@Qualifier("service")
public HttpInvokerProxyFactoryBean invoker() {
    HttpInvokerProxyFactoryBean invoker = new HttpInvokerProxyFactoryBean();
    invoker.setServiceUrl(testUrl);
    invoker.setServiceInterface(Service.class);
    // set our custom request executor
    CustomHttpInvokerRequestExecutor executor = new CustomHttpInvokerRequestExecutor();
    invoker.setHttpInvokerRequestExecutor(executor);

    return invoker;
}

@Autowired
CustomRemoteExecutor executor;

@Autowired
Service service;

public void invoke(Bean bean) {

    // when you need custom headers
    Map<String, String> headers = new HashMap<>();
    headers.put("CUSTOM_HEADER", "CUSTOM_VALUE");
    headers.put("CUSTOM_HEADER2", "CUSTOM_VALUE2");
    executor.executeInTemplate(headers, () -> service.process(bean));

}

这里有一个缺点,正如我在评论中也提到的那样,如果您在多线程环境(服务器到服务器的请求可能是)中执行代理服务客户端,则应考虑使用executeInTemplate方法synchronized

如果您的服务方法需要返回某个对象,那么除了我的答案,您还可以向CustomRemoteExecutor添加另一个帮助程序方法,并在需要返回某些内容时使用它。该方法在这里可以具有相同的名称,因此可以重载前一种方法,我认为这要好得多。

public <T> T executeInTemplate(Map<String, String> headers, Callable<T> task) {
    CustomHttpInvokerRequestExecutor executor = (CustomHttpInvokerRequestExecutor) factoryBean.getHttpInvokerRequestExecutor();
    executor.setHeaders(headers);

    try {
        return task.call();
    } catch (Exception e) {
        // it is better to log this exception by your preferred logger (log4j, logback
        // etc.)
        e.printStackTrace();
    }

    return null;
}

同样,您可以像下面这样使用:

@Autowired
CustomRemoteExecutor executor;

@Autowired
ISampleService service;

public void invoke(Bean bean) {

    // when you need custom headers
    Map<String, String> headers = new HashMap<>();
    headers.put("CUSTOM_HEADER", "CUSTOM_VALUE");
    headers.put("CUSTOM_HEADER2", "CUSTOM_VALUE2");

    // assume that service.returnSomething() method returns String
    String value = executor.executeInTemplate(headers, () -> service.returnSomething(bean));

}

希望有帮助。