WebService:使用tcp/ip monitor拦截请求
1,wsimport -d<目录>:参数是默认的,不写也有, -s<目录>:生成.java文件, -p<生成的新包名>:生成包 ? 2,发布的类中必须有一个非静态,非私有的方法,否则报错。 ? 3,开发时,soap1.2的客户端可以向soap1.2的服务端发请求, ?????????? Soap1.1的客户端可以向soap1.1的服务端发请求, ?????????? Soap1.1的客户端可以向soap1.2的服务端发请求,(向下兼容) ?????????? Soap1.2的客户端不可以想soap1.1的服务端发请求。 4,在WSDL文档中,portType标识的一般是接口, 一个标签的字标签一般是这个标签的方法。 例如<service>的字标签 Service表示的是一个类,可以new。他的字标签port标识的就是这个类中的一个方法,名为getMobileCodeWSSoap()。 ? 5,jdk1.6只支持SOAP1.1,到了jdk1.7,就支持soap1.2了。 可以通过注解绑定SOAP类型。 在需要发布的类上添加注解: @BindingType(javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING) 上面注解绑定了SOAP1.1的规范。如果不加这个注释,默认使用SOAP1.1规范。 如果在jdk1.6的环境绑定SOAP1.2,会报错,“不能绑定SOAP1.2协议”。 如果要在jdk1.6环境下开发SOAP1.2,需要用到第三方框架。Cxf或xfire。 我们主要使用cxf。 ? 不加注解的情况下运行,如何知道是使用SOAP1.1呢? 运行之后,在浏览器访问这个服务的WSDL,发现: 6,我们通常都是远程调用这个方法,访问对方的数据库,增删改查,获取信息。比如我们要获取一组用户的数据,需要用一个List集合来存储。获取单个用户,可以直接从这个List集合中获取。 例如: private List<User> userList = new ArrayList<User>(); //获取一个用户。 public User getUser(int index){//根据用户传入的角标获取集合中的用户 if(index < 0 || index >= userList.size()) { //防止角标越界异常 return null; } return userList.get(index); } //保存用户 public void saveUser(User user){ userList.add(user); } //获取所有用户 public List<User> getAllUser() { return userList; } //根据id删除用户信息。 public User deleteUser(int index) { if(index < 0 || index >= userList.size()) { return null; } return userList.remove(index); } 再将这个工程发布,浏览器输入 http://192.168.3.237:8989/hello?wsdl 访问生成的WSDL文档,刚才定义的方法就会在这里面描述: 此外,还有一段描述: 这个是方法的描述,与这个WSDL文档不同。将这个url拷贝到地址栏中:比如: 描述了deleteUser这个方法需要的参数类型是int型,返回值类型是user。(只要是Response都是返回信息) ? 7,发布的方式有两种,一种是告诉对方WSDL地址http://192.168.3.237:8989/hello?wsdl 另一种方式就是在页面上点击右键另存为,保存为一个.xml文件,就会下载一个.xml文件。如果对方没有网络,你就可以把这个文件通过某种方式烤给他。他获取这个文件之后,可以将这个文件放入任何目录之下,通过wsimport命令解析java文件。 就可以在当前目录下生成Java文件,将里面的class文件全部删除,把cn目录整体拷贝到项目中, 可以像刚才一样调用方法。 ? 8,上面生成的Java文件运行没有问题,然后我们把hello.xml文件删掉,再运行,会报错,报找不到hello.xml文件的错误。为什么呢? 通过这种方式运行需要依赖这个文件。 在生成的HelloWorldService.java的46行报错,查看这个类的46行: 发现这个构造函数调用了父类的构造函数,父类构造函数需要一个HELLOWORLDSERVICE_WSDL_LOCATION常量参数,那这个参数是什么呢?按住ctrl点进去: 发现它绑定了一个url,这个url在构建的时候就使用了刚才的hello.xml文件,在这里写死了,最后又将这个url赋值给这个常量。 所以会报找不到这个文件的错误。 但是我们在web上使用的时候是不应该依赖这个文件的。怎么办呢?只要将这个写死的文件引用改掉就可以了。 我们需要在发布的时候,将WSDL地址也告诉对方,把这两个地方改成WSDL地址就可以了。 在上边还有一个: OK了。 ? 9,客户端请求远程数据的时候发送的是SOAP协议数据,即HTTP+XML格式的数据。之前已经提到,我们可以通过HTTPwatch拦截HTTP请求信息,但是不能拦截SOAP协议数据信息。因为发送SOAP协议的时候没有使用浏览器,所以无法捕获。 ? Sniffer局域网监听器,可以用于监听局域网传递的信息。 监听器相当于在局域网设置了一个代理,客户端将请求数据发送到代理,通过代理再发送到服务端,服务端返回数据的时候同样先将数据发送到代理上,通过代理返回给客户端。 MyEclipse自带一个代理监听工具,TCP/IPMonitor。 通过菜单栏windowàShow viewàother... 搜索tcp/ip monitor。 就找到了这个工具,点击OK打开。会在下面出现一个界面: 可以在公司中通过这个工具拦截局域网的信息。-_-# 右上角有一个小三角,点击出现下拉菜单,选择Properties。 一开始里面什么都没有,我们点击add添加一个。 点击OK后,还没有启动这个代理,点击右侧的start启动。 然后我们在浏览器中访问localhost:7777,就可以看到百度的主页。 10,使用TCP/IP Monitor监听我们的发布服务的请求及相应。 比如要监听http://192.168.3.237/hello需要如下定义: 在浏览器访问http://localhost:5555/hello?wsdl, 可以访问我们发布的服务wsdl。 在tcp/ip monitor中可以看到: 我们可以使用http://localhost:5555/hello?wsdl地址在本地生成java文件,与之前的方式相同, 将class文件删除,把cn拷贝到项目中,与之前的调用方式一样,可以访问服务器,因为我们为服务器配置了代理,所以请求会通过代理转发到服务器上,在TCP/IP Monitor就可以看到拦截的请求信息。 观察请求信息,发现它发送了GET请求,这是因为第一次访问的时候需要先与服务器握手,以后再请求就不会发送GET请求了。 注意:如果是GET请求,Content-type是null,如果是POST请求,Content-type不是空值。 请求头中有一个soapaction,只有soap1.1才有这个头信息。 在请求体中可以发现是xml数据。 这个xml的格式就是soap的标准格式,与网站上的格式比较: 上面是我们截取的请求体,后面是网站的内容。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |