使用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、项目结构

使用Jersey+Spring+Tomcat构建RESTful Web服务_第1张图片

2、pom.xml

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

    <dependencies>

        <dependency>
            <groupId>org.glassfish.jersey.extgroupId>
            <artifactId>jersey-spring3artifactId>
            <version>${jersey-spring.version}version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframeworkgroupId>
                    <artifactId>spring-coreartifactId>
                exclusion>
                <exclusion>
                    <groupId>org.springframeworkgroupId>
                    <artifactId>spring-webartifactId>
                exclusion>
                <exclusion>
                    <groupId>org.springframeworkgroupId>
                    <artifactId>spring-beansartifactId>
                exclusion>
            exclusions>
        dependency>

        <dependency>
            <groupId>org.glassfish.jersey.containersgroupId>
            <artifactId>jersey-container-servletartifactId>
            <version>${jersey-spring.version}version>
        dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containersgroupId>
            <artifactId>jersey-container-servlet-coreartifactId>
            <version>${jersey-spring.version}version>
        dependency>

        <dependency>
            <groupId>org.glassfish.jersey.mediagroupId>
            <artifactId>jersey-media-json-jacksonartifactId>
            <version>${jersey.version}version>
        dependency>
        <dependency>
            <groupId>org.glassfish.jersey.mediagroupId>
            <artifactId>jersey-media-multipartartifactId>
            <version>${jersey.version}version>
        dependency>
        <dependency>
            <groupId>org.glassfish.jersey.extgroupId>
            <artifactId>jersey-entity-filteringartifactId>
            <version>${jersey.version}version>
        dependency>

        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-coreartifactId>
            <version>${spring.version}version>
        dependency>

        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>${spring.version}version>
        dependency>

        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-webartifactId>
            <version>${spring.version}version>
        dependency>

        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>${spring.version}version>
        dependency>

        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-txartifactId>
            <version>${spring.version}version>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-testartifactId>
            <version>${spring.version}version>
            <scope>testscope>
        dependency>

        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>javax.servlet-apiartifactId>
            <version>${servlet-api-version}version>
            <scope>providedscope>
        dependency>

        
        <dependency>
            <groupId>ch.qos.logbackgroupId>
            <artifactId>logback-classicartifactId>
            <version>${logback.version}version>
        dependency>
        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>jcl-over-slf4jartifactId>
            <version>${jcloverslf4j.version}version>
        dependency>

        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
            <scope>testscope>
        dependency>
    dependencies>

3、web.xml



<web-app>
    <display-name>Archetype Created Web Applicationdisplay-name>

    <context-param>
        <param-name>contextConfigLocationparam-name>
        <param-value>classpath:applicationContext.xmlparam-value>
    context-param>

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

    <servlet>
        <servlet-name>jersey-serlvetservlet-name>
        <servlet-class>
            org.glassfish.jersey.servlet.ServletContainer
        servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Applicationparam-name>
            <param-value>com.ricky.codelab.jersey.RestJaxRsApplicationparam-value>
        init-param>
        <load-on-startup>1load-on-startup>
    servlet>

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

web-app>

3.1、applicationContext.xml


<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 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注解定义

注解 描述
@Path URI 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,点此下载

你可能感兴趣的:(Spring,Framework,Jersey,RESTful,spring)