javascript
Jersey和Spring Boot入门
除了許多新功能,Spring Boot 1.2還帶來了Jersey支持。 這是吸引喜歡標準方法的開發人員的重要一步,因為他們現在可以使用JAX-RS規范構建RESTful API,并將其輕松部署到Tomcat或任何其他Spring's Boot支持的容器中。 帶有Spring平臺的Jersey可以在mico服務的開發中發揮重要作用。 在本文中,我將演示如何使用Spring Boot(包括:Spring Data,Spring Test,Spring Security)和Jersey快速構建應用程序。
引導一個新項目
該應用程序是常規的Spring Boot應用程序,它使用Gradle及其最新的2.2版本。 Gradle不如Maven冗長,它特別適合Spring Boot應用程序。 可以從Gradle網站下載Gradle: http : //www.gradle.org/downloads 。
啟動項目的初始依賴項:
dependencies {compile("org.springframework.boot:spring-boot-starter-web")compile("org.springframework.boot:spring-boot-starter-jersey")compile("org.springframework.boot:spring-boot-starter-data-jpa")// HSQLDB for embedded database supportcompile("org.hsqldb:hsqldb")// Utilitiescompile("com.google.guava:guava:18.0")// AssertJtestCompile("org.assertj:assertj-core:1.7.0")testCompile("org.springframework.boot:spring-boot-starter-test") }應用程序入口點是一個包含main方法的類,并使用@SpringBootApplication注釋進行注釋:
@SpringBootApplication public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);} }@SpringBootApplication注釋是一個便捷注釋,等效于聲明@Configuration @EnableAutoConfiguration , @ComponentScan @EnableAutoConfiguration和@ComponentScan ,它是Spring Boot 1.2的新增功能。
球衣配置
入門就像創建用@Path和Spring的@Component注釋的根資源一樣容易:
@Component @Path("/health") public class HealthController {@GET@Produces("application/json")public Health health() {return new Health("Jersey: Up and Running!");} }并將其注冊在從Jersey ResourceConfig擴展的Spring的@Configuration類中:
@Configuration public class JerseyConfig extends ResourceConfig {public JerseyConfig() {register(HealthController.class);} }我們可以使用gradlew bootRun啟動該應用程序,訪問: http:// localhost:8080 / health ,我們應該看到以下結果:
{"status": "Jersey: Up and Running!" }但是也可以編寫一個具有完全加載的應用程序上下文的Spring Boot集成測試:
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration @IntegrationTest("server.port=9000") public class HealthControllerIntegrationTest {private RestTemplate restTemplate = new TestRestTemplate();@Testpublic void health() {ResponseEntity<Health> entity = restTemplate.getForEntity("http://localhost:9000/health", Health.class);assertThat(entity.getStatusCode().is2xxSuccessful()).isTrue();assertThat(entity.getBody().getStatus()).isEqualTo("Jersey: Up and Running!");} }Jersey 2.x具有本機Spring支持( jersey-spring3 ),Spring Boot通過spring-boot-starter-jersey起動器為其提供了自動配置支持。 有關更多詳細信息,請查看JerseyAutoConfiguration類。
根據spring.jersey.type屬性值,Jersey Servlet或Filter都注冊為Spring Bean:
Mapping servlet: 'jerseyServlet' to [/*]可以通過添加到ResourceConfig配置類的javax.ws.rs.ApplicationPath批注來更改默認映射路徑:
@Configuration @ApplicationPath("/jersey") public class JerseyConfig extends ResourceConfig {}JSON媒體類型支持隨附有jersey-media-json-jackson依賴項,該依賴項注冊了可供Jersey使用的Jackson JSON提供程序。
Spring Data JPA集成
Spring Data JPA是較大的Spring Data系列的一部分,可輕松實現基于JPA的存儲庫。 對于那些不熟悉該項目的人,請訪問: http : //projects.spring.io/spring-data-jpa/
客戶和客戶存儲庫
此示例項目的域模型只是具有一些基本字段的Customer :
@Entity public class Customer extends AbstractEntity {private String firstname, lastname;@Columnprivate EmailAddress emailAddress;Customer需要一個@Repository ,因此我們使用Spring的Data倉庫創建了一個基本的倉庫。 通過簡單的接口定義,Spring Data存儲庫減少了許多樣板代碼:
public interface CustomerRepository extends PagingAndSortingRepository<Customer, Long> {}使用域模型后,可以方便地使用一些測試數據。 最簡單的方法是為data.sql文件提供要在應用程序啟動時執行的SQL腳本。 該文件位于src/main/resources ,Spring會自動將其拾取。 該腳本包含幾個SQL插入內容以填寫customer表。 例如:
insert into customer (id, email, firstname, lastname) values (1, 'joe@doe.com', 'Joe', 'Doe');客戶總監
在使用Spring Data JPA存儲庫之后,我創建了一個控制器(以JAX-RS –資源表示),該控制器允許對Customer對象進行CRUD操作。
注意:我堅持使用HTTP端點的Spring MVC命名約定,但可以隨意使用JAX-RS方式。
獲得客戶
讓我們從返回所有客戶的方法開始:
@Component @Path("/customer") @Produces(MediaType.APPLICATION_JSON) public class CustomerController {@Autowiredprivate CustomerRepository customerRepository;@GETpublic Iterable<Customer> findAll() {return customerRepository.findAll();} }使用@Component保證CustomerController是一個Spring托管對象。 @Autowired可以輕松替換為標準javax.inject.@Inject注釋。
由于我們在項目中使用Spring Data,因此我可以輕松利用PagingAndSortingRepository.提供的PagingAndSortingRepository. 我修改了資源方法以支持某些頁面請求參數:
@GET public Page<Customer> findAll(@QueryParam("page") @DefaultValue("0") int page,@QueryParam("size") @DefaultValue("20") int size,@QueryParam("sort") @DefaultValue("lastname") List<String> sort,@QueryParam("direction") @DefaultValue("asc") String direction) {return customerRepository.findAll(new PageRequest(page, size, Sort.Direction.fromString(direction), sort.toArray(new String[0]))); }為了驗證以上代碼,我創建了Spring集成測試。 在第一次測試中,我將要求所有記錄,并且根據先前準備的測試數據,我希望在20頁的1頁中總共有3個客戶:
@Test public void returnsAllPages() {// actResponseEntity<Page<Customer>> responseEntity = getCustomers("http://localhost:9000/customer");Page<Customer> customerPage = responseEntity.getBody();// assertPageAssertion.assertThat(customerPage).hasTotalElements(3).hasTotalPages(1).hasPageSize(20).hasPageNumber(0).hasContentSize(3); }在第二個測試中,我將調用大小為1的第0頁,并按firstname排序,排序方向descending 。 我希望元素總數不變(3),返回的頁面總數為3,返回的頁面內容大小為1:
@Test public void returnsCustomPage() {// actResponseEntity<Page<Customer>> responseEntity = getCustomers("http://localhost:9000/customer?page=0&size=1&sort=firstname&direction=desc");// assertPage<Customer> customerPage = responseEntity.getBody();PageAssertion.assertThat(customerPage).hasTotalElements(3).hasTotalPages(3).hasPageSize(1).hasPageNumber(0).hasContentSize(1); }該代碼也可以使用curl檢查:
$ curl -i http://localhost:8080/customerHTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: application/json;charset=UTF-8 Content-Length: 702 Date: Sat, 03 Jan 2015 14:27:01 GMT{...}請注意,為了輕松測試RestTemplate的分頁,我創建了一些幫助程序類: Page , Sort和PageAssertion 。 您可以在Github中的應用程序源代碼中找到它們。
添加新客戶
在這個簡短的代碼片段中,我使用了Jersey的某些功能,如注入@Context 。 在創建新實體的情況下,我們通常要返回標題中資源的鏈接。 在下面的示例中,我將UriBuilder注入到終結點類中,并使用它來構建新創建的客戶的位置URI:
@Context private UriInfo uriInfo;@POST public Response save(Customer customer) {customer = customerRepository.save(customer);URI location = uriInfo.getAbsolutePathBuilder().path("{id}").resolveTemplate("id", customer.getId()).build();return Response.created(location).build(); }在調用POST方法(不存在電子郵件)時:
$ curl -i -X POST -H 'Content-Type:application/json' -d '{"firstname":"Rafal","lastname":"Borowiec","emailAddress":{"value": "rafal.borowiec@somewhere.com"}}' http://localhost:8080/customer我們將得到:
HTTP/1.1 201 Created Server: Apache-Coyote/1.1 Location: http://localhost:8080/customer/4 Content-Length: 0 Date: Sun, 21 Dec 2014 22:49:30 GMT當然,也可以創建集成測試。 它使用RestTemplate使用postForLocation方法保存客戶,然后使用getForEntity檢索它:
@Test public void savesCustomer() {// actURI uri = restTemplate.postForLocation("http://localhost:9000/customer",new Customer("John", "Doe"));// assertResponseEntity<Customer> responseEntity =restTemplate.getForEntity(uri, Customer.class);Customer customer = responseEntity.getBody();assertThat(customer.getFirstname()).isEqualTo("John");assertThat(customer.getLastname()).isEqualTo("Doe"); }其他方法
端點的其余方法確實很容易實現:
@GET @Path("{id}") public Customer findOne(@PathParam("id") Long id) {return customerRepository.findOne(id); }@DELETE @Path("{id}") public Response delete(@PathParam("id") Long id) {customerRepository.delete(id);return Response.accepted().build(); }安全
通過向項目添加新的依賴關系,可以快速地將Spring Security添加到應用程序中:
compile("org.springframework.boot:spring-boot-starter-security")使用Spring Security在classpath中,應用程序將通過所有HTTP端點上的基本身份驗證得到保護。 可以使用以下兩個應用程序設置( src/main/resources/application.properties )更改默認的用戶名和密碼:
security.user.name=demo security.user.password=123在使用Spring Security應用程序運行該應用程序之后,我們需要為每個請求提供一個有效的身份驗證參數。 使用curl我們可以使用--user開關:
$ curl -i --user demo:123 -X GET http://localhost:8080/customer/1隨著Spring Security的添加,我們先前創建的測試將失敗,因此我們需要為RestTemplate提供用戶名和密碼參數:
private RestTemplate restTemplate = new TestRestTemplate("demo", "123");分派器Servlet
Spring的Dispatcher Servlet與Jersey Servlet一起注冊,并且它們都映射到根資源 。 我擴展了HealthController ,并向其中添加了Spring MVC請求映射:
@Component @RestController // Spring MVC @Path("/health") public class HealthController {@GET@Produces({"application/json"})public Health jersey() {return new Health("Jersey: Up and Running!");}@RequestMapping(value = "/spring-health", produces = "application/json")public Health springMvc() {return new Health("Spring MVC: Up and Running!");} }通過上面的代碼,我希望根上下文中可以同時使用health和spring-health端點,但顯然不起作用。 我嘗試了幾種配置選項,包括設置spring.jersey.filter.order但沒有成功。
我發現的唯一解決方案是更改Jersey @ApplicationPath或更改Spring MVC server.servlet-path屬性:
server.servlet-path=/s在后一個示例中,調用:
$ curl -i --user demo:123 -X GET http://localhost:8080/s/spring-health返回預期結果:
{"status":"Spring MVC: Up and Running!" }使用Undertow代替Tomcat
從Spring Boot 1.2開始,支持Undertow輕量級高性能Servlet 3.1容器。 為了使用Undertow代替Tomcat,必須將Tomcat依賴項與Undertow的依賴項交換:
buildscript {configurations {compile.exclude module: "spring-boot-starter-tomcat"} } dependencies {compile("org.springframework.boot:spring-boot-starter-undertow:1.2.0.RELEASE") }運行該應用程序時,日志將包含:
org.xnio: XNIO version 3.3.0.Final org.xnio.nio: XNIO NIO Implementation Version 3.3.0.Final Started Application in 4.857 seconds (JVM running for 5.245)摘要
在這篇博客文章中,我演示了一個簡單的示例,說明如何開始使用Spring Boot和Jersey。 由于Jersey的自動配置,向Spring應用程序添加JAX-RS支持非常容易。
通常,Spring Boot 1.2使使用Java EE的應用程序構建更加容易:使用Atomikos或Bitronix嵌入式事務管理器進行JTA事務,在JEE Application Server中對DataSource和JMS ConnectionFactory進行JNDI查找,并簡化JMS配置。
資源資源
- 項目源代碼: https : //github.com/kolorobot/spring-boot-jersey-demo
- 后續: 使用JAX-RS和Spring構建HATEOAS API
翻譯自: https://www.javacodegeeks.com/2015/01/getting-started-with-jersey-and-spring-boot.html
總結
以上是生活随笔為你收集整理的Jersey和Spring Boot入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 绿萝的样子和特点 绿萝的样子和特点是什么
- 下一篇: Spring Stateless Sta