问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何处理 WebService 中的 Map 对象

发布网友 发布时间:2022-04-19 00:01

我来回答

2个回答

热心网友 时间:2022-04-19 01:31

对于普通的 Java 数据类型、JavaBean、List 而言,SOAP 服务可以完全将其处理(序列化与反序列化),这些都没有任何问题,但对于 Map 对象而言,似乎就有些麻烦了。

请看下面这个例子:

 

   

@WebService(value = "/soap/ProctService", type = WebService.Type.SOAP)

public interface ProctService {

 

    boolean createProct(Map<String, Object> proctFieldMap);

}

   


为了创建一个 Proct,我们需要传递一个 Map<String, Object> 类型的参数。实现该接口应该不难,关键是客户端能否将 Map 对象传递过来?

Whatever,我们都要用一个客户端来验证一下:

 

public class ProctServiceSOAPTest {

 

    private String wsdl = "http://localhost:8080/smart-sample/ws/soap/ProctService";

    private ProctService proctService = SOAPHelper.createClient(wsdl, ProctService.class);

 

    @Test

    public void createProctTest() {

        Map<String, Object> proctFieldMap = new HashMap<String, Object>();

        proctFieldMap.put("proctTypeId", 1);

        proctFieldMap.put("name", "1");

        proctFieldMap.put("code", "1");

        proctFieldMap.put("price", 1);

        proctFieldMap.put("description", "1");

 

        boolean result = proctService.createProct(proctFieldMap);

        Assert.assertTrue(result);

    }

}

   


看来开发一个客户端也不难,关键是我们使用了 SOAPHelper,它为我们创建了一个 ProctService 的代理对象,所以接下来的一切都是那么简单!

运行一下,看看结果究竟如何吧!


异常告诉我们:Marshalling Error: java.util.Map is not known to this context,意思是说,java.util.Map 序列化(Marshalling)错误。

看来 SOAP 果无法处理 Map 对象啊!怎么解决呢?

对于 SOAP 而言,确实有些复杂,JDK 的 JAXB 规范为我们提供了一个解决方案。

我们得自定义一个 XmlAdapter(XML 适配器),将 Map 对象转换为 SOAP 可以处理的对象。

我们做的有两件事情:

定义一个 StringObjectMapAdapter 类扩展 javax.xml.bind.annotation.adapters.XmlAdapter,目的是为了转换 Map<String, Object> 对象。

使用 javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter 注解,标注需要转换的 Map 对象。

Come on!

 

   

public class StringObjectMapAdapter extends XmlAdapter<StringObjectMapAdapter.Data, Map<String, Object>> {

 

    @Override

    public Map<String, Object> unmarshal(Data data) throws Exception {

        Map<String, Object> map = new HashMap<String, Object>();

        for (Data.Entry entry : data.getList()) {

            map.put(entry.getKey(), entry.getValue());

        }

        return map;

    }

 

    @Override

    public Data marshal(Map<String, Object> map) throws Exception {

        Data data = new Data();

        for (Map.Entry<String, Object> entry : map.entrySet()) {

            data.addEntry(entry.getKey(), entry.getValue());

        }

        return data;

    }

 

    public static class Data {

 

        private List<Entry> list = new ArrayList<Entry>();

 

        public void addEntry(String fieldName, Object fieldValue) {

            Entry entry = new Entry();

            entry.setKey(fieldName);

            entry.setValue(fieldValue);

            list.add(entry);

        }

 

        public List<Entry> getList() {

            return list;

        }

 

        public void setList(List<Entry> list) {

            this.list = list;

        }

 

        public static class Entry {

 

            private String key;

            private Object value;

 

            public String getKey() {

                return key;

            }

 

            public void setKey(String key) {

                this.key = key;

            }

 

            public Object getValue() {

                return value;

            }

 

            public void setValue(Object value) {

                this.value = value;

            }

        }

    }

}

   


我们写类一个 StringObjectMapAdapter 类,让它继承 XmlAdapter,只需实现两个方法即可:

unmarshal:反序列化,将 Data 对象转为 Map 对象。

marshal:序列化,将 Map 对象转为 Data 对象。

注意,这里的 Data 可作为 StringObjectMapAdapter 的静态内部类,当然也可独立存在。在 Data 类中还有另一个静态内部类 Entry,它实际上就是 Map 中的若干条目,可将 Map 看做是用一个 List 对 Entry 的包装,这是我们上面看到的 Data 类。

随后,我们需要将 StringObjectMapAdapter 作用在 Map<String, Object> 上,只需在方法的参数中使用一个 @XmlJavaTypeAdapter 注解即可实现。

 

   

@WebService(value = "/soap/ProctService", type = WebService.Type.SOAP)

public interface ProctService {

 

    boolean createProct(@XmlJavaTypeAdapter(StringObjectMapAdapter.class) Map<String, Object> proctFieldMap);

}

   


这样,再次调用 WebService,就会看到运行成功的信息!

在这个解决方案中比较复杂的就是 StringObjectMapAdapter 了,而且我们要知道,它仅仅能处理 Map<String, Object> 类型的数据而已,对于其它不同泛型的 Map 对象还*为力,我们只能编写其它对应的 XxxMapAdapter,确实够折腾的!

