欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Web Service 简明教程 (三) —— Namespace

程序员文章站 2022-03-17 16:49:16
...
    这一章节将会非常非常的简单,因为在前文code上做的修改只有4行。虽然我知道Namespace是个专业的规范,但是我对于wsdl的namespace相关概念太不熟悉了,按照我现在的认知,在这里使用非常鸡肋。

    首先先思考一个场景:在一个Endpoint内,可以有多个方法来接受不同业务的请求。同时, 发起方只传递了一个uri和参数User,因此是如何来确定由具体哪个方法来接收呢?答案就是根节点名(localPart)…… 对于前文的例子来说,接受方法的选择,仅仅依靠的是根节点名user,更重要的是对于哪个Endpoint实现类的选择也是没有的。换句话说,不管你按照业务分了多少个endpoint,每个endpoint中分了多少个方法,这些方法就好像扔进了一个水池里,是混在一起的,而你只能通过根节点名选择执行的方法,这样,就不能有两个相同根节点名的方法并存。这样的局面我并不能接受。
  
    所以我开始研究namespace的用法,但是结果依然让我失望,namespace也无法帮助我选择endpoint的方法。以下,我们先修改代码,看看namespace最最简单的用法是什么样的吧。

    首先,修改User.java,在类名前加上namespace的注解
@XmlRootElement(name = "user",namespace = "http://mycompany.com/hr/schemas")

    然后,在每一个属性的setter前也加入注解
@XmlElement(namespace = "http://mycompany.com/hr/schemas")
public void setId(int id) { this.id = id; }

@XmlElement(namespace = "http://mycompany.com/hr/schemas")
public void setName(String name) { this.name = name; }

      说明:注解本身,顾名思义,无需解释。这里有几个注意点:

               1. 属性的注解为什么要加在setter上?只要在类名前加上@XmlAccessorType(XmlAccessType.FIELD),就可以直接在属性上加注解了。

               2. 为什么要在类名和属性上反复写相同的namespace?可以只在类名前加,但是转换成XML以后的字符串会有不同。简单的场景下,两种都兼容,但是我后面需要实现一个特性,而这个特性要求我这么做。这也是让我很不爽的地方。

               3. namespace的值有什么要求吗?还记得在user.xsd中定义的targetNamespace吗?嗯,当然不需要一致,而这里写成一致,对后面也是有帮助的,所以就这么着吧。但是一定要和@Endpoint中的namespace属性一致,这个后面会贴出来。

      UserEndpoint.java
@PayloadRoot(localPart = "user", namespace = "http://mycompany.com/hr/schemas")
    @ResponsePayload
    public User handle(@RequestPayload User user) throws Exception {

      添加了namespace属性,无需多说,没什么需要注意的。

      使用第二章的第二个测试方法testSourceSend()进行测试,在请求参数转换后,打一句输出语句,就能看到添加了namespace后的User会转换成什么样子。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user xmlns="http://mycompany.com/hr/schemas">
<id>1</id>
<name>chenzhouce</name>
</user>

      干脆贴出不在属性上加注解后转换的效果吧:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:user xmlns:ns2="http://mycompany.com/hr/schemas">
<id>1</id>
<name>chenzhouce</name>
</ns2:user>

      这两种形式在现在的case中都是能通过的,至于含义上的区别,这里就不讲了,麻烦,也讲不太清楚。

      这就是最简单的namespace使用,如果client端和server端有一处没有配置,或者两处不一致,就不能通过,server端会出现No endpoint mapping found的警告。

      回过头,之所以说namespace鸡肋,是因为它虽然也是用来endpoint执行方法选择的,但是在与jaxb2直接转换的配合中,完全和localPart重复了,因为一个User就对应了主namespace.....

     我也找过有没有没注意的地方,但是没有找到,而且大把的时间其实是花在了一个坑上。。这个坑我一定会在后面说的。。。我觉得namespace一定有它应该存在的规范,只是我不知道。。

     代码提交到github上了,传送门:
https://github.com/chenzhouce/spring-webservice-demo/blob/Section_Namespace/src/main/java/com/zchen/User.java
注意:我放在了一个branch里Section_Namespace。前章节的内容依然在Master分支。