前段時間有博友在看我的博文《WebService入門案例》后,發郵件問我關於WebService 接口在java中的開發,以及在實際生產環境中的應用。想想自己入職也有一段時間了,似乎也該總結一下自己對於接口化開發的認識,以及如何利用java開發一些可以供其他應用程序使用的web服務。
其實最開始對Web服務的認識還是在課堂上,老師反復地在講SOAP協議,其實也不懂究竟是什么意思,無緣無故就在大腦中形成了條件反射,SOAP協議的中文意思就是簡單對象訪問協議;而且,更加巧合的是自己在求職面試時就被項目經理問到這么一個問題,直接回答簡單對象訪問協議!此時,只能對當時上課的老師表示感謝。
好了,廢話不多說,轉入正題。在本文中,首先總結一下自己對接口化編程的認識,自己在項目結構方面MVC思想的體現,然后談談對WebService的印象,最后以Xfire的實際開發為案例具體談談自己的接口開發,以及如何在MVC的結構思想基礎上開發WebService。本文為自己學習和工作總結積累所得,歡迎轉載。請保留原文出處。
接口化編程,在項目結構方面MVC思想
隨着J2EE實際開發的機會增多,經驗也在慢慢地積累,就是這些小知識的積累就形成了自己開發實踐的一種模式。但是就整個項目的結構思想而言,是沒有任何變化的,即MVC。畢竟就MVC本身來說,它已經是一種軟件典范,這種邏輯,界面,數據分離的設計早就被行業內所認可。就拿都比較熟悉的,也比較熱的J2EE中SSH三大框架來說,就是很好的體現了這么一個特點,而有一些企業則是用ibatis或mybatis替代Hibernate進行數據層的操作。兩者都有其各自的優缺點,此處就不談了。因為畢竟不是在說MVC或者框架的開發實踐。但是,我們需要在這樣的基礎上開發接口,就必須要對這些框架有一定的了解。
在我個人而言,開發接口,我喜歡用interface的首字母加上需要開發的接口名稱再加上服務的英文單詞就可以了。比如說,我需要開發一個用戶的接口,那么我給這個接口的名稱就是IUserService;而且實現這個接口的類則命名為UserService。個人感覺比較簡單,容易分辨。至於在此基礎上的框架開發,不同的功能使用不同的包名,其命名規范也得講究才行,我自己的項目中包名通常用com.red.功能包,實體包bean,接口包service,DAO包dao,工具包util等,具體情況具體分析;實體bean類,則用User或UserBean,如果數據層采用的是Hibernate那就用User.hbm.xml或UserBean.hbm.xml;如果是ibatis等,那就用User.xml或UserBean.xml。我的原則就是盡可能一眼就分辨出這個java類或文件具體是干什么的,其主要內容是什么。
對WebService的印象
接口化自己的程序方法可以將自己的實現類進行一定程度的封裝,只提供接口方法給其它程序,如果其它程序需要調用這個接口,它不再需要關心具體的實現,數據的如何處理,而且,這也更加體現了分布式應用程序的好處。比如我有一個程序作為整個系統多個項目的數據處理中心,為不同的項目提供數據服務,即所有的項目都是建立在這個基礎上的,而且,其它的項目不再進行數據處理服務,只是負責頁面和業務邏輯,有效地將數據徹底和業務分開,而且,它還沒有數據庫和相關環境的依賴。這樣開發的優點就不言而喻了。實際上,這樣做對數據的安全也有一定的保障。
接着談談WebService,開發了這么久的WebService,今天就痛快的總結一下吧。
WebService在當下,它是開發分布式的互操作的應用程序不可缺少的一部分。Web服務,能夠使部署在不同平台上的不同語言開發的不同的應用在不需要借助第三方的基礎上進行數據的交互和系統的集成。而WebService的基礎特點就是開放性,剛才已經體現出來了。要使用WebService,就必須得會用兩種技術,分別是XML和SOAP。XML無疑是在web中傳輸結構化數據的一種偉大方式,它可以用來標記數據,定義數據類型,然而WebService正是需要以一種可靠的方式處理數據,因此XML來實現這樣的功能是最理想的;SOAP,前文已經提到的簡單對象訪問協議,是一種基於XML的簡單,輕量的交換數據的協議規范,一條SOAP信息就是一個標准的XML文檔,SOAP使用XML信息調用遠程方法,這樣WebService就可以通過不同的請求方式與遠程機進行交互。其實SOAP的實現也挺有意思的,由於篇幅有限,此處就不再贅述。
以Xfire的實際開發,在MVC的結構思想基礎上開發WebService
談了如此多的接口開發,畢竟實踐是檢驗真理的唯一標准。下面就以一個小Demo來說說利用Xfire開發接口,並且供其它程序調用的方式。
1. 建庫:
所用的數據庫demo和測試用表userinfo:
CREATE TABLE `userinfo` ( `USER_ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶id', `USER_NAME` varchar(45) DEFAULT NULL COMMENT '用戶名', `USER_PASSWORD` varchar(45) DEFAULT NULL COMMENT '用戶密碼', `USER_EMAIL` varchar(45) DEFAULT NULL COMMENT '用戶郵箱', PRIMARY KEY (`USER_ID`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
測試數據如下:
2. 服務器端:提供WebService
a. 新建一個web工程,為其添加xfire功能;直接點擊項目,然后鼠標右鍵,添加Xfire功能,根據向導下一步就行。我在這個demo中只是把xfire配置文件的路徑給改了,放到了WEB-INF下面;添加完成后,在web.xml中可以看到多出的幾行代碼:
<servlet> <servlet-name>XFireServlet</servlet-name> <servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>XFireServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
b. 可以新建一個接口了,然后實現它,數據處理等。就如同我在上文中提到的一樣,以MVC的方式進行結構化,我在這個demo中只是為了說明WebService的開發,就沒涉及到多的框架,采用JDBC訪問的mysql數據庫,demo的項目結構整體如下:
c. 現將重點代碼粘貼:
User實體類:其get和set方法以及構造方法已經省略。
private int user_id; private String user_name; private String user_password; private String user_email;
數據庫開啟和關閉鏈接的工具類Conn類:
public Connection getConn() { try { String Driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://127.0.0.1:3306/demo"; String user = "root"; String password = "123456"; Class.forName(Driver); Connection conn = DriverManager.getConnection(url, user, password); return conn; } catch (Exception e) { e.printStackTrace(); } return null; } public void closeConn(ResultSet rs, Statement stmt, Connection conn) { try { if (null != rs && !rs.isClosed()) rs.close(); if (null != stmt && !stmt.isClosed()) stmt.close(); if (null != conn && !conn.isClosed()) conn.close(); } catch (Exception e) { e.printStackTrace(); } }
用戶接口類IUserService:
public interface IUserServices { /** * 查詢所有 * @return list集合 */ public List<User> findAll(); /** * 通過用戶id查找 * @param user_id 客戶id * @return 用戶對象 */ public User findById(int user_id); }
用戶接口實現類UserService:
public class UserServices implements IUserServices { private UserDao userDao=new UserDao(); public List<User> findAll() { return userDao.findAll(); } public User findById(int userId) { return userDao.findById(userId); } public UserDao getUserDao() { return userDao; } public void setUserDao(UserDao userDao) { this.userDao = userDao; } }
數據庫操作類UserDao:
public List<User> findAll() { try { List<User> list = new ArrayList<User>(); String sql = "SELECT USER_ID, USER_NAME, USER_PASSWORD, USER_EMAIL FROM userinfo"; Connection conn = new ConnUtil().getConn(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { User user = new User(); user.setUser_id(rs.getInt("USER_ID")); user.setUser_name(rs.getString("USER_NAME")); user.setUser_password(rs.getString("USER_PASSWORD")); user.setUser_email(rs.getString("USER_EMAIL")); list.add(user); } return list; } catch (Exception e) { e.printStackTrace(); } return null; } public User findById(int userId) { try { User user = new User(); String sql = "SELECT USER_ID, USER_NAME, USER_PASSWORD, USER_EMAIL FROM userinfo AS u WHERE u.USER_ID= '" + userId + "'"; Connection conn = new ConnUtil().getConn(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { user.setUser_id(rs.getInt("USER_ID")); user.setUser_name(rs.getString("USER_NAME")); user.setUser_password(rs.getString("USER_PASSWORD")); user.setUser_email(rs.getString("USER_EMAIL")); } return user; } catch (Exception e) { e.printStackTrace(); } return null; }
此時的開發已經基本上完成了,最后配置xfire.xml就算完成了webService 的開發。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xfire.codehaus.org/config/1.0"> <service> <name>UserServices.cis</name> <serviceClass>com.red.services.IUserServices</serviceClass> <implementationClass>com.red.services.UserServices </implementationClass> </service> </beans>
將這個新項目部署到tomcat,然后啟動tomcat。在瀏覽器中輸入:http://localhost:8080/svc/UserServices.cis?wsdl 就會看到如下的頁面,說明開發完成:
3. 客戶端訪問WebService的開發:
a. 為了方便,直接新建一個java工程,只要能夠訪問剛剛開發好的webService就行。項目結構如下:
b. 重點代碼粘貼:同名類的代碼和service端相同。
ConfigUtil類:
public class ConfigUtil { private static final long serialVersionUID = -5639833339612968585L; private volatile static ConfigUtil client = null; public static ConfigUtil getInstance() { if (null == client) { client = new ConfigUtil(); } return client; } public Object createTunnel(Class<?> interfaceclass, String url) { try { Service srvcModel = new ObjectServiceFactory().create(interfaceclass); XFire client = XFireFactory.newInstance().getXFire(); XFireProxyFactory factory = new XFireProxyFactory(client); Object service = factory.create(srvcModel, url); return service; } catch (MalformedURLException e) { } return null; } }
ServiceTest類進行測試:
public class ServiceTest { public static void main(String[] args) { try { IUserServices service = getService(); List<User> list = service.findAll(); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i).getUser_name() + "::" + list.get(i).getUser_email()); } User user=service.findById(1); System.out.println(user.getUser_email()+"::mail"); } catch (Exception e) { e.printStackTrace(); } } public static IUserServices getService() { ConfigUtil util = ConfigUtil.getInstance(); String url = "http://127.0.0.1:8080/svc/UserServices.cis"; IUserServices ctservice = (IUserServices) util.createTunnel(IUserServices.class, url); return ctservice; } }
Main方法測試結果:控制台打印結果。
順利完成。
作者:itRed 郵箱:it_red@sina.com 博客:http://www.cnblogs.com/itred 個人網站:http://wangxingyu.jd-app.com ***版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但請在文章顯眼位置標明文章出處。未經本人書面同意,將其作為他用,本人保留追究責任的所有權利。