对于 REST 而言,以上这一切都似乎不算什么了,不相信您就往下看把。

先写一个 REST 服务端:

 

   

@Bean

@WebService(value = "/rest/ProctService", type = WebService.Type.REST)

@Consumes(MediaType.APPLICATION_JSON)

@Proces(MediaType.APPLICATION_JSON)

public class ProctService extends BaseService {

 

    @POST

    @Path("/proct")

    @Transaction

    public boolean createProct(Map<String, Object> proctFieldMap) {

        return DataSet.insert(Proct.class, proctFieldMap);

    }

}

   


接口免了,直接为 Service 类发布 REST 服务,我们可定义输入与输出的数据类型,不妨都为 JSON 吧,当然也可以为 XML。

再写一个 REST 客户端:

 

   

public class ProctServiceRESTTest {

 

    private String wadl = "http://localhost:8080/smart-sample/ws/rest/ProctService";

    private ProctService proctService = RESTHelper.createClient(wadl, ProctService.class);

 

    @Test

    public void createProctTest() {

        Map<String, Object> proctFieldMap = new HashMap<String, Object>();

        proctFieldMap.put("proctTypeId", 1);

        proctFieldMap.put("name", "1");

        proctFieldMap.put("code", "1");

        proctFieldMap.put("price", 1);

        proctFieldMap.put("description", "1");

 

        boolean result = proctService.createProct(proctFieldMap);

        Assert.assertTrue(result);

    }

}

   


注意,这里使用的是 RESTHelper 获取 REST 客户端代理对象的,而不是 SOAPHelper。此外,我们使用的 WADL,而不是 WSDL。

运行一下,完全正确!

看来在对象序列化方面,REST 确实比 SOAP 要优秀一些。如果实际应用场景中,只能使用 SOAP 那么我们应该尽可能回避 Map 对象,实在不行的话,就只能使用 XmlAdapter 的解决方案了。如果条件允许的话,推荐尽量使用 REST。

或许有些朋友提出质疑,在 Security 方面,REST 也提供了类似 SOAP 那样的 WS-Security 解决方案吗?将来有机会再与大家讨论这方面的问题吧!

热心网友 时间:2022-04-19 02:49

定义一个 StringObjectMapAdapter 类扩展 javax.xml.bind.annotation.adapters.XmlAdapter,目的是为了转换 Map<String, Object> 对象。
使用 javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter 注解,标注需要转换的 Map 对象。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
vivox9和x9i有什么区别 ...设置原则跟构造要求。构造柱的设置原则跟构造要求是什么_百度... ...的U型钢筋锚环要几道?在哪里可以找到依据啊 ...月末不含税库存金额1065000元,请计算门店库存天数 公蟹吃什么 公蟹吃什么东西 爬行健身操功能和原理 锻炼爬行的好处有哪些呢 爬行健身法有什么优缺点 檀木如何粘合 成田剑先生还为哪些日本动漫配音,有名一点滴。谢谢了,大神帮忙啊 微波粼粼近义词 波光粼粼近义词 “波光粼粼”的近义词是什么? 粼粼的近义词 市医保石家庄报销比例 石家庄怎么办理大病医保报销多少 绣球花养殖多久能开花 C# Marshal类的中关于内存资源的释放。求解答! 如何邮箱添加快递公司邮箱 南昌西湖m方流行舞蹈学院有营业执照吗 连个小病小伤都发朋友圈的人是什么心态? 夏季皮肤干燥,用什么面膜好? 我发朋友圈说自己手受伤了,有人还点赞。我问那人为什么这么做?他就发来哈哈两个字,好气人啊,什么意思 干性肌肤要用什么补水面膜强? 银行借记卡还有没有年费和小额管理费? 有人在朋友圈发自己的惨事,该不该点赞? 我受伤了 发个朋友圈为何喜欢的女生还点个赞 大家知道枣庄银行卡么?收年费么? 我手机欠费了,收不到短信,现在想充充不了? 编程!用Python!求100以内的素数,并打印!多谢! 水波粼粼的近反义词 波光粼粼 近义词 粼粼的近义词,急 微波粼粼的近义词,急!!! 碧波粼粼是什么意思 波光粼粼和粼粼波光一样吗?杨柳依依和依依杨柳呢?? WPS为什么PDF的图标变了和Word,表格都不是一个风格了? 兴味盎然、喝彩、为所欲为、窃窃私语、微波粼粼的近义词 波光粼粼什么意思(专业回答) 波光粼粼的意思是什么? 长恩无敌门适合什么样的指纹锁? vivoy79是两面指纹解锁吗 指纹锁里面有两根线什么意思? 梦到有小偷进门偷东西代表什么 冰柜冷凝器发烫的原因 冰柜的冷凝器什么 豆干炒肉末的做法,豆干炒肉末怎么做好吃,豆干 肉末炒豆干怎么做好 德国飞艇彩票是违法的吗 魔兽世界暗月马戏团奖券换什么