我觉得主要意思就是:参数传递采用REST风格的WebService,借助HttpClient访问WebService接口,完成服务访问。
吐槽:
这一点我是真Tama个壁的鹅心这些技术,版本升级后,好多API都不能用了。而教程又不一定是哪个版本录制的,加上目前一般都用idea+maven了,又不能直接拿着lib往里边扔。一句话,找个依赖,太他吗费劲了!!!
不多比比,开撸:
需求:Server端发布接口,client端发送携带ID的get请求,调用Server端接口获取对应ID的客户信息。
创建maven项目
1、pom.xml需要的依赖坐标如下
这部分,不清楚为什么一定需要jetty,莫非是内置的有要求。总之不加这个jetty的,代码报错。
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>3.3.4</version>
</dependency>
<!-- This dependency is needed if you're using the Jetty container -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.3.4</version>
</dependency>
</dependencies>
2、Server端
2.1 、 实体类
主要是 ** @XmlRootElement** 这个注解,用来将实体类与其他数据格式(网络传输中肯定不是以实体类进行转化,包括一些没有类这个概念的语言)进行转换。
@XmlRootElement(name = "Customer")
public class Customer {
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.2 service类
rest风格的webservice,是不需要写Service接口的,写了应该也没问题。代码,暂时不涉及太多逻辑,没有太大难度,主要就是注解。
@Path 作用同 SpringMVC的 ReauestMapping
@GTE 代表请求类型是get请求
@PathParam 作用同PathVariable
@Produces 定义方法的响应实体的数据类型(数据类型包括xml、json等等)
@Path("/customerservice/")
@Produces("text/xml")
public class CustomerService {
long currentId = 123;
Map<Long, Customer> customers = new HashMap<Long, Customer>();
public CustomerService() {
init();
}
@GET
@Path("/customers/{id}/")
public Customer getCustomer(@PathParam("id") String id) {
System.out.println("----invoking getCustomer, Customer id is: " + id);
long idNumber = Long.parseLong(id);
return customers.get(idNumber);
}
final void init() {
Customer c = new Customer();
c.setName("John");
c.setId(123);
customers.put(c.getId(), c);
}
2.3 发布接口的类
最开始,我跟着尚硅谷教程学习的。他用Eclipse创建项目后直接将下载的CXF依赖全部扔到lib文件夹下了。我使用的idea+mave,直接把依赖扔进来不现实。只能根据视频中显示的“import …”信息查找,发现很多类都找不到对应的依赖。例如:JAXRSServerFactoryBean ,按照网上说的只需要两个依赖就行,然而一直报错。我怀疑是版本问题导致的,先后更换了几个版本,结果又出现了多版本依赖冲突的问题。
此过程中出现的部分报错信息,我是一个没解决啊,但是可以肯定的是jar包的问题:
Caused by: java.lang.ClassNotFoundException: org.apache.cxf.binding.xml.XMLBinding
Caused by: java.lang.ClassNotFoundException: org.apache.cxf.binding.xml.XMLBinding
我几乎绝望了的时候,一条以我性格本来该破口大骂的回答挽救了我。既然大家说的可能版本有所不同,我直接看官方的资料总不会有错吧。
我把下载的CXF-3.3.4中的依赖的demo导入idea。
这些demo,是以聚合工程的形式存在的,因为担心父工程依赖影响我判断写这个demo需要的依赖,我又单独创建了一个项目。
public class Server {
protected Server() throws Exception {
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(CustomerService.class);
sf.setResourceProvider(CustomerService.class,
new SingletonResourceProvider(new CustomerService()));
sf.setAddress("http://localhost:9000/");
sf.create();
}
public static void main(String[] args) throws Exception {
new Server();
System.out.println("Server ready...");
Thread.sleep(5 * 6000 * 1000);
System.out.println("Server exiting");
System.exit(0);
}
}
3、客户端
3.1
该部分代码与我想象的略有出入,我开始学习参考点视频是使用HttpClient发送的请求,这里的代码我不是很理解。后边可以研究,暂时放一下就好。
2019-12-12 补充:
url.onOpen :直接获取URL指定资源的流InputStream对象,该方法无法向URL中写如数据,也无法访问这个协议的所有的元数据(如:html协议的请求头)。所以说,这个只能是对应get请求。
参考:看看人家咋说的
public final class Client {
public static void main(String[] args) throws Exception {
// Sent HTTP GET request to query customer info
System.out.println("Sent HTTP GET request to query customer info");
URL url = new URL("http://localhost:9000/customerservice/customers/123");
InputStream in = url.openStream();
System.out.println(getStringFromInputStream(in));
}
private static String getStringFromInputStream(InputStream in) throws Exception {
CachedOutputStream bos = new CachedOutputStream();
IOUtils.copy(in, bos);
in.close();
bos.close();
return bos.getOut().toString();
}
}
4、测试效果
启动server端:
启动客户端:
&& 目前暂时不涉及数据解析
2019-12-12