使用契约优先的方式来开发WebService(用到了jaxws-ri),并发布到tomcat中

来源:互联网 发布:张学友 经典 知乎 编辑:程序博客网 时间:2024/06/10 20:42

代码下载地址:

http://download.csdn.net/detail/mr_pang/9270313

功能:

开发这个WebService用于与数据库中的数据进行交互,这样当数据库位于一台单独的主机中时,我们就能方便的对其中的数据进行操作。但是这里只是进行了查找的操作,更多复杂的操作还要用到数据库中的一些东西。


环境:
1.数据库:Oracle11g
2.IDE:MyEclipse
3.Server:Tomcat 5.0
4.WebService:jaxws-ri


提示:
1.这种方式不是最好的,还有一种使用jaxws-ejb的方式,比这种方式还要简洁,只是我暂时没用过,最近忙着学习TCP/IP原理,就没研究,读者有兴趣的话,就自己研究吧。
2.代码挺多,而且步骤也挺多,如果读者照着自己编写的话,由于开发环境不同等外部因素,肯定会遇到不少错误的。就算读者将项目下载下来,再导入进自己的IDE中,来运行,也不能保证100%能成功运行。但是对我们来说,有问题正常,有问题我们就解决问题,没有问题是解决不了的。请读者自行google来解决问题。
3.如果实在看不懂,请根据孔浩老师的WebService视频来学习。
4.其中用到的数据库连接,还得需要各位自己创建,其中连接的用户名为scott,密码自己定。数据库表也请自己创建,在其中添加上相应的数据即可。
5.其中需要用到的jaxws-ri的jar包,在服务器端的lib目录下都有。


步骤:
1.编写服务器端代码:
(1) 编写wsdl文件,在其中定义好输入的内容的类型,输出内容的类型,异常,SOAP头部信息等。wsdl文件要位于/WEB-INF/wsdl文件夹中。
下面是dbOperation.wsdl文件中的内容,如果不懂这个文件中的内容,请自行学习,其中用到了XML Schema,SOAP消息.这个文件中还包含了异常,所以应当有相应的异常的类,请参考项目目录:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wsdl:definitions 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
xmlns:tns="http://www.example.org/dbOperation/" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
name="dbOperation" 
targetNamespace="http://www.example.org/dbOperation/">
 <wsdl:types>
   <xsd:schema targetNamespace="http://www.example.org/dbOperation/">
     <xsd:element name="sql" type="tns:sql"></xsd:element>
     <xsd:element name="sqlResponse" type="tns:sqlResponse"></xsd:element>
     <xsd:element name="DBException" type="xsd:string"></xsd:element>
     <xsd:element name="licenceInfo" type="tns:licenceInfo"></xsd:element>
     
     <xsd:complexType name="sql">
<xsd:sequence>
<xsd:element name="sql" type="xsd:string"></xsd:element>
</xsd:sequence>
     </xsd:complexType>
     
     <xsd:complexType name="sqlResponse">
<xsd:sequence minOccurs="1" maxOccurs="unbounded">
<xsd:element name="sqlResponse" type="xsd:string"></xsd:element>
</xsd:sequence>
     </xsd:complexType>
     
     <xsd:complexType name="licenceInfo">
<xsd:sequence>
<xsd:element name="username" type="xsd:string"></xsd:element>
<xsd:element name="password" type="xsd:string"></xsd:element>
</xsd:sequence>
     </xsd:complexType>
     
   </xsd:schema>
 </wsdl:types>
 
 <wsdl:message name="sql">
   <wsdl:part element="tns:sql" name="parameters"/>
 </wsdl:message>
 <wsdl:message name="sqlResponse">
   <wsdl:part element="tns:sqlResponse" name="parameters"/>
 </wsdl:message>
 <wsdl:message name="DBException">
<wsdl:part element="tns:DBException" name="parameters"></wsdl:part>
 </wsdl:message>
 <wsdl:message name="licenceInfo">
<wsdl:part element="tns:licenceInfo" name="licenceInfo"></wsdl:part>
 </wsdl:message>
 
 <wsdl:portType name="dbOperation">
   <wsdl:operation name="sql">
     <wsdl:input message="tns:sql"/>
     <wsdl:output message="tns:sqlResponse"/>
     <wsdl:fault name="DBException" message="tns:DBException"></wsdl:fault>
   </wsdl:operation>
 </wsdl:portType>
 <wsdl:binding name="dbOperationSOAP" type="tns:dbOperation">
   <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
   <wsdl:operation name="sql">
     <wsdl:input>
<soap:header use="literal" part="licenceInfo" message="tns:licenceInfo"/>
<soap:body use="literal"/>
     </wsdl:input>
     <wsdl:output>
