创建框架
执行命令,创建一个最基础的应用脚手架
1 2 3 4
| mvn archetype:generate -DarchetypeArtifactId=jersey-quickstart-webapp -DarchetypeGroupId=org.glassfish.jersey.archetypes -DinteractiveMode=false -DgroupId=com.example -DartifactId=simple-service-webapp -Dpackage=com.example -DarchetypeVersion=2.16
|
该脚手架使用的是servlet 2.5,主要关注两个地方:
web.xml
要声明入口的servlet以及要扫描的资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>com.example</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey Web Application</servlet-name> <url-pattern>/webapi/*</url-pattern> </servlet-mapping> </web-app>
|
pom.xml
使用的依赖包为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey</groupId> <artifactId>jersey-bom</artifactId> <version>2.17</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet-core</artifactId> </dependency> </dependencies>
|
如果使用的是servlet 3.0,则以上两个地方分别为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| web.xml <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <!-- Servlet declaration can be omitted in which case it would be automatically added by Jersey --> <servlet> <servlet-name>javax.ws.rs.core.Application</servlet-name> </servlet> <servlet-mapping> <servlet-name>javax.ws.rs.core.Application</servlet-name> <url-pattern>/webapi/*</url-pattern> </servlet-mapping> </web-app>
|
1 2 3 4 5
| pom.xml <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> </dependency>
|
当然,上述web.xml
中的入口也可以配置成Application的子类,并在该子类中声明好各种配置信息,那样在web.xml
中就不需要再配置了,对servlet2.5,可以只保留空的web.xml;对于servlet3.0,可以不需要web.xml
添加响应GET
的rest服务
增加一个类,声明@Path
注解
1 2 3 4 5
| @Path("/item") public class ItemService { ...... }
|
添加一个方法响应GET
请求
1 2 3 4 5 6 7 8 9
| @Path("/item") public class ItemService { @GET @Produces(MediaType.APPLICATION_JSON) public String get() { return "item1"; } }
|
在web.xml
中添加入口servlet的配置
1 2 3 4 5 6 7 8 9 10 11 12 13
| <servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>com.louz.gds</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey Web Application</servlet-name> <url-pattern>/webapi/*</url-pattern> </servlet-mapping>
|
访问http://localhost:8080/simple-service-webapp/webapi/item
即可看到页面显示item1
还可以在方法中声明子资源
1 2 3 4 5 6
| @GET @Path("{id}") @Produces(MediaType.APPLICATION_JSON) public String getById(@PathParam("id") String id) { return id; }
|
访问http://localhost:8080/simple-service-webapp/webapi/item/1
即可看到页面显示1
如何接收POST请求
1. 使用JSON-P
首先需要增加对json的支持,先在pom.xml
增加如下的依赖
1 2 3 4
| <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-processing</artifactId> </dependency>
|
后台的service方法:
1 2 3 4 5 6 7
| @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public JsonObject getItem(JsonObject item) { // 使用JsonObject接收请求的json串 System.out.println(item); return item; }
|
2. 使用MOXy
首先需要增加对json的支持,先在pom.xml
增加如下的依赖
1 2 3 4
| <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-moxy</artifactId> </dependency>
|
后台的service方法:
1 2 3 4 5 6 7
| @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public Item getItem(Item item) { System.out.println(item.getId()); return item; }
|
注意:
无论是JSON-P
还是MOXy
,对客户端传过来的json串都有比较严格的格式要求,如果不符合的话,会报参数解析出错或者其他奇奇怪怪的错,正确的json串格式应该是:
{"属性名1": 值1, "属性名2": 值2}
,属性名两边的双引号一定要有!可以利用JSON.stringify(jsonObj)
方法对json对象进行字符串化,以下是使用jQuery
的前端代码样例:
1 2 3 4 5 6 7 8 9 10 11
| $.ajax({ url: "webapi/item", type: "POST", // data: JSON.stringify({id: 1}), 效果与下一行的一样 data: '{"id": 1}', success: function (data) { alert(data.id); }, contentType: "application/json", dataType: "json" });
|
如何做单元测试
下面例子使用JSON-P
进行描述。首先在pom.xml
增加jersey的单元测试框架依赖:
1 2 3 4 5 6 7 8 9 10 11
| <dependency> <groupId>org.glassfish.jersey.test-framework</groupId> <artifactId>jersey-test-framework-core</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.glassfish.jersey.test-framework.providers</groupId> <artifactId>jersey-test-framework-provider-grizzly2</artifactId> <scope>test</scope> </dependency>
|
编写测试类(继承JerseyTest
类)即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class ItemServiceTest extends JerseyTest { @Override protected Application configure() { final ResourceConfig config = new ResourceConfig(GridStrategyResource.class); // 为便于调试,一般启用以下两个选项 enable(TestProperties.LOG_TRAFFIC); enable(TestProperties.DUMP_ENTITY); return config; } @Test public void testPostItem() { JsonObject doc = Json.createObjectBuilder() .add("id", "1") .build(); final Response response = target("item").request(MediaType.APPLICATION_JSON_TYPE).post(Entity.json(doc)); System.out.println(response); assertEquals(200, response.getStatus()); } }
|
与spring集成
首先在pom.xml
引入相关依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| <dependencyManagement> <dependencies> ... <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>3.2.13.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> ... <dependencies> <dependency> <groupId>org.glassfish.jersey.ext</groupId> <artifactId>jersey-spring3</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> </dependencies>
|
在web.xml
声明spring的配置文件位置
1 2 3 4 5 6 7 8
| <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
|
增加spring的配置文件:
1 2 3 4 5 6 7 8 9 10 11 12
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.louz.gds"/> </beans>
|
Spring的bean可以在上面的配置文件中声明,也可以通过@Component/@Repository/@Service/@Controller
的方式声明。
Jersey的资源类注入Spring的bean可以通过以下方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Path("/item") public class ItemService { // @Resource(name = "itemDao") 如果该类没有声明成@Component,@Resource无法生效 @Autowired @Qualifier("itemDao") // @Autowired默认按类注入,使用@Qualifier可以按bean名称注入 // @Inject // @Named("itemDao") // 与使用@Autowired+@Qualifier等效 private ItemDao myItemDao; ... } @Repository(value = "itemDao") public class ItemDao { public void saveItem(JsonObject item) { System.out.println("save in dao"); } }
|
注意,当Jersey与spring集成测试时,Jersey容器默认加载classpath:applicationContext.xml
文件作为spring的配置文件,如果要加载指定文件,需要做以下处理:
1 2 3 4 5 6 7 8 9 10
| public class ResourceTest extends JerseyTest { @Override protected Application configure() { final ResourceConfig config = new ResourceConfig(Resource.class); config.property("contextConfigLocation", "classpath:my.spring.xml"); // 该参数名和值与web.xml里配置的一致 return config; } ......
|