Camel - Rest: request/response data type judgement

Camel - Rest: request/response data type judgement

binding mode

org.apache.camel.reifier.rest.RestBindingReifier#createRestBindingAdvice

public RestBindingAdvice createRestBindingAdvice() throws Exception {
        RestConfiguration config = CamelContextHelper.getRestConfiguration(camelContext, definition.getComponent());

        // these options can be overridden per rest verb
        String mode = config.getBindingMode().name();
        if (definition.getBindingMode() != null) {
            mode = parse(RestBindingMode.class, definition.getBindingMode()).name();
        }
		// omit
        if ("off".equals(mode)) {
            // binding mode is off, so create a off mode binding processor
            return new RestBindingAdvice(
                    camelContext, null, null, null, null,
                    parseString(definition.getConsumes()), parseString(definition.getProduces()), mode, skip, validation, cors,
                    corsHeaders,
                    definition.getDefaultValues(), definition.getRequiredBody() != null ? definition.getRequiredBody() : false,
                    definition.getRequiredQueryParameters(), definition.getRequiredHeaders());
        }

        // setup json data format
        DataFormat json = null;
        DataFormat outJson = null;
        if (mode.contains("json") || "auto".equals(mode)) {
            String name = config.getJsonDataFormat();
            if (name != null) {
                // must only be a name, not refer to an existing instance
                Object instance = lookupByName(name);
                if (instance != null) {
                    throw new IllegalArgumentException(
                            "JsonDataFormat name: " + name + " must not be an existing bean instance from the registry");
                }
            } else {
                name = "json-jackson";
            }
            // this will create a new instance as the name was not already
            // pre-created
            json = camelContext.resolveDataFormat(name);
            outJson = camelContext.resolveDataFormat(name);

            if (json != null) {
                setupJson(
                        config,
                        parseString(definition.getType()), definition.getTypeClass(),
                        parseString(definition.getOutType()), definition.getOutTypeClass(),
                        json, outJson);
            }
        }

        // setup xml data format
        DataFormat jaxb = null;
        DataFormat outJaxb = null;
        if (mode.contains("xml") || "auto".equals(mode)) {
            String name = config.getXmlDataFormat();
            if (name != null) {
                // must only be a name, not refer to an existing instance
                Object instance = lookupByName(name);
                if (instance != null) {
                    throw new IllegalArgumentException(
                            "XmlDataFormat name: " + name + " must not be an existing bean instance from the registry");
                }
            } else {
                name = "jaxb";
            }
            // this will create a new instance as the name was not already
            // pre-created
            jaxb = camelContext.resolveDataFormat(name);
            outJaxb = camelContext.resolveDataFormat(name);

            // is xml binding required?
            if (mode.contains("xml") && jaxb == null) {
                throw new IllegalArgumentException("XML DataFormat " + name + " not found.");
            }

            if (jaxb != null) {
                // to setup JAXB we need to use camel-jaxb
                camelContext.adapt(ExtendedCamelContext.class).getRestBindingJaxbDataFormatFactory().setupJaxb(
                        camelContext, config,
                        parseString(definition.getType()), definition.getTypeClass(),
                        parseString(definition.getOutType()), definition.getOutTypeClass(),
                        jaxb, outJaxb);
            }
        }

        return new RestBindingAdvice(
                camelContext, json, jaxb, outJson, outJaxb,
                parseString(definition.getConsumes()), parseString(definition.getProduces()),
                mode, skip, validation, cors, corsHeaders,
                definition.getDefaultValues(), definition.getRequiredBody() != null ? definition.getRequiredBody() : false,
                definition.getRequiredQueryParameters(), definition.getRequiredHeaders());
    }

unmarshal

org.apache.camel.processor.RestBindingAdvice#unmarshal

判定请求内容格式的逻辑

boolean isXml = false;
boolean isJson = false;

// 判定contentType,如果contentType包含xml,设置isXml = true, 如果contentType包含json,设置isJson = true
String contentType = ExchangeHelper.getContentType(exchange);
if (contentType != null) {
    isXml = contentType.toLowerCase(Locale.ENGLISH).contains("xml");
    isJson = contentType.toLowerCase(Locale.ENGLISH).contains("json");
}
// 如果content type没有告诉我们是xml还是json,则根据consumers配置检查请求内容类型;
// 如果consumers包含xml,设置 isXml = true; 如果consumers包含json,设置 isJson = true;
if (!isXml && !isJson) {
    isXml = consumes != null && consumes.toLowerCase(Locale.ENGLISH).contains("xml");
    isJson = consumes != null && consumes.toLowerCase(Locale.ENGLISH).contains("json");
}

// 如果请求内容是DataTypeAware类型,则设置data type
if (exchange.getContext().isUseDataType()) {
    if (exchange.getIn() instanceof DataTypeAware && (isJson || isXml)) {
        ((DataTypeAware) exchange.getIn()).setDataType(new DataType(isJson ? "json" : "xml"));
    }
}

// 只有bindMode为auto或xml时,isXml的值才有效
// 只有bindMode为auto或json时,isJson的值才有效
isXml &= bindingMode.equals("auto") || bindingMode.contains("xml");
isJson &= bindingMode.equals("auto") || bindingMode.contains("json");

// 如果此时 isXml、isJson的值均为false,则根据bindMode获取请求内容格式
// 如果bindMode为auto或xml时,isXml = true
// 如果bindMode为auto或json时,isJson = true
if (!isJson && !isXml) {
    isXml = bindingMode.equals("auto") || bindingMode.contains("xml");
    isJson = bindingMode.equals("auto") || bindingMode.contains("json");
}

// 如果 isXml和isJson 的值均为true,则根据请求内容判定请求格式,如果是以<开始,则 isXml = true; 否则 isXml = true;
if (exchange.getIn().getBody() != null) {
    // okay we have a binding mode, so need to check for empty body as that can cause the marshaller to fail
    // as they assume a non-empty body
    if (isXml || isJson) {
        // we have binding enabled, so we need to know if there body is empty or not
        // so force reading the body as a String which we can work with
        body = MessageHelper.extractBodyAsString(exchange.getIn());
        if (body != null) {
            if (exchange.getIn() instanceof DataTypeAware) {
                ((DataTypeAware) exchange.getIn()).setBody(body, new DataType(isJson ? "json" : "xml"));
            } else {
                exchange.getIn().setBody(body);
            }

            if (isXml && isJson) {
                // we have still not determined between xml or json, so check the body if its xml based or not
                isXml = body.startsWith("<");
                isJson = !isXml;
            }
        }
    }
}

marshal

boolean isXml = false;
boolean isJson = false;

// 如果accept包含xml,isXml = true; 如果accept包含json, isXml = true;
String accept = (String) state.get(STATE_KEY_ACCEPT);
if (accept != null) {
    isXml = accept.toLowerCase(Locale.ENGLISH).contains("xml");
    isJson = accept.toLowerCase(Locale.ENGLISH).contains("json");
}
// 如果无法判定响应类型,根据content type判定响应类型,如果content type包含xml,isXml = true; 如果content type包含json,isJson = ture
if (!isXml && !isJson) {
    String contentType = ExchangeHelper.getContentType(exchange);
    if (contentType != null) {
        isXml = contentType.toLowerCase(Locale.ENGLISH).contains("xml");
        isJson = contentType.toLowerCase(Locale.ENGLISH).contains("json");
    }
}
// 如果无法判定响应类型,则根据配置producers判断响应类型,如果producers包含xml,isXml = ture; 如果producers包含json,isJson = true
if (!isXml && !isJson) {
    isXml = produces != null && produces.toLowerCase(Locale.ENGLISH).contains("xml");
    isJson = produces != null && produces.toLowerCase(Locale.ENGLISH).contains("json");
}

// 只有在binding mode允许的情况下,isXml和isJson的值才能生效(当binding mode关闭的情况下isXml、isJson的值仍然生效)
if (bindingMode != null) {
    isXml &= bindingMode.equals("off") || bindingMode.equals("auto") || bindingMode.contains("xml");
    isJson &= bindingMode.equals("off") || bindingMode.equals("auto") || bindingMode.contains("json");

    // 如果此时尚未判定响应内容的值,则根据binding mode的值进行判定。如果binding mode的值是auto或xml,则isXml = true,如果binding mode的值是auto或json,则isJson = true
    if (!isJson && !isXml) {
        isXml = bindingMode.equals("auto") || bindingMode.contains("xml");
        isJson = bindingMode.equals("auto") || bindingMode.contains("json");
    }
}

// 如果此时仍然不能决定响应类型,则取请求内容的类型
if (isXml && isJson) {
    isXml = state.get(STATE_KEY_DO_MARSHAL).equals(STATE_XML);
    isJson = !isXml;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值