spring-gateway整合spring-Integration,链式处理请求体相关

背景

物联网比较核心的就是处理上报,并处理不同协议的问题。当然没有通用的思路,只有适合业务的场景。

http适用

mqtt不做相关,相关设备都是适用http协议做出数据发送。

url与handlerFilter配置

不使用controller配置对url路径进行管理。
其实和使用controller是同一种效果,使用controller也是需要策略模式,对不同协议进行处理。

配置需要用到HttpRequestHandlingMessagingGateWay。
HttpRequestHandlingMessagingGateWay 源码文档解释中,可以直接注册为bean。 同理serverlet
可以处理请求信息。
实现HttpRequstHandler接口。

HttpRequestHandlerServlet

public class HttpRequestHandlerServlet extends HttpServlet {

	@Nullable
	private HttpRequestHandler target;


	@Override
	public void init() throws ServletException {
		WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
		this.target = wac.getBean(getServletName(), HttpRequestHandler.class);
	}


	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		Assert.state(this.target != null, "No HttpRequestHandler available");

		LocaleContextHolder.setLocale(request.getLocale());
		try {
			this.target.handleRequest(request, response);
		}
		catch (HttpRequestMethodNotSupportedException ex) {
			String[] supportedMethods = ex.getSupportedMethods();
			if (supportedMethods != null) {
				response.setHeader("Allow", StringUtils.arrayToDelimitedString(supportedMethods, ", "));
			}
			response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, ex.getMessage());
		}
		finally {
			LocaleContextHolder.resetLocaleContext();
		}
	}

}

然后是配置代码

 @Bean
    public HttpRequestHandlingMessagingGateway networkingOrganizationExtendInbound() {
        return HttpInboundGatewayBuilder.newInstance().pathPatterns(
                ProtocolUrlEnum.COMPANY_EXTEND.URI).httpMethod(HttpMethod.POST).requestPayloadType(SzdAccessDataDTO.class)
                .requestChannel(this.szdOrganizationExtendMessageRequestChannel)
                .errorChannel(this.szdHttpGlobalErrorChannel).build();
    }

pathPatterns指定路径,相当于requestMapping中的value
requstPayLoadType指定消息体的实例化类型
requestChannel定义消息处理通道
errorChannel出错后消息处理通道

private DirectChannel szdBaseMessageChannelbuild() {
        DirectChannel channel = new DirectChannel();
        // 权限拦截
        channel.addInterceptor(this.permissionInterceptor);
        // 平台对接状态
        channel.addInterceptor(this.dockingStatusInterceptor);
        // 消息包体大小拦截
        channel.addInterceptor(this.packetSizeInterceptor);
        // 绑定消息所属消息协议
        channel.addInterceptor(this.protocolInterceptor);
        // HTTP接入数据处理链
        channel.subscribe(this.szdhttpRequestHandlerChain);
        return channel;
    }

spring-Integration现在使用的确实比较少。相关文章也较少。spring实战第六版中对相应组件有所介绍。
interceptor 实现ChannelInterceptor接口就可以
subscribe()方法需要传入httpHandler

   public MessageHandlerChain szdhttpRequestHandlerChain() {
        // 创建消息处理链类
        MessageHandlerChain chain = new MessageHandlerChain();
        // 消息处理类集合
        List<MessageHandler> handlers = new ArrayList<>();
        // 原数据平台编号填充处理器
        handlers.add(this.szdFillPlatformCodeActivator);
        // 消息响应处理器
        handlers.add(this.szdHttpResponseActivator);
        chain.setHandlers(handlers);
        return chain;
    }

这里使用MessageHandlerChain集成一下
添加的两个Activator 为框架基础的服务激活器。可以将消息发送给handler实现。

   @Bean
    public ServiceActivatingHandler szdHttpResponseActivator(MessageChannel rawDataMsgChannel,
                                                             ProtocolContext protocolContext) {
        SzdSyncProtocolCheckRespProcessor processor =
                new SzdSyncProtocolCheckRespProcessor(rawDataMsgChannel, protocolContext);
        return new ServiceActivatingHandler(processor);
    }

代码中是再次创建了一个通道,spring-intergration本身就是为集成流的处理方案。
一开始配置了一个通道,是http接受请求的通道,此时在通道内再次集成另一个通道.

 @Bean
    public DirectChannel rawDataMsgChannel(AccessDataCountInterceptor accessDataCountInterceptor,
                                           AccessDataCovertToJsonInterceptor accessDataCovertToJsonInterceptor, @Qualifier("rawDataKafkaOutbound") MessageHandler rawDataKafkaOutbound) {
        DirectChannel channel = new DirectChannel();
        channel.addInterceptor(accessDataCountInterceptor);
        channel.addInterceptor(accessDataCovertToJsonInterceptor);
        channel.subscribe(rawDataKafkaOutbound);
        return channel;
    }

跟前面的代码异曲同工,并再次subscribe 一个kafka消息通道.

@Bean
    public KafkaProducerMessageHandler<String, String> rawDataKafkaOutbound(
            KafkaTemplate<String, String> kafkaTemplate) {
        KafkaProducerMessageHandler<String, String> handler =
                new KafkaProducerMessageHandler<>(kafkaTemplate);
        // 将发送失败的消息发送到失败通道
        handler.setSendFailureChannel(this.rawDataSendToKafkaFailureChannel);
        return handler;
    }

如何发送到响应的kafka Topic

KafkaProducerMessageHandler 有相应说明

producerRecord = createProducerRecord(message);
MessageHeaders messageHeaders = message.getHeaders();
String topic = this.topicExpression != null ?
				this.topicExpression.getValue(this.evaluationContext, message, String.class)
				: messageHeaders.get(KafkaHeaders.TOPIC, String.class);
		if (topic == null) {
			topic = this.kafkaTemplate.getDefaultTopic();
		}

这个只能
所以设置kafka topic需要在请求体的请求头中设置 KafakaHeader.TOPIC

集成流从通道流转完成。

集成流 入站协议和出站协议都可以自行配置,处理的多了,就多几个handler.

还有自定义xml,作为协议模板的这次写不完了,打包出bug, 一直在解决。
结束,下班。假期愉快。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值