<soap:body use="literal"/>
     </wsdl:output>
   </wsdl:operation>
 </wsdl:binding>
 <wsdl:service name="dbOperation">
   <wsdl:port binding="tns:dbOperationSOAP" name="dbOperationSOAP">
     <soap:address location="http://localhost/DBWebService/do"/>
     <!-- 这里的DBWebService是项目的名字,不要写成别的,写成别的启动不了,因为我的tomcat的端口号是80,所以这里省略了 -->
   </wsdl:port>
 </wsdl:service>
</wsdl:definitions>
(2) 使用命令行,转到projectname/WEB-INF/wsdl文件夹中,并使用wsimport命令将wsdl文件导出到一个自定义的文件夹,至于都导出了些什么,还请各位自行查看,其中最重要的就是那个接口,其他的都可以不要,但是这个接口一定要的。
C:\Users\lenovo>cd e:/project/projectname/WEB-INF/wsdl
C:\Users\lenovo>e:
E:\project\projectname\WEB-INF\wsdl>wsimport -d e:/webservice -keep -verbose dbOperation.wsdl 
(3) 将除了DbOperation.java这个接口外的其他全部类删掉就行,这时,需要修改DbOperation这个接口中的一些内容,修改后的代码如下:

package org.example.dboperation;


import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;




/**
* This class was generated by the JAX-WS RI.
* JAX-WS RI 2.2.4-b01
* Generated source version: 2.2

*/
@WebService(name = "dbOperation", targetNamespace = "http://www.example.org/dbOperation/")
public interface DbOperation {


   /**
    * 
    * @param sql
    * @return
    *     returns java.util.List<java.lang.String>
    */
   @WebResult(name = "sqlResponse", targetNamespace = "")
   @RequestWrapper(localName = "sql", targetNamespace = "http://www.example.org/dbOperation/", className = "org.example.dboperation.Sql")
   @ResponseWrapper(localName = "sqlResponse", targetNamespace = "http://www.example.org/dbOperation/", className = "org.example.dboperation.SqlResponse")
   public List<String> sql(
@WebParam(name = "sql", targetNamespace = "")
String sql);


}
(4) 新建一个类(DbOperationImp.java)来实现DbOperation这个接口,并在其中实现访问数据库的方法。因为还要涉及到权限管理,所以其中添加了登录检查的代码:
package org.example.dboperation;


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;


import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;
import javax.xml.ws.WebServiceContext;


import org.example.exception.DBException;


import com.sun.xml.ws.api.message.Header;
import com.sun.xml.ws.api.message.HeaderList;
import com.sun.xml.ws.developer.JAXWSProperties;


@WebService(endpointInterface="org.example.dboperation.DbOperation",
wsdlLocation="WEB-INF/wsdl/dbOperation.wsdl",
serviceName="dbOperation",
portName="dbOperationSOAP",
targetNamespace="http://www.example.org/dbOperation/")
public class DbOperationImp implements DbOperation {
List<String> resultList = new ArrayList<String>();


String userName = "scott";//数据库连接的账号名
String userPassword = "*****";//这里是你的数据库的密码

@Resource
private WebServiceContext ctx;

@Override
public List<String> sql(String sql) {

try {

if (checkLogin() == false) {
throw new DBException("身份验证没通过,无法进行下面的操作");
}

Class.forName("oracle.jdbc.driver.OracleDriver");

Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl",userName,userPassword);

Statement statement = connection.createStatement();

ResultSet resultSet = statement.executeQuery(sql);
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();

if (resultSet == null) {
throw new DBException("查询没有结果");
}else {
while (resultSet.next()) {
for (int i = 0; i < columnCount; i++) {
resultList.add(resultSet.getString(i + 1));
}
// resultList.add(resultSet.getString("projectname"));
}
return resultList;
}

} catch (ClassNotFoundException e) {
if (e.getMessage().equals("oracle.jdbc.driver.OracleDriver")) {
System.out.println("We are so sorry that we have not found this database driver,please load it");
}
} catch (SQLException e) {
e.printStackTrace();
} catch (DBException e) {
System.out.println(e.getMessage());
}

resultList.add(" ");

return resultList;
//在这里往列表中添加一个空元素,并返回这个值
}

/*
* 通过检查客户端发送给服务器端的SOAP消息中的SOAP:Header的内容,来判断是否可以让用户执行后面的操作
*
* @return 如果验证成功,则返回true,验证失败则返回false
*/
private boolean checkLogin () {
HeaderList headerList = (HeaderList) ctx.getMessageContext().get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY);

Header header = headerList.get(new QName("http://www.example.org/dbOperation/", "userinformation"),true);

String userName = "";
String password = "";

try {
XMLStreamReader reader = header.readHeader();

while (reader.hasNext()) {

int event = reader.next();

if (event == XMLStreamConstants.START_ELEMENT) {
String paramName = reader.getName().toString();
if (paramName.equals("userName")) {
userName = reader.getElementText();
} else if (paramName.equals("password")) {
password = reader.getElementText();
}
}

}

if (userName.equals("pangshuyue") && password.equals("123456")) {
return true;
}

} catch (Exception e) {
e.printStackTrace();
}


return false;
}


}
(5) 在WEB-INF目录下,创建sun-jaxws.xml文件,这个文件是将WebService发布到Tomcat上的必须文件,文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">
<endpoint name="dbOperation" implementation="org.example.dboperation.DbOperationImp" url-pattern="/do"/>
<!-- 
name属性指的是servlet中对应的名称
implementation是实现类
url-pattern指的是在浏览器中的后缀
-->
</endpoints>
(6) 在WEB-INF的lib文件夹中导入jaxws-ri相关的所有jar包,因为要涉及到数据库的连接,所以在构建路径中要加上jdbc6.jar,如果还要用到其他的jar包,也要添加到构建路径中
(7) 在WEB-INF文件夹下的web.xml中声明一个监听器来监听与WebService相关的事件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>

