核心服务器(Core Server) 通过提供JSR 311中标准化的注释和API标准化,可以用直观的方式开发RESTful Web服务。
核心客户端(Core Client) Jersey客户端API能够帮助开发者与RESTful服务轻松通信;
集成(Integration) Jersey还提供可以轻松继承Spring、Guice、Apache Abdera的库。
本节使用Jersey集成Spring搭建。
1.spring web基础环境
eclipse的Maven Web工程,工程名为testRest。集成spring并创建简单的Teacher模块,包含POJO、SERVICE、DAO层简单代码,使用spring注解注入bean。
见 spring mvc系列,第六篇使用springmvc实现了REST。
后续各框架陆续并入该工程。
2.REST地址
设计jersey模块rest接口地址:
/jersey/teachers GET 获取所有资源
/jersey/teachers POST 创建新资源,content中包含资源内容
/jersey/teacher/{id} GET 获取编号为id的资源
/jersey/teacher/{id} PUT 更新编号为id的资源,content中包含资源内容
/jersey/teacher/{id} DELETE 删除编号为id的资源
3.jersey库
在项目pom.xml中加入Jersey依赖:
2.25.1 ... org.glassfish.jersey.containers jersey-container-servlet ${jersey.version} org.glassfish.jersey.core jersey-client ${jersey.version} org.glassfish.jersey.ext jersey-spring3 ${jersey.version} org.springframework spring org.springframework spring-core org.springframework spring-web org.springframework spring-beans org.springframework spring-context ... org.codehaus.jackson jackson-jaxrs 1.8.11
使用Jersey老版本2.25.1,与spring4集成也可使用jersey-spring3包。不使用jersey-client调用api可不载入该依赖。
4.Servlet
配置Jersey访问入口。
Jersey REST Service org.glassfish.jersey.servlet.ServletContainer javax.ws.rs.Application com.sunbin.test.jersey.JerseyConfig 1 Jersey REST Service /jersey/*
Jersey Servlet将拦截/jersey/*下的所有访问。
因为Jersey服务必须通过容器来访问,实践过程中发现直接在web.xml中配置:
不生效,还是需要实现Application来设置扫描的包路径。
新增JerseyConfig类:
package com.sunbin.test.jersey; import org.glassfish.jersey.server.ResourceConfig; import org.codehaus.jackson.jaxrs.JacksonJsonProvider; // TODO: Auto-generated Javadoc /** * The Class JerseyConfig. */ public class JerseyConfig extends ResourceConfig { /** * Instantiates a new jersey config. */ public JerseyConfig() { // 配置扫描包 packages("com.sunbin.test.jersey"); // 配置json转换。配置后如果api定义返回类型为json、且pojo注解XmlRootElement,将自动转为json返回;否则需要自己转换 register(JacksonJsonProvider.class); } }
Jersey将com.sunbin.test.jersey包下的类中的注解,转换为REST服务。
5.实现api
在com.sunbin.test.jersey新增TeachersResource类,以实现/teachers路径的接口:
package com.sunbin.test.jersey; import java.util.HashMap; import java.util.Map; import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.springframework.beans.factory.annotation.Autowired; import com.sunbin.test.teacher.pojo.Teacher; import com.sunbin.test.teacher.service.TeacherService; @Path("teachers") @Produces(MediaType.APPLICATION_JSON) public class TeachersResource { @Autowired private TeacherService teacherService; @GET public Map get() { System.out.println("Jersey TeachersResource.get"); Map map = new HashMap(); map.put("teachers", teacherService.list()); return map; } @POST public Map post(@FormParam("age") int age, @FormParam("name") String name) { Map map = new HashMap(); try { Teacher teacher = new Teacher(); teacher.setName(name); teacher.setAge(age); System.out.println("Jersey TeachersResource.post:" + teacher); teacherService.save(teacher); map.put("status", "y"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return map; } }
用到了以下JAX-RS注解:
@Path("teachers")绑定路径:/servlet路径/teachers。可在类和方法上加注解。
@Produces(MediaType.APPLICATION_JSON)支持返回类型:application/json。可支持多种类型,按请求header:AcceptType返回。
@GET:GET请求的响应方法。
@POST:POST请求的响应方法。
@FormParam("age") int age, @FormParam("name") String name:获取通过application/x-www-form-urlencoded方式提交的参数。
新增TeacherResource类,以实现/teacher/{id}路径的接口:
package com.sunbin.test.jersey; import java.util.HashMap; import java.util.Map; import javax.ws.rs.DELETE; import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.springframework.beans.factory.annotation.Autowired; import com.sunbin.test.teacher.pojo.Teacher; import com.sunbin.test.teacher.service.TeacherService; @Path("teacher/{id}") @Produces(MediaType.APPLICATION_JSON) public class TeacherResource { @Autowired private TeacherService teacherService; @GET public Map get(@PathParam("id") int id) { System.out.println("Jersey TeacherResource.get:" + id); Teacher teacher = new Teacher(); teacher.setId(id); Map map = new HashMap(); map.put("teacher", teacherService.get(teacher)); return map; } @PUT public Map put(@PathParam("id") int id, @FormParam("age") int age, @FormParam("name") String name) { Map map = new HashMap(); try { Teacher teacher = new Teacher(); teacher.setId(id); teacher.setName(name); teacher.setAge(age); System.out.println("Jersey TeacherResource.put:" + id + ":" + teacher); teacherService.update(teacher); map.put("status", "y"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return map; } @DELETE public Map delete(@PathParam("id") int id) { Map map = new HashMap(); try { System.out.println("Jersey TeacherResource.delete:" + id); Teacher teacher = new Teacher(); teacher.setId(id); teacherService.remove(teacher); map.put("status", "y"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return map; } }
用到了以下JAX-RS注解:
@PathParam("id"):获取路径参数{id}
@PUT:PUT请求的响应方法。
@DELETE:DELETE请求的响应方法。
6.js测试
Jersey不像springmvc一样,可以通过在POST form中增加_method=PUT/DELETE隐藏参数的方法来支持表单直接提交PUT/DELETE,所以要通过javascript或者程序来访问。
先使用jquery库来进行ajax访问测试。
在src\main\webapp\rest目录下新建index.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %>teacher save
list
id | name | age | 操作 |
重新部署后,使用浏览器访问 http://localhost:8080/testRest/rest,可以看到页面:
通过js访问REST api,就类似网站使用第三方登录(QQ、微博等)后访问用户头像昵称的过程,当然登录时一般使用OAUTH2.0 做认证方案。
7.JerseyClient测试
Jersey提供Client库用于测试JAX-RS接口。Client不仅可用来测Jersey REST,也可以用来测试其他框架实现的接口和http服务。
新建TestJersey类,代码如下:
package com.sunbin.test.jersey; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.Form; public class TestJersey { public static final String URL_BASE = "http://localhost:8080/testRest/jersey/"; public static void main(String[] args) { Client client = ClientBuilder.newClient(); String module = "teacher"; String url = ""; String result = ""; Entity