使用Jersey+Spring+Tomcat构建RESTful Web服务

RESTful Web 服务

REST 在 2000 年由 Roy Fielding 在博士论文中提出,他是 HTTP 规范 1.0 和 1.1 版的首席作者之一。
REST 中最重要的概念是资源(resources),使用全球 ID(通常使用 URI)标识。客户端应用程序使用 HTTP 方法(GET/ POST/ PUT/ DELETE)操作资源或资源集。RESTful Web 服务是使用 HTTP 和 REST 原理实现的 Web 服务。通常,RESTful Web 服务应该定义以下方面:

  • Web 服务的基/根 URI,比如 http://hostname/{appcontext}/resources。
  • 支持 MIME 类型的响应数据,包括 JSON/XML/ATOM 等等。
  • 服务支持的操作集合(例如 POST、GET、PUT 或 DELETE)。

表 1. HTTP 方法操作映射表

方法执行动作示例:http://hostname/{appcontext}/resources/1234
GET查看资源查看ID为1234的资源
POST创建一个资源在下面创建一个子资源
PUT创建或更新一个资源创建或更新ID为1234的资源
DELETE删除资源删除ID为1234的资源

Jersey

Jersey is Sun’s production quality reference implementation for JSR 311: JAX-RS: The Java API for RESTful Web Services. Jersey implements support for the annotations defined in JSR-311, making it easy for developers to build RESTful web services with Java and the Java JVM. Jersey also adds additional features not specified by the JSR.

开发环境

  • JDK 1.7
  • Jersey 2.6
  • Spring 4.2.7.RELEASE
  • Maven 3.3.9
  • Apache Tomcat 7.0.70

配置

1、项目结构

这里写图片描述

2、pom.xml

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jersey.version>2.6</jersey.version>
        <jersey-spring.version>2.23.1</jersey-spring.version>
        <spring.version>4.2.7.RELEASE</spring.version>
        <servlet-api-version>3.1.0</servlet-api-version>
        <logback.version>1.1.1</logback.version>
        <jcloverslf4j.version>1.7.6</jcloverslf4j.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-spring3</artifactId>
            <version>${jersey-spring.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-web</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>${jersey-spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>${jersey-spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-multipart</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-entity-filtering</artifactId>
            <version>${jersey.version}</version>
        </dependency>

        <!-- Spring4.2 dependencies -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet-api-version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- Logback dependencies -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${jcloverslf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

3、web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>
            org.glassfish.jersey.servlet.ServletContainer
        </servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.ricky.codelab.jersey.RestJaxRsApplication</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>
3.1、applicationContext.xml
<?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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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-4.1.xsd">

    <context:component-scan base-package="com.ricky.codelab.jersey"></context:component-scan>


</beans>
3.2、Jersey servlet configuration
package com.ricky.codelab.jersey;

import com.ricky.codelab.jersey.resource.UserResource;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.spring.scope.RequestContextFilter;

/**
 * ${DESCRIPTION}
 *
 * @author Ricky Fung
 * @create 2016-07-20 14:15
 */
public class RestJaxRsApplication extends ResourceConfig {

    /**
     * Register JAX-RS application components.
     */
    public RestJaxRsApplication() {

        // register application resources
        this.register(UserResource.class);

        // register filters
        register(RequestContextFilter.class);
        //register(LoggingResponseFilter.class);
        //register(CORSResponseFilter.class);

        // register exception mappers
        //register(GenericExceptionMapper.class);
        //register(AppExceptionMapper.class);
        //register(NotFoundExceptionMapper.class);

        // register features
        register(JacksonFeature.class);
        //register(MultiPartFeature.class);
    }
}

REST API设计实现

Resources

package com.ricky.codelab.jersey.resource;

import com.ricky.codelab.jersey.domain.User;
import com.ricky.codelab.jersey.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;

/**
 * ${DESCRIPTION}
 *
 * @author Ricky Fung
 * @create 2016-07-20 14:28
 */
@Path("/user")
public class UserResource {

    @Autowired
    private IUserService userService;

    @POST
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces({ MediaType.TEXT_HTML })
    public Response createUser(User user){

        long id = userService.insert(user);

        return Response.status(Response.Status.CREATED)// 201
                .entity("A new user has been created")
                .header("Location",
                        "http://localhost:8888/user/"
                                + String.valueOf(id)).build();
    }

    @POST
    @Consumes({ MediaType.APPLICATION_FORM_URLENCODED })
    @Produces({ MediaType.TEXT_HTML })
    public Response createUserApplicationFormURLencoded(
            @FormParam("name") String name,
            @FormParam("age") Integer age) {

        User user = new User();
        user.setName(name);
        user.setAge(age);
        long id = userService.insert(user);

        return Response
                .status(Response.Status.CREATED)// 201
                .entity("A new user/resource has been created at /user/"
                        + id)
                .header("Location",
                        "http://localhost:8888/user/"
                                + String.valueOf(id)).build();
    }

    //http://localhost:8080/user/1
    @GET
    @Path("/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public User getUserById(@PathParam("id") Long id) {

        return userService.findUserById(id);
    }

    @GET
    @Path("/list")
    @Produces(MediaType.APPLICATION_JSON)
    public List<User> getUserList() {

        return userService.getUserList();
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public User getUserByName(@QueryParam("username") String username) {

        return userService.findUserByName(username);
    }

    @PUT
    @Path("{id}")
    @Consumes({ MediaType.APPLICATION_JSON })
    @Produces({ MediaType.TEXT_HTML })
    public Response putUserById(@PathParam("id") Long id, User user){

        User userById = userService.findUserById(id);

        if (userById == null) {
            // resource not existent yet, and should be created under the specified URI
            long userId = userService.insert(user);
            return Response
                    .status(Response.Status.CREATED)
                    .entity("A new user has been created AT THE LOCATION you specified")
                    .header("Location",
                            "http://localhost:8888/user/"
                                    + String.valueOf(userId)).build();
        } else {
            // resource is existent and a full update should occur
            userService.update(user);
            return Response
                    .status(Response.Status.OK)
                    .entity("The user you specified has been fully updated created AT THE LOCATION you specified")
                    .header("Location",
                            "http://localhost:8888/user/"
                                    + String.valueOf(id)).build();
        }
    }

    @DELETE
    @Produces({ MediaType.APPLICATION_JSON })
    public Response deleteUser() {
        userService.delete();
        return Response.status(Response.Status.NO_CONTENT)
                .entity("All users have been successfully removed").build();
    }

    @DELETE
    @Path("{id}")
    @Produces({ MediaType.TEXT_HTML })
    public Response deletePodcastById(@PathParam("id") Long id) {
        userService.deleteById(id);
        return Response.status(Response.Status.NO_CONTENT)
                .entity("User successfully removed from database").build();
    }

}

其中有几个地方需要强调:
资源类(Resource Class)
资源类是一个简单的 Java 对象 (POJO),可以实现任何接口。这增加了许多好处,比如可重用性和简单。

JAX-RS注解定义

注解描述
@PathURI path
@GET
@POST
@PUT
@DELETE
@HEAD
@PathParam
@QueryParam
@Consumes
@Produces
@Provider

参考文档

Oracle RESTful Web Services Developer’s Guide:https://docs.oracle.com/cd/E19776-01/820-4867/ggnyk/index.html

资源下载

上述代码均已上传至Github,点此下载

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值