<servlet>
<servlet-name>dbOperation</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>dbOperation</servlet-name>
<url-pattern>/do</url-pattern>
</servlet-mapping>

</web-app>
(8) 在MyEclipse的server中部署上我们的WebService服务器端项目,启动server,在浏览器中输入
http://localhost/DBWebService/do?dbOperation.wsdl
    看看是不是出现了我们编写的wsdl文件?如果是这样,那么WebService就发布完成啦。


2.编写客户端代码:
既然已经发布了WebService,那么我们总得写个客户端来访问它吧。好,那我们就开始吧:
(1) 使用wsimport命令将我们的webservice导出
C:\Users\lenovo>wsimport -d e:/webservice -keep -verbose http://localhost/DBWebService/do?dbOperation.wsdl
(2) 将上述命令生成的类,拷贝到我们的客户端程序中,并编写测试类来连接:
package org.example.test;


import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;


import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;


import org.example.bean.UserInformationBean;
import org.example.dboperation.DbOperation;
import org.example.dboperation.DbOperation_Service;
import org.w3c.dom.Document;


import com.sun.xml.ws.api.message.Headers;
import com.sun.xml.ws.developer.WSBindingProvider;


public class Test {

public static void main(String[] args) throws MalformedURLException {

URL url = new URL("http://localhost:8645/DBWebService/do?wsdl");
QName qName = new QName("http://www.example.org/dbOperation/", "dbOperation", "db");

DbOperation_Service service = new DbOperation_Service(url,qName);
//通过这种指定端口号的方式,来查看服务器接收到的SOAP消息和 发送出去的SOAP消息
// DbOperation_Service service = new DbOperation_Service();
DbOperation operation = service.getDbOperationSOAP();

try {
JAXBContext jaxbContext = JAXBContext.newInstance(UserInformationBean.class);

UserInformationBean userInformationBean = new UserInformationBean();
userInformationBean.setUserName("pangshuyue");
userInformationBean.setPassword("123456");

QName elementName = new QName("http://www.example.org/dbOperation/", "userinformation");

JAXBElement<UserInformationBean> jaxbElement = new JAXBElement<UserInformationBean>(elementName, UserInformationBean.class, userInformationBean);
System.out.println("The JAXBElement is " + jaxbElement);

Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);

Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
marshaller.marshal(jaxbElement, document);

WSBindingProvider provider = (WSBindingProvider) operation;
provider.setOutboundHeaders(Headers.create(document.getDocumentElement()));

} catch (Exception e) {
e.printStackTrace();
}

List<String> list = operation.sql("select userEmail from userinformation where username=\'逄淑越\'");

for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}

}
}
(3) 因为客户端中也用到了jaxws-ri中的一些类,所以也要将编写服务器端代码时的那些jaxws-ri相关的类全部加入到构建路径中,当然,也可以只添加需要的那几个。另外,不要忘记将jdbc的jar包添加进来。
(4) 运行一下看看,会有什么结果?这时候tomcat一定要是启动的,如果tomcat是关闭的,那么自然会不成功的。

结束语:
   其实昨天这篇文章就写好了,但是昨天oracle被我卸载重装了,今天才将原来的数据都导进去,所以今天早晨才能发布。
   另外提醒大家一句,装windows千万别装home版的,这个版本很多功能没有,满足不了我们开发者的要求。昨天就是因为oracle中SYSTEM的密码忘记了,
然后按照网上的教程,本想用conn / as sysdba;命令来修改SYSTEM账号的密码,但是提示权限不够,去找用户和组想把当前登录用户加上,可是加不上,
因为windows 8.1这个功能被禁用了!!!
   有条件最好用Linux,我最近正在研究,但是仍旧是小菜鸟。对于网络管理来说,Linux的优势太明显了。而且全部用Shell操作,也感觉很有成就感。






0 0
原创粉丝点击