【JAVA 编程】基于SOAP协议和REST协议的邮件发送服务
1.SOA(面向服务的架构)架构模式现在十分的流行。WebService是SOA的一种实现方式,本文将用发送邮件这个服务来展示一下WebService是如何工作的。
2.WebService就是提供服务的网络API,它给你提供服务的结构,调用方只需要负责调用服务即可。这里其实就涉及到了一些问题,首先是如何调用?服务肯定是运行在服务器上的,要想远程调用服务器上的服务就需要和服务器通信,和服务器通信就需要通信协议,比如大名鼎鼎的TCP协议。以及封装了它的上层HTTP协议等等。SOAP协议和REST协议就是两种在实现WebService的通信协议,有了这个协议,服务器会把自己的提供的服务的配置信息写到这个协议里,客户端的调用解析这个协议然后调用即可。
3.首先是SOAP协议。这个协议看上去有点复杂:首先给出整个Demo的项目结构:
这里服务和客户端写在了一起,无所谓了,反正知识Demo,客服端和服务器的分离也是分分种的事情,懒得每次都要切屏了。
首先,是提供服务的类:mailService.这个类提供了发送邮件的服务:
具体看一下实现:
比如sendEmail这个函数,传入地址和内容,然后调用邮件发送工具的发送函数,发送邮件。注意这里的格式,首先是@WebService这个注解,表明这里的类是即将被发布成WebService类,类中要提供服务的函数,需要注解为@WebMethod。
其他三个函数类似。(啥,邮箱工具的发送函数是怎么写的?,后边会统一发出来,这个不是重点,服务的实现方式并不是重点,重点是我们怎么实现服务的发布和调用)。
然后服务写好了之后,很重要,怎么发布?
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
@WebService
public class PublishServer {
public static void main(String[] args) {
// TODO Auto-generated method stub
String url="http://localhost:9090/Service/mailService";
Endpoint.publish(url,new mailService());
System.out.print("public Success");
}
}
调用Endpoint的发布函数,把服务发送到固定的端口。当然了,这里可以直接启动Tomcat,把服务丢进Tomcat内,Tomcat启动的时候就会自动的把服务给发布了。
发布完成以后,服务端会有一个.WSDL的文件。叫做WebService描述文档,这个就是基于SOAP协议的文档,怎么看这个文档呢?启动服务(我这里直接启动主函数就行,如果是在Tomcat内,就启动tomcat),然后到发布的端口上去看:
注意看一下地址栏的网址,就是服务所在的地址+?WSDL,意思就是请求WSDL,这是一个基于get方法的请求方法,不多说了。可以看到这个WSDL文档,这是WebService的核心。这个文档内描述了这个服务的所有信息,客户端正是由于知道了这些信息才能正确的实现调用。
那么客户端如何调用呢?首先需要生成客户端,生成客户端其实就是在解析这个WSDL文档,根据这个文档在客户端建立服务端服务的视图,通过这个视图来调用。解析WSDL文档有很多种方式,这里提供一个简单的,打开cmd输入:
wsimport -s D:\DataBase\AWSTestEclipse\WebServiceProject\src -p mailClient -keep http://localhost:9090/Service/mailService?wsdl
解释一下,-s后的就是这个项目src所在的文件夹,-p后是目标代码生成的包名,-keep就是WSDL文档的地址,然后刷新一下文件目录结构。
就生成了这些东西。这是怎么实现的?其实是JDK里面有一个专门解析WSDL文档的JAR包。具体叫啥好像就是wsiport.jar.有了这个,就可以尽情的调用了。
客户端的调用我写了两种方式,由于懒只介绍一种吧。采用JSP+Servlet的调用。JSP前端传回信息,后端接受信息调用服务。
核心代码:由于在客户端我们有了服务器的视图,就相当于把服务端的代码给重现了,然后直接new对应的类,调用对应的方法提供服务。完事了,好像很简单。其实这里的底层实现我想了一下,大胆猜测,就是JAVA的RMI,简直和远程方法调用一摸一样。所以软件的发展好像就是再不断重复?????
然后SOAP就说完了。然后是REST。
REST可能就是JAVA注解的应用吧(啥叫注解???随便理解一下就是注入并解释,JAVA的动态注入大名鼎鼎,这也算是一个应用吧)
正题:
还是看一下Demo的目录结构:
还是用REST实现一个邮件发送服务:首先需要一些外部JAR包。
这个文件夹我后边会上传打github,当然自己下也可以。把里面的所有的jar包导入成外部jar包,并且在WEB-INF/lib复制一份
为啥要复制到lib下因为汤姆猫启动的时候,只会加载lib下的外部jar包,所以以后遇到tomcat报错无法找到XX类,就去把包复制进就完事了。
然后继续写服务类:
hai还是刚才的sendEmail函数,这里有几个很重要的注解,首先是最上面的@Path("/SendService")注解,这里其实就是在定义这个类的路径。然后函数上的三个注解,@GET指的是网络请求方法,@Path()定义了这个函数相对于类的路径,最后一个Prodeces我也没仔细看。函数参数的注解,额,没啥好说的,很normal,就是动态注入时候用的。
最后写一下配置文件,这个很重要,但是格式几乎就是固定的:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>CalculatorREST</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Jersey RESTful Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>mypackage</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Jersey RESTful Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HandleQuery</servlet-name>
<servlet-class>test.HandEmail</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HandleQuery</servlet-name>
<url-pattern>/test1</url-pattern>
</servlet-mapping>
</web-app>
除去我得Servlet(HandleQuery)的配置,上边的都是这个服务的配置,其实大多都不变,只需要配置一下包名:
服务写完,直接在项目名上右键,run起来,tomcat启动。
客户端如何调用?其实很简单,REST之所以使用@Path注解一直在注解路径,就是为了向外部暴露自己方法的路径,只要是沿着路径找到它,然后再把参数给注入进去就完事了。Tomcat通过反射注入参数,实现调用。比如服务器启动之后,直接再浏览器输入:http://localhost:8080/TestRest/rest/SendService/[email protected]&payload=test
解析一下这个地址:首先TestRest是项目名,rest表明我们用rest协议,SendService呢?
再看一下这张图,我们把类注解为SendService,所以他会找到这个类,后边的也是一样的,找到sendEmail这个方法,然后把参数注入。完成调用。
常见问题:
(1)javax.email找不到?哥哥你要导入啊!!!!!,官网下一个??
(2)SOAP协议发布的时候,显示areadyBind???之类的,如果你已经run了一次了,这个端口就被bind了,解决方案:换一个或者从起
(3)SOAP协议是@WebSevice之类的注解失败??该注解的地方注解一下。。。。。别偷懒
(4)REST协议web.xml配置文件总是出错???复制我上边哪个,别瞎改。。。。
(5)REST协议时,注意把javax.email也给加到lib里
github地址:https://github.com/wsyingang/SA/tree/master/SendEmail