javascript
Spring 3 RESTful Web服务
Spring 3提供了對(duì)RESTful Web服務(wù)的支持。 在本教程中,我們將向您展示如何在Spring中實(shí)現(xiàn)RESTful Web服務(wù) ,或者如何將現(xiàn)有的Spring服務(wù)公開為RESTful Web服務(wù) 。 為了使事情變得更有趣,我們將從上一篇關(guān)于Spring GWT Hibernate JPA Infinispan HornetQ集成的文章的 結(jié)尾處繼續(xù) 。 我們將使用GWTSpringInfinispanHornetQ項(xiàng)目,并將“ employeeService” CRUD功能公開為RESTful Web服務(wù) 。 當(dāng)然,您可以參考本文,以了解如何將Spring服務(wù)公開為RESTful Web服務(wù) 。
實(shí)現(xiàn)RESTful Web服務(wù)的最流行的方法是Sun的JAX-RS規(guī)范。 有幾個(gè)支持JAX-RS的項(xiàng)目,例如CXF , Jersey , RESTEasy和Restlet 。 他們中的大多數(shù)人還提供Spring支持。 Spring不直接支持JAX-RS ,而是將RESTful功能添加到了Spring MVC本身。 如果您不熟悉Spring MVC框架,請(qǐng)?jiān)诖颂幉殚哠pring文檔的相應(yīng)章節(jié)。 對(duì)于不耐煩的人,下面簡(jiǎn)要概述。
Spring MVC代表模型視圖控制器。 它有助于構(gòu)建靈活且松散耦合的Web應(yīng)用程序。 模型-視圖-控制器設(shè)計(jì)模式可確保多層Web應(yīng)用程序中關(guān)注點(diǎn)(業(yè)務(wù)邏輯,表示邏輯和導(dǎo)航邏輯)的分離。 “控制器”負(fù)責(zé)接收來自用戶的請(qǐng)求并調(diào)用后端服務(wù)。 模型負(fù)責(zé)封裝應(yīng)用程序數(shù)據(jù)。 視圖使用模型對(duì)象將響應(yīng)呈現(xiàn)給用戶。 簡(jiǎn)而言之 :
將請(qǐng)求發(fā)送到Spring MVC Framework時(shí),將發(fā)生以下事件序列。
- “ DispatcherServlet”首先收到請(qǐng)求
- “ DispatcherServlet”查詢“ HandlerMapping”并調(diào)用與請(qǐng)求關(guān)聯(lián)的“ Controller”
- “控制器”通過調(diào)用適當(dāng)?shù)姆?wù)方法來處理請(qǐng)求,并將“ ModeAndView”對(duì)象返回到“ DispatcherServlet”。 “ ModeAndView”對(duì)象包含模型數(shù)據(jù)和視圖名稱
- “ DispatcherServlet”將視圖名稱發(fā)送到“ ViewResolver”以查找要調(diào)用的實(shí)際“視圖”
- “ DispatcherServlet”將模型對(duì)象傳遞給“視圖”以呈現(xiàn)結(jié)果
- 在模型數(shù)據(jù)的幫助下,“視圖”呈現(xiàn)結(jié)果并將其返回給用戶
聊夠了! 讓我們弄臟雙手!
我們將需要“ cglib”字節(jié)碼生成庫和“ asm”字節(jié)碼操作框架,以便Spring能夠?qū)OP方面正確地應(yīng)用于“ Controller”對(duì)象。 我們將使用“CGLIB” 2.2版本,您可以下載在這里和在“asm”二進(jìn)制分發(fā)版,你可以下載在這里 。 在“ asm”二進(jìn)制發(fā)行版的/ lib / all文件夾下找到asm-all-3.3.jar,并將asm-all-3.3.jar和cglib-2.2.jar都放置在項(xiàng)目的/ war / WEB-INF / lib文件夾下。
最后,我們將需要Jackson JSON處理器。 我們將使用1.5.3版的“核心”和“映射器”發(fā)行版,您可以從此處下載。 將兩個(gè)jackson-core-asl-1.5.3.jar
和項(xiàng)目的/ war / WEB-INF / lib文件夾下的jackson-mapper-asl-1.5.3.jar。
我們必須照顧我們的Eclipse項(xiàng)目的依賴性。 以下jars應(yīng)該包含在項(xiàng)目的Java構(gòu)建路徑中:
- org.springframework.web-3.0.1.RELEASE-A.jar
如上所述,“ DispatcherServlet”是一個(gè)用于管理整個(gè)請(qǐng)求處理過程的servlet。 與其他任何servlet一樣,它需要在Web部署描述符或我們的應(yīng)用程序中進(jìn)行配置。 在/ war / WEB-INF文件夾下找到“ web.xml”文件,然后添加以下內(nèi)容:
<servlet><servlet-name>dispatcher</servlet-name><servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class><load-on-startup>2</load-on-startup> </servlet><servlet-mapping><servlet-name>dispatcher</servlet-name><url-pattern>/restServices/*</url-pattern> </servlet-mapping>默認(rèn)情況下,“ DispatcherServlet”將查找名為“ {servlet-name} –servlet.xml”的文件以加載Spring MVC配置。 在我們的例子中是“ dispatcher-servlet.xml”。 在這里,我們將url –模式用作“ / restServices / *”,以便“ DispatcherServlet”僅處理指定模式下的所有傳入請(qǐng)求。 創(chuàng)建一個(gè)“ dispatcher–servlet.xml”文件,并將其放在/ war / WEB-INF文件夾下,如下所示:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"><context:component-scan base-package="com.javacodegeeks.gwtspring.server.endpoints" /><tx:annotation-driven /><mvc:annotation-driven /></beans>這里要注意的事情:
- 我們將“ context:component-scan”配置元素的base-package屬性設(shè)置為我們的Spring MVC注釋類將駐留的位置
- 我們使用“ tx:annotation-driven”配置元素,以便能夠向我們的MVC類注入事務(wù)行為
- “ mvc:annotation-driven”是Spring 3的配置元素,可大大簡(jiǎn)化Spring MVC的設(shè)置。 該標(biāo)簽注冊(cè)了將請(qǐng)求分派到@Controller注釋類的所需的“ HandlerMapping”和“ HandlerAdapter”。 另外,它根據(jù)您的類路徑中存在的內(nèi)容應(yīng)用合理的默認(rèn)值。 這樣的默認(rèn)值包括(包括其他):
- 支持使用@NumberFormat注釋格式化數(shù)字字段
- 如果類路徑上有Joda Time,則支持使用@DateTimeFormat批注格式化Date,Calendar和Joda Time字段
- 如果類路徑上有JSR-303提供者,則支持使用@Valid注釋驗(yàn)證@Controller注釋的類輸入
- 如果類路徑上包含JAXB ,則支持讀取和寫入XML
- 如果杰克遜在類路徑上,則支持讀寫JSON
在項(xiàng)目的“服務(wù)器”包下創(chuàng)建一個(gè)“端點(diǎn)”子包。 就GWT而言,服務(wù)端點(diǎn)是服務(wù)器端組件,因此所有類都必須放在“服務(wù)器”包下。 在“端點(diǎn)”子包下,放置“ EmployeeServiceController”類,如下所示:
package com.javacodegeeks.gwtspring.server.endpoints;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody;import com.javacodegeeks.gwtspring.shared.dto.EmployeeDTO; import com.javacodegeeks.gwtspring.shared.services.EmployeeService;@Controller @RequestMapping("/employeeService") public class EmployeeServiceController {@AutowiredEmployeeService employeeService;@RequestMapping(value = "/{id}", method = RequestMethod.GET)@ResponseBodypublic EmployeeDTO findEmployee(@PathVariable("id") long employeeId) {return employeeService.findEmployee(employeeId);}@RequestMapping(value = "/{id}/{name}/{surname}/{job}", method = RequestMethod.POST)@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)public String saveEmployee(@PathVariable("id") long employeeId, @PathVariable String name, @PathVariable String surname, @PathVariable("job") String jobDescription) throws Exception {employeeService.saveEmployee(employeeId, name, surname, jobDescription);return "redirect:/restServices/employeeService/" + employeeId;}@RequestMapping(value = "/{id}/{name}/{surname}/{job}", method = RequestMethod.PUT)@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)public String updateEmployee(@PathVariable("id") long employeeId, @PathVariable String name, @PathVariable String surname, @PathVariable("job") String jobDescription) throws Exception {employeeService.updateEmployee(employeeId, name, surname, jobDescription);return "redirect:/restServices/employeeService/" + employeeId;}@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)@ResponseBodypublic String deleteEmployee(@PathVariable("id") long employeeId) throws Exception {employeeService.deleteEmployee(employeeId);return "OK";}}我們提供“ EmployeeService”和“ EmployeeDTO”實(shí)現(xiàn)作為參考:
package com.javacodegeeks.gwtspring.server.services;import javax.annotation.PostConstruct; import javax.annotation.PreDestroy;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional;import com.javacodegeeks.gwtspring.server.dao.EmployeeDAO; import com.javacodegeeks.gwtspring.server.utils.NotificationsProducer; import com.javacodegeeks.gwtspring.shared.dto.EmployeeDTO; import com.javacodegeeks.gwtspring.shared.services.EmployeeService;@Service("employeeService") public class EmployeeServiceImpl implements EmployeeService {@Autowiredprivate EmployeeDAO employeeDAO;@AutowiredNotificationsProducer notificationsProducer;@PostConstructpublic void init() throws Exception {}@PreDestroypublic void destroy() {}public EmployeeDTO findEmployee(long employeeId) {return employeeDAO.findById(employeeId);}@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)public void saveEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception {EmployeeDTO employeeDTO = employeeDAO.findById(employeeId);if(employeeDTO == null) {employeeDTO = new EmployeeDTO(employeeId, name,surname, jobDescription);employeeDAO.persist(employeeDTO);}}@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)public void updateEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception {EmployeeDTO employeeDTO = employeeDAO.findById(employeeId);if(employeeDTO != null) {employeeDTO.setEmployeeName(name);employeeDTO.setEmployeeSurname(surname);employeeDTO.setJob(jobDescription);}}@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)public void deleteEmployee(long employeeId) throws Exception {EmployeeDTO employeeDTO = employeeDAO.findById(employeeId);if(employeeDTO != null)employeeDAO.remove(employeeDTO);}@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)public void saveOrUpdateEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception {EmployeeDTO employeeDTO = new EmployeeDTO(employeeId, name,surname, jobDescription);employeeDAO.merge(employeeDTO);notificationsProducer.sendNotification("Save Or Update Employee with values : \nID : " + employeeId + "\nName : " + name + "\nSurname : " + surname + "\nJob description : " + jobDescription);}}如您所見,“ EmployeeServiceController”充當(dāng)“ employeeService”類的包裝器類。 我們參考了實(shí)際的服務(wù),并實(shí)現(xiàn)了直接調(diào)用服務(wù)功能的方法。 要將具有“控制器”功能的“ EmployeeServiceController”類注入,我們只需對(duì)其進(jìn)行注釋即可。 @Controller批注表示已批注的類是“ Controller”類,可用于“ DispatcherServlet”將請(qǐng)求委托給它。
在本教程的開始,我們談到了“ DispatcherServlet”如何使用“ HandlerMappings”來選擇適當(dāng)?shù)摹?Controllers”以委派用戶請(qǐng)求。 @RequestMapping批注用于將Web請(qǐng)求映射到特定的處理程序類和/或處理程序方法。 因此,通過在類型級(jí)別使用@RequestMapping(“ / employeeService”)批注,我們指示“ DispatcherServlet”將“ / employeeService”資源URI下的所有Web請(qǐng)求委托給“ EmployeeServiceController”實(shí)例。 此外,我們?cè)诜椒?jí)別使用@RequestMapping批注,以根據(jù)請(qǐng)求的資源URI將“ DispatcherServlet”委派范圍縮小到特定操作。 您應(yīng)該已經(jīng)注意到@PathVariable注釋的使用。 在Spring 3中,引入了通過@PathVariable注釋使用URI模板的方法。 URI模板是URI –類似于字符串,包含一個(gè)或多個(gè)變量名。 當(dāng)這些變量代替值時(shí),模板將成為URI。 因此,對(duì)“ / employeeService / 1”資源URI的客戶端HTTP GET請(qǐng)求將委派給我們的“ EmployeeServiceController”實(shí)例的“ findEmployee”操作,并且“ employeeId”參數(shù)的值將設(shè)置為1。
注意:僅當(dāng)調(diào)度程序中存在相應(yīng)的“ HandlerMapping”(用于類型級(jí)別的注釋)和/或“ HandlerAdapter”(用于方法級(jí)別的注釋)時(shí),才會(huì)處理@RequestMapping。 由于Spring 3 MVC的簡(jiǎn)化,在“ dispatcher-servlet.xml”中使用“ mvc:annotation-driven”配置元素可以滿足我們的所有配置需求。
在本教程的開始,我們談到了“控制器”如何通過調(diào)用適當(dāng)?shù)姆?wù)方法來處理每個(gè)請(qǐng)求,并將“ ModeAndView”對(duì)象返回到“ DispatcherServlet”。 “ ModeAndView”對(duì)象包含模型數(shù)據(jù)和視圖名稱,以便正確地呈現(xiàn)給客戶端。 這種行為并不總是令人滿意的。 例如,在我們的示例中,我們想將服務(wù)響應(yīng)序列化到HTTP響應(yīng)主體。 可以將@ResponseBody批注放置在方法上,并指示應(yīng)將返回類型直接寫到HTTP響應(yīng)主體(而不是放置在Model中或解釋為視圖名稱)。 根據(jù)客戶端接受的內(nèi)容類型(信息來自客戶端請(qǐng)求的“ Accept” HTTP Header字段),我們將返回服務(wù)回復(fù)的XML或JSON表示形式。 為此,我們通過Spring OXM模塊和Jackson JSON處理器使用JAXB編組器和解組器。
最后,您應(yīng)該注意到“ saveEmployee”和“ updateEmployee”操作。 這兩個(gè)沒有@ResponseBody批注,并返回“ redirect:/ restServices / employeeService / + employeeId”字符串。 “ Controller”方法可以返回“特殊” String值,該值會(huì)向“ DispatcherServlet”發(fā)出命令。 使用上述重定向命令,“ DispatcherServlet”會(huì)將調(diào)用重定向到與指定URI資源關(guān)聯(lián)的“ Controller”方法(在我們的示例中為“ findEmployee”操作)。 因此,當(dāng)客戶端發(fā)出“ saveEmployee”或“ updateEmployee”命令時(shí),將收到剛剛插入或更新的“ employeeDTO”對(duì)象的XML或JSON表示作為答復(fù)。
下面我們介紹DTO類。
package com.javacodegeeks.gwtspring.shared.dto;import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table;import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy;@Cache (usage=CacheConcurrencyStrategy.TRANSACTIONAL) @Entity @XmlRootElement @Table(name = "EMPLOYEE") public class EmployeeDTO implements java.io.Serializable {private static final long serialVersionUID = 7440297955003302414L;@Id@Column(name="employee_id")private long employeeId;@Column(name="employee_name", nullable = false, length=30)private String employeeName;@Column(name="employee_surname", nullable = false, length=30)private String employeeSurname;@Column(name="job", length=50)private String job;public EmployeeDTO() {}public EmployeeDTO(int employeeId) {this.employeeId = employeeId; }public EmployeeDTO(long employeeId, String employeeName, String employeeSurname,String job) {this.employeeId = employeeId;this.employeeName = employeeName;this.employeeSurname = employeeSurname;this.job = job;}public long getEmployeeId() {return employeeId;}public void setEmployeeId(long employeeId) {this.employeeId = employeeId;}public String getEmployeeName() {return employeeName;}public void setEmployeeName(String employeeName) {this.employeeName = employeeName;}public String getEmployeeSurname() {return employeeSurname;}public void setEmployeeSurname(String employeeSurname) {this.employeeSurname = employeeSurname;}public String getJob() {return job;}public void setJob(String job) {this.job = job;} }這里唯一需要注意的是,我們已經(jīng)用@XmlRootElement注釋對(duì)DTO類進(jìn)行了注釋,以便被JAXB編組器正確編組。
而已! 要部署Web應(yīng)用程序,只需將/ war文件夾復(fù)制到Apache – Tomcat “ webapps”文件夾中。 您可以將war文件夾的名稱更改為自己喜歡的名稱,最好在項(xiàng)目名稱之后將其重命名,例如GWTSpringInfinispanHornetQRemoting
在午餐之前,應(yīng)用程序不要忘記創(chuàng)建數(shù)據(jù)庫模式,這里是“ javacodegeeks”。
在此示例中,我們使用了Apache Derby數(shù)據(jù)庫版本10.6.1.0。 您可以在此處下載二進(jìn)制發(fā)行版。 在發(fā)行版的/ lib目錄下找到derby.jar并將其放置在項(xiàng)目的/ war / WEB-INF / lib目錄下。 要使用Spring配置嵌入式數(shù)據(jù)庫,請(qǐng)?jiān)? war / WEB-INF目錄下的applicationContext.xml中添加以下配置代碼:
<bean id="dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"><property name="uniqueResourceName" value="javacodegeeks" /><property name="xaDataSourceClassName" value="org.apache.derby.jdbc.EmbeddedXADataSource" /><property name="xaProperties"><props><prop key="databaseName">javacodegeeks</prop><prop key="createDatabase">create</prop></props></property><property name="maxPoolSize" value="50" /><property name="minPoolSize" value="20" /> </bean>您可以下載RESTClient并測(cè)試“ employeeService”的REST接口,如下所示:
- 發(fā)出“ http:// localhost:8080 / GWTSpringInfinispanHornetQRemoting / restServices / employeeService / 1 / myName / mySurname / myJob”的POST請(qǐng)求,然后應(yīng)檢索新創(chuàng)建的“ employeeDTO”的XML表示形式,如下所示:
- 對(duì)http:// localhost:8080 / GWTSpringInfinispanHornetQRemoting / restServices / employeeService / 1發(fā)出GET請(qǐng)求,通過POST操作將收到相同的結(jié)果
- 發(fā)出PUT請(qǐng)求,并從“ employeeDTO”對(duì)象更新您喜歡的任何字段。 該服務(wù)將以更新的“ employeeDTO” XML表示形式進(jìn)行回復(fù)
- 對(duì)http:// localhost:8080 / GWTSpringInfinispanHornetQRemoting / restServices / employeeService / 1發(fā)出DELETE請(qǐng)求,您將收到“確定”答復(fù)!
- 在添加HTTP標(biāo)頭指令以將接受的內(nèi)容類型定義為“ application / json”后,發(fā)出上述命令。 返回的“ employeeDTO”表示應(yīng)如下所示:
您可以從此處下載該項(xiàng)目(如開頭所述,并且不包含先前的文章,所需的第三方庫)
玩得開心!
賈斯汀
相關(guān)文章 :- GWT 2 Spring 3 JPA 2 Hibernate 3.5教程
- GWT Spring和Hibernate進(jìn)入數(shù)據(jù)網(wǎng)格世界
- Spring 3 HornetQ 2.1集成教程
- GWT 2 Spring 3 JPA 2 Hibernate 3.5教程– Eclipse和Maven 2展示
- 具有Spring和Maven教程的JAX–WS
翻譯自: https://www.javacodegeeks.com/2010/06/spring-3-restful-web-services.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的Spring 3 RESTful Web服务的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小米VR设备(小米VR软件)
- 下一篇: 路由器怎么直接连接校园网校园网如何连接华