曾静的技术博客

但行好事,莫问前程.

嗨,我是曾静 (@devzeng),目前暂居深圳。


这是我用来记录平日学习笔记的地方,欢迎您的访问.

使用Jersey开发REST服务

REST 是英文 Representational State Transfer 的缩写,有中文翻译为“表述性状态转移”。REST 这个术语是由 Roy Fielding 在他的博士论文 《 Architectural Styles and the Design of Network-based Software Architectures 》中提出的。REST 并非标准,而是一种开发 Web 应用的架构风格,可以将其理解为一种设计模式。REST 基于 HTTP,URI,以及 XML 这些现有的广泛流行的协议和标准,伴随着 REST,HTTP 协议得到了更加正确的使用。

Jersy是一个业内使用非常广泛的Java Rest框架,本文就Jersey(2.13版本)的快速使用进行简单介绍,如需要了解更多的高级用法请查看官方的文档。

1、在pom.xml中加入jersey相关依赖

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-grizzly2-servlet</artifactId>
    <version>2.13</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet-core</artifactId>
    <version>2.13</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.13</version>
</dependency>

2、配置web.xml文件

<servlet>
    <servlet-name>Jersey REST Service</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.devzeng.demo.api</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Jersey REST Service<rvlet-name>
	<url-pattern>/api/*</url-pattern>
</servlet-mapping>

3、开发

@Path("/api")
public class HelloApiService {

    @POST
	@Path("save")
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	@Produces(MediaType.APPLICATION_JSON)
	public String save(@FormParam("data") String data) {
		return "{\"message\":\"save\"}";
	}
	
	@GET
	@Path("list")
	@Produces(MediaType.APPLICATION_JSON)
	public String list(@QueryParam("from") String from, @QueryParam("to") String to) {
		return "{\"message\":\"list\"}"; 
	}
	
	@GET
	@Path("detail/{id}")
	@Produces(MediaType.APPLICATION_JSON)
	public String detail(@PathParam("id") String id) {
		return "{\"message\":\"detail\"}"; 
	}
}

说明:

(1)跨域问题解决

如果编写的API接口需要给前端进行调用,通常会遇到跨域的问题,可以使用下面的方式进行解决:

@Provider
public class SceduleApiServiceCorsFilter implements ContainerResponseFilter {

	public void filter(ContainerRequestContext creq, ContainerResponseContext cres) throws IOException {
		cres.getHeaders().add("Access-Control-Allow-Origin", "*");
        cres.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
        cres.getHeaders().add("Access-Control-Allow-Credentials", "true");
        cres.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
        cres.getHeaders().add("Access-Control-Max-Age", "1209600");
	}
	
}

(2)JSON & XML处理

对于REST的接口通常需要返回的数据格式是JSON、XML。如果每次都是使用JSONObject这样的库来进行拼接,也是一件很麻烦的事情,为何不能直接返回对应的POJO对象呢。Jersey就支持这样的处理,为了让项目结构比较清晰,推荐建立一个单独的package(如com.devzeng.rest.pojo),在该package创建一个POJO对象MyCustomBean

public class MyCustomBean {

    private String name;
    private int age;

    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
}
1)JSON处理
@GET
@Path("hellojson")
@Produces(MediaType.APPLICATION_JSON)
public MyCustomBean sayHelloWithJson() {
    MyCustomBean bean = new MyCustomBean();
    bean("tom");
    bean.setAge(20);
    return bean;
}

说明:

Produces注解需要指定返回的数据格式是JSON格式(MediaType.APPLICATION_JSON)。

② 如果启动之后报如下错误:

org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo

表示POJO对象没有被序列化成JSON对象,需要添加相关的库,推荐使用jersey-media-json-jackson模块:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.13</version>
</dependency>
2) XML处理
@GET
@Path("helloxml")
@Produces(MediaType.APPLICATION_XML)
public MyCustomBean sayHelloWithXML() {
    MyCustomBean bean = new MyCustomBean();
    bean("tom");
    bean.setAge(20);
    return bean;
}

Produces注解需要指定返回的数据格式是XML格式(MediaType.APPLICATION_XML)。

② 启动项目之后如果报如下错误:

org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo

需要在POJO对象上面加上@XmlRootElement@XmlRootElement表示将一个类或者是枚举类型映射成为一个XML元素。

(3)中文乱码问题

1) 推荐将项目的所有格式设置为UTF-8;

2) 如果还存在中文乱码的问题,需要将

@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")

参考资料

1.《Jersey官方文档》

2.《REST 实战》

最近的文章

Windows环境下OpenSSL的编译和使用

OpenSSL是目前使用的非常广泛的加密算法库,基本上我们日常使用到的HTTPS、SSH都离不开它的身影。本文就在Windows环境下面编译最新版本的OpenSSL的步骤进行整理。编译OpenSSL1.编译环境准备(1) perlOpenSSL的编译需要使用到perl的环境,如果之前安装过可以跳过此步骤。1) 下载perl安装包根据操作系统的版本下载对应最新版本的perl(当前最新的版本是5.22.3.2204),下载地址是:https://www.activestate.com/acti...…

C++继续阅读
更早的文章

iOS中使用Jenkins搭建持续集成环境

在持续集成(Continuous integration,简称CI)这块,Jenkins无疑是目前使用的比较多的一个开源框架。本文就如何快速搭建一个iOS的持续集成环境进行介绍。Jenkins安装系统要求:必须安装JDK 1.5以上版本,推荐安装最新版本的JDK。可以通过java -version查看是否安装JDK。$ java -version java version "1.8.0_91"Java(TM) SE Runtime Environment (build 1.8.0_91-b...…

iOS继续阅读