boot jersey_Jersey和Spring Boot入门

boot jersey

除了许多新功能,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 starter为它提供自动配置支持。 有关更多详细信息,请查看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测试分页,我创建了一些帮助程序类: PageSortPageAssertion 。 您可以在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!");}
}

通过以上代码,我希望根上下文中可以同时使用healthspring-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

boot jersey

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/338641.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mime类型是什么 node_Node.js - 文件系统获取文件类型

我需要借助node.js来获取文件的文件类型以设置内容类型。我知道我可以很容易地检查文件扩展名&#xff0c;但我也有没有扩展名的文件&#xff0c;其内容类型应该是image/png,text/html aso。Node.js - 文件系统获取文件类型这是我的代码(我知道这并没有太大的意义&#xff0c;但…

函数或全局变量重复定义时会怎样?

可能有些朋友第一反应是&#xff0c;那肯定是编译不过喽&#xff1a;// fun.c #include void func() {printf("编程珠玑\n"); }// main.c #include void func() {printf("公众号\n"); } int main(void) {func();return 0; }编译&#xff1a;$ gcc -o main …

c语言开源编辑器,一个C语言编写的跨平台C语言编译器(开源) UCC

很多科班出身的搞开发的同事大都应该学过《编译原理》这门课程&#xff0c;或许也动手做过一些实践。这次向大家推荐一个由清华大学学生完成的C语言编译器实现 -- UCC。这个项目目前位于sf.net网站&#xff0c;开放源代码&#xff0c;代码使用C语言编写&#xff0c;对于理解和实…

java持久性与安全性_Java持久性锁定初学者指南

java持久性与安全性隐式锁定 在并发理论中&#xff0c;锁定用于保护可变共享数据免受危险数据完整性异常的影响。 因为锁管理是一个非常复杂的问题&#xff0c;所以大多数应用程序都依赖于其数据提供程序隐式锁技术。 将整个锁定职责委托给数据库系统既可以简化应用程序开发&a…

c语言实验报告5数组,c语言实验报告五一维数组.doc

c语言实验报告五一维数组《C程序设计》课程实验报告学院&#xff1a; 班级&#xff1a; 姓名&#xff1a; 学号&#xff1a; 实验设备&#xff1a;计算机1台2011年3月1日实验项目名称一维数组掌握一维数组的定义、初始化&#xff0c;以及一维数组元素的下标法引用。实验要求&am…

当C语言函数执行成功时,返回1和返回0究竟哪个好?

基本上&#xff0c;没有人会将大段的C语言代码全部塞入 main() 函数。更好的做法是按照复用率高&#xff0c;耦合性低的原则&#xff0c;尽可能的将代码拆分不同的功能模块&#xff0c;并封装成函数。C语言代码的组合千变万化&#xff0c;因此函数的功能可能会比较复杂&#xf…

ubuntu自定义安装里怎么选_超市里的五香粉怎么选?看懂配料表,两个小技巧,不怕选不好。...

点击右上角【关注】&#xff0c;可获得本头条号推荐的更多美食干货五香粉是家庭常用的一种调味料&#xff0c;焖、炖、烧、煮、卤都常备使用&#xff0c;如今市场上的五香粉品牌也是相当繁多&#xff0c;质量也是参差不齐&#xff0c;有时买到的五香粉烧制的菜肴根本就不好吃&a…

原来C语言还可以这样实现“泛型编程”!

在回答标题问题之前&#xff0c;先了解下什么是泛型编程。泛型编程&#xff08;generic programming&#xff09;是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型&#xff0c;在实例化时作为参数指明这些类型。C支持…

javadoc 标签_新的Javadoc标签@ apiNote,@ implSpec和@implNote

javadoc 标签如果您已经在使用Java 8&#xff0c;则可能会看到一些新的Javadoc标签&#xff1a; apiNote &#xff0c; implSpec和implNote 。 他们怎么了&#xff1f; 如果要使用它们&#xff0c;该怎么办&#xff1f; 总览 该帖子将快速查看标签的来源和当前状态。 然后&…

c语言万年历附加功能,万年历(c语言,多功能).doc

万年历(c语言,多功能)#include "time.h" /*包含的头文件*/#include "stdio.h"#include "math.h"#include "windows.h"#include "conio.h"#define KEYNUMUp 0x48 /*宏定义*/#define KEYNUMDown 0x50#define KEYNUMLeft 0x4b#…

联想小新300加固态_就联想小新 Pro 13 固态硬盘混用一事,官方回应

IT之家11月3日消息 近日有用户反馈称&#xff0c;联想小新Pro 13的部分批次固态硬盘从三星PM981A换成亿联了&#xff0c;因此还出现了退货现象。针对上述情况&#xff0c;联想官方刚刚发表声明回应此事。以下为联想回应全文&#xff1a;有关小新Pro 13固态硬盘(SSD)配置问题的公…

C语言入门基础之输入和输出

标准输入函数在stdio.h中scanf声明如下&#xff1a;/* Read formatted input from stdin.This function is a possible cancellation point and therefore notmarked with __THROW. */ extern int scanf (const char *__restrict __format, ...) __wur;使用Mac或Linux的同学&am…

camel java_与Java EE和Camel的轻量级集成

camel javaEnterprise Java具有不同的风格和观点。 从简单的平台技术&#xff08;众所周知的Java EE&#xff09;开始&#xff0c;到不同的框架和集成方面&#xff0c;最后是涉及以数据为中心的用户界面或特定可视化效果的用例。 Java EE本身无法解决的最突出的问题是“集成”。…

c语言 伪随机数程序,C语言的伪随机数

一直想好好的系统的学习一下C语言的伪随机数&#xff0c;今天终于逮到机会了伪随机数C语言中有可以产生随机数据的函数&#xff0c;需要添加stdlib.h和time.h头文件。首先在main函数开头加上srand(unsigned)time(NULL))。先来介绍一下srand头文件&#xff1a;定义函数&#xff…

最大隶属度原则_模糊数学笔记:六、模糊模型识别-I(最大隶属度原则)

1、模型识别的问题提出模型识别&#xff0c;通俗地理解即是对一个类别未知的对象进行归类&#xff08;或者叫分类&#xff09;。这里与聚类不同的是&#xff0c;聚类实际上是要区分出已有的样本哪些属于同一类&#xff0c;但并没有参考标准。而识别则事先有参考的标准&#xff…

C语言经典题

C 库函数 - tanh()描述C 库函数 double tanh(double x) 返回 x 的双曲正切。声明下面是 tanh() 函数的声明。double tanh(double x)参数x -- 浮点值。返回值该函数返回 x 的双曲正切。实例下面的实例演示了 tanh() 函数的用法。#include#include int main (){ double x, ret;…

用c语言产生大素数,C语言实现寻找大素数

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼找到一亿内所有素数并写入文件用时 35秒.#include "math.h"#include "stdio.h" #include "stdlib.h" #include "time.h"int isP(int num,int *p) { int i; int lenp[0]; int flag1; p;for…

java ee自动生成编码_EE Servlet 3:在Servlet中生成HTML输出

java ee自动生成编码如果您只需要在EE Web模块中处理少量请求URI&#xff0c;那么在Servlet代码中生成自己HTML响应可能比使用完整的模板库更容易。 作为示例的一部分&#xff0c;我尝试了一个非常简单的Java DSL&#xff0c;该Java DSL在编写自己的Serlvet时生成html输出。 代…

jq 控制td只显示一行_CSS让表格里的内容强制显示一行,超出长度显示省略号

在写html页面的时候&#xff0c;会经常用到表格&#xff0c;而且很多时候一个tr里边需要包含好几个td&#xff0c;这样就会导致tr的高度不一致&#xff0c;被撑开了这时候&#xff0c;如果能让td里的内容强制显示在一行&#xff0c;并让超出边界范围的内容显示点点&#xff0c;…

C++11的模板改进

C11关于模板有一些细节的改进&#xff1a;模板的右尖括号模板的别名函数模板的默认模板参数模板的右尖括号C11之前是不允许两个右尖括号出现的&#xff0c;会被认为是右移操作符&#xff0c;所以需要中间加个空格进行分割&#xff0c;避免发生编译错误。int main() {std::vecto…