原生webService发布服务

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014252478/article/details/88805419

在做这个欧洲项目的webService已经过了好几个月了,现在还是得及时总结一下。(不觉得技术很老吗,哈哈哈)

原生webService和CXF框架发布服务,其实没有太大的区别,尽管前者没有后者功能那么强大,但在实际使用中,前者在中间件使用中显得更加轻量级,后者则更加重。但是前者也不是万能的,在实际项目开发中已有证明,问题就在于发送请求的格式设置,最后实在无法,笔者使用了http字节流方式,虽然发布服务没有那么便捷,但达到了满足客户需求的目的。

下面介绍原生webService发布服务:

1、发布流程

2、基本功能使用

3、坑点

1、发布流程:

.config文件

import com.chargedot.webdemo.handler.InAccessHandler;
import com.chargedot.webdemo.handler.OutAccessHandler;
import com.chargedot.webdemo.service.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.xml.ws.Binding;
import javax.xml.ws.Endpoint;
import javax.xml.ws.handler.Handler;
import java.util.ArrayList;
import java.util.List;

/**
 * @author yanghao
 * @Description:
 * @date 2019/1/31 10:39
 */
@Configuration
public class SoapConfig {

    @Autowired
    private InAccessHandler inAccessHandler;
    @Autowired
    private OutAccessHandler outAccessHandler;

    @Bean
    public Endpoint endpoint(){
        Endpoint endpoint = Endpoint.publish(MessageConstant.ADDRESS, new UserServiceImpl());
        List<Handler> handlersList = new ArrayList<Handler>();
        handlersList.add(inAccessHandler);
        handlersList.add(outAccessHandler);
        Binding binding = endpoint.getBinding();
        binding.setHandlerChain(handlersList);
        System.out.println("endpoint success");
        return endpoint;
    }
}

由代码知道,加入输入拦截器和输出拦截器

Service.java接口

/**
 * @author yanghao
 * @Description:
 * @date 2019/1/29 14:29
 */
@WebService(name = "UserService",
        targetNamespace = "urn://Ocpp/Cs/2015/10/"
)
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
//@Addressing(enabled = true)
public interface UserService {

    @WebMethod(operationName = "Authorize", action = "/Authorize")
    @Action(input = "/Authorize", output = "/AuthorizeResponse")
    @WebResult(name = "authorizeResponse", /*targetNamespace = "urn://Ocpp/Cs/2015/10/",*/ partName = "parameters")
    AuthorizeResponse authorize(

            @WebParam(partName = "chargeBoxIdentity", name = "chargeBoxIdentity", header = true, targetNamespace = "urn://Ocpp/Cs/2015/10/")
                    String chargeBoxIdentity,
            @WebParam(partName = "parameters", name = "authorizeRequest", targetNamespace = "urn://Ocpp/Cs/2015/10/")
                    AuthorizeRequest parameters,
            @WebParam(partName = "Action", name = "Action", header = true, targetNamespace = "urn://Ocpp/Cs/2015/10/")
                    String action,
            @WebParam(partName = "MessageID", name = "MessageID", header = true, targetNamespace = "urn://Ocpp/Cs/2015/10/")
                    String messageID,
            @WebParam(partName = "From", name = "From", header = true, targetNamespace = "urn://Ocpp/Cs/2015/10/")
                    String from,
            @WebParam(partName = "ReplyTo", name = "ReplyTo", header = true, targetNamespace = "urn://Ocpp/Cs/2015/10/")
                    String replyTo,
            @WebParam(partName = "To", name = "To", header = true, targetNamespace = "urn://Ocpp/Cs/2015/10/")
                    String to

    );

ServiceImpl.java

/**
 * @author yanghao
 * @Description:
 * @date 2019/1/29 14:29
 */
@WebService(serviceName = "UserService",
        targetNamespace = "urn://Ocpp/Cs/2015/10/",
        endpointInterface = "com.chargedot.webdemo.service.UserService"
)
@BindingType(SOAPBinding.SOAP12HTTP_BINDING)
@Slf4j
@Component
public class UserServiceImpl implements UserService {

    @Autowired
    private KafkaProducer kafkaProducer;
    @Autowired
    private KafkaConsumer kafkaConsumer;
    @Resource
    private WebServiceContext webServiceContext;

    public String getMessageId() {
        System.out.println("getMessageId");

        String messageId = null;
        SOAPHeader header = null;

        SOAPMessageContext msgContext = (SOAPMessageContext) webServiceContext.getMessageContext();
        SOAPMessage soapMessage = msgContext.getMessage();

        try {
            header = soapMessage.getSOAPPart().getEnvelope().getHeader();
        } catch (SOAPException e) {
            log.info("soapException: {}", e);
        }

        if (header != null) {
            Node messageNode = header.getElementsByTagName("MessageId").item(1);
            if (messageNode != null) {
                log.info("MessageId is not exist");
            }
            messageId = messageNode.getTextContent();
            if (messageId == null) {
                log.warn("messageId is not exist");
            }
            log.info("MessageId:{}", messageId);
        }

        return messageId;
    }

    @Override
    public AuthorizeResponse authorize(String chargeBoxIdentity, AuthorizeRequest authorizeRequest, String action, String messageID,
                                       String from, String replyTo, String to) {

        // 1. 构造响应
        AuthorizeResponse response = new AuthorizeResponse();
        IdTagInfo idTagInfo = new IdTagInfo();
        idTagInfo.setExpiryDate(null);
        idTagInfo.setParentIdTag("");

        // 2. 封装传递centralService参数
        HashMap<String, Object> map = new HashMap<>();
        String messageId = getMessageId();
        map.put("MessageId", messageId);
        map.put("OperatorType", MessageConstant.AUTHORIZE_TYPE);
        map.put("IdTag", authorizeRequest.getIdTag());
        log.info("[ChargeBoxIdentity]:{} [MessageId]:{} [IdTag]:{}", chargeBoxIdentity, messageId, authorizeRequest.getIdTag());

        // 3. kafka send to centralService
        kafkaProducer.send(MessageConstant.OCPP16_D2S_TOPIC, chargeBoxIdentity, JacksonUtil.map2Json(map));

        // 4. 根据centralService回复,应答chargePoint
        if (Objects.nonNull(kafkaConsumer.hashMap.get(messageId))) {
            AuthorizationStatus status = (AuthorizationStatus) kafkaConsumer.hashMap.get(messageId);
            log.info("状态status: {}", status);
            idTagInfo.setStatus(status);
        }
        response.setIdTagInfo(idTagInfo);

        return response;
    }
}

2、功能使用:

(1)输入拦截器

/**
 * @author yanghao
 * @Description: 服务端过滤处理
 * @date 2019/1/30 17:45
 */
@Slf4j
@Component
public class InAccessHandler implements SOAPHandler<SOAPMessageContext> {

    @Override
    public boolean handleMessage(SOAPMessageContext context) {

        log.info("InAccessHandler.");
        Boolean out = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

        // false 表示进的方向,即接收客户端请求(解析)
        if (!out) {
            SOAPMessage message = context.getMessage();
            try {

                SOAPHeader header = message.getSOAPPart().getEnvelope().getHeader();

                if (header != null) {
                    Node chargeBoxIdentityNode = header.getElementsByTagName("ChargeBoxIdentity").item(0);
                    if (chargeBoxIdentityNode == null) {
                        log.info("chargeBoxIdentity invalid");
                        return false;
                    }
                    String chargeBoxIdentity = chargeBoxIdentityNode.getTextContent();

                    Node messageNode = header.getElementsByTagName("MessageId").item(1);
                    if (messageNode == null) {
                        log.info("MessageId invalid");
                        return false;
                    }
                    String messageId = messageNode.getTextContent();

                    Node fromNode = header.getElementsByTagName("From").item(2);
                    if (fromNode == null) {
                        log.info("fromNode invalid");
                        return false;
                    }
                    String fromUrl = fromNode.getTextContent();

                    Node toNode = header.getElementsByTagName("To").item(3);
                    if (toNode == null) {
                        log.info("toNode invalid");
                        return false;
                    }
                    String toUrl = fromNode.getTextContent();

                    log.info("ChargeBoxIdentity:{} MessageId:{}", chargeBoxIdentity, messageId);

                    new SOAPInfo(chargeBoxIdentity, fromUrl, toUrl, MessageConstant.NAMESPACE_CENTRALSYSTEM);


                } else {
                    log.info("SoapMessage header invalid");
                    return false;
                }

                message.writeTo(System.out);

            } catch (SOAPException e) {
                log.info("SOAPException: {}", e);
            } catch (IOException e) {
                log.info("IOException: {}", e);
            }
        }

        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        SOAPFault fault = null;
        try {
            SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
            fault = (SOAPFault) envelope.getBody().getFault();
        } catch (SOAPException e) {
            e.printStackTrace();
            return false;
        }
        log.info("run handleFault method!");
        return false;
    }

    @Override
    public void close(MessageContext context) {

    }

    @Override
    public Set<QName> getHeaders() {
        return null;
    }
}

(2)输出拦截器

/**
 * @author yanghao
 * @Description:
 * @date 2019/1/30 18:20
 */
@Slf4j
@Component
public class OutAccessHandler implements SOAPHandler<SOAPMessageContext> {

    @Autowired
    private WebServiceWrapper webServiceWrapper;
    @Autowired
    private KafkaConsumer kafkaConsumer;

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        Boolean out = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

        // true 表示出的方向,即发送请求到服务端
        if (out) {
            SOAPEnvelope envelope = null;
            try {
                SOAPMessage message = context.getMessage();
                envelope = message.getSOAPPart().getEnvelope();
                SOAPHeader header = envelope.getHeader();
                if (header != null) {
                    Node node = header.getElementsByTagName("MessageId").item(0);
                    String messageId = node.getTextContent();
                    if (messageId == null) {
                        log.info("OutAccessHandler messageId invalid");
                        return false;
                    }
                    String operatorType = (String) kafkaConsumer.hashMap.get("OperatorType" + messageId);
                    if (operatorType == null) {
                        log.info("operatorType invaild");
                        return false;
                    }
                    webServiceWrapper.wrapper(operatorType, messageId, message);
                }

                message.writeTo(System.out);

            } catch (SOAPException e) {
                log.info("SOAPException: {}", e);
            } catch (IOException e) {
                log.info("IOException: {}", e);
            }
        }

        return false;
    }

    @Override
    public Set<QName> getHeaders() {
        return null;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return false;
    }

    @Override
    public void close(MessageContext context) {

    }
}

3、坑点:

有2服务实现代码知道,那里我本想是获取messageId的,而这个messageId是通过webServiceContext获取的,看起来没有错误,实际上在测试时候,根本注入不进来,哪怕是获取bean的方式也无法注入进来,当然后来解决了就是在springboot+cxf下可以注入。

4、总结

可以看到在2 Service.java接口上可以看到我在配置soap协议的请求格式,是不是很笨重?确实!而且这只是一个接口,如果来个十来个不得疯掉啊,所以原生的webService也是无法完美解决分装soap协议格式的,因此最后使用http字节流的方式完美解决了,这个等以后在介绍,就到这吧,先下班了。

猜你喜欢

转载自blog.csdn.net/u014252478/article/details/88805419