杰瑞科技汇

webservice java

OfOf course! Let's create a comprehensive guide to creating a web service in Java. We'll cover the two most popular approaches:

  1. JAX-RS (Java API for RESTful Web Services): The modern, standard, and most common way to create RESTful web services. We'll use the reference implementation, Jersey.
  2. JAX-WS (Java API for XML Web Services): The older, standard way to create SOAP web services. We'll use the reference implementation, Metro.

Part 1: Creating a RESTful Web Service with JAX-RS (Jersey)

REST (Representational State Transfer) is an architectural style that uses standard HTTP methods (GET, POST, PUT, DELETE) to perform operations on resources. It's lightweight, easy to use, and the de-facto standard for modern web APIs and microservices.

Why JAX-RS?

  • Standard: It's a Java EE (now Jakarta EE) standard, so your code is portable across different application servers.
  • Simplicity: Annotating a plain Java class is all you need to create a web service.
  • Flexibility: Easy to integrate with JSON libraries (like Jackson) and dependency injection frameworks (like CDI).

Step-by-Step Guide: Creating a RESTful Service with Jersey

We'll use Maven to manage our project dependencies, which is the standard in the Java world.

Step 1: Set up a Maven Project

Create a new Maven project. In your pom.xml, add the necessary dependencies for Jersey and a JSON provider (to handle JSON data automatically).

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>java-webservice</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <jersey.version>3.1.1</jersey.version>
    </properties>
    <dependencies>
        <!-- Jersey Server -->
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-grizzly2-http</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <!-- Jackson for JSON support -->
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-binding</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <!-- For unit testing -->
        <dependency>
            <groupId>org.glassfish.jersey.test-framework</groupId>
            <artifactId>jersey-test-framework-core</artifactId>
            <version>${jersey.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <mainClass>com.example.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Step 2: Create the Resource Class

This is the core of your web service. It's a simple Java class with JAX-RS annotations.

package com.example;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
// The @Path annotation defines the base URL for this resource.
@Path("/users")
public class UserResource {
    // A simple in-memory "database"
    private ConcurrentMap<Integer, User> userStore = new ConcurrentHashMap<>();
    private int currentId = 1;
    public UserResource() {
        // Seed with some data
        userStore.put(currentId++, new User(1, "Alice"));
        userStore.put(currentId++, new User(2, "Bob"));
    }
    // @GET: Handles HTTP GET requests.
    // @Produces: Specifies the media type this method can return (e.g., JSON).
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<User> getAllUsers() {
        return new ArrayList<>(userStore.values());
    }
    // @GET with a path parameter: e.g., /users/1
    @GET
    @Path("/{userId}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getUserById(@PathParam("userId") int userId) {
        User user = userStore.get(userId);
        if (user == null) {
            // Return a 404 Not Found response if the user doesn't exist.
            return Response.status(Response.Status.NOT_FOUND).build();
        }
        // Return a 200 OK response with the user object.
        return Response.ok(user).build();
    }
    // @POST: Handles HTTP POST requests to create a new resource.
    // @Consumes: Specifies the media type this method can accept (e.g., JSON).
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response createUser(User user) {
        // In a real app, you would validate the input.
        user.setId(currentId++);
        userStore.put(user.getId(), user);
        // Return a 201 Created response with the location of the new resource.
        return Response.status(Response.Status.CREATED)
                       .entity(user)
                       .build();
    }
    // A simple data model (POJO)
    public static class User {
        private int id;
        private String name;
        public User() {}
        public User(int id, String name) {
            this.id = id;
            this.name = name;
        }
        // Getters and Setters are crucial for JSON serialization/deserialization
        public int getId() { return id; }
        public void setId(int id) { this.id = id; }
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
    }
}

Step 3: Create the Application Class and Main Method

This class configures and starts the Jersey web server.

package com.example;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.grizzly.http.server.HttpServer;
public class Main {
    public static void main(String[] args) {
        // Create a resource config that scans for JAX-RS resources and providers.
        ResourceConfig config = new ResourceConfig(UserResource.class);
        // Create and start the Grizzly HTTP server.
        HttpServer server = GrizzlyHttpServerFactory.createHttpServer(
                URI.create("http://localhost:8080/"), config);
        System.out.println("Server started. Available resources:");
        System.out.println("  - GET  http://localhost:8080/api/users");
        System.out.println("  - GET  http://localhost:8080/api/users/1");
        System.out.println("  - POST http://localhost:8080/api/users");
        System.out.println("Press Enter to stop the server...");
        try {
            System.in.read();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            server.shutdownNow();
        }
    }
}

Note: You'll need to add the import for GrizzlyHttpServerFactory and URI.

Step 4: Run and Test

  1. Run the application:

    mvn compile exec:java

    You should see the server startup message.

  2. Test the endpoints:

    • Get all users: Open your browser or use a tool like curl or Postman.

      curl http://localhost:8080/api/users

      Output: [{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]

    • Get a single user:

      curl http://localhost:8080/api/users/1

      Output: {"id":1,"name":"Alice"}

    • Create a new user:

      curl -X POST \
           -H "Content-Type: application/json" \
           -d '{"name":"Charlie"}' \
           http://localhost:8080/api/users

      Output: {"id":3,"name":"Charlie"}


Part 2: Creating a SOAP Web Service with JAX-WS

SOAP (Simple Object Access Protocol) is a protocol for exchanging structured information in web services. It's more complex, relies heavily on XML, and often uses WSDL (Web Services Description Language) to define the service contract.

Why JAX-WS?

  • Standard: It's the Java standard for building SOAP services.
  • WSDL First: It allows you to generate a service contract (WSDL) from your Java code, or vice-versa.
  • Tooling: Excellent IDE and build tool support for generating client and server code.

Step-by-Step Guide: Creating a SOAP Service with JAX-WS

Step 1: Set up a Maven Project

Create a new Maven project. For a simple, standalone server, we don't need many extra dependencies beyond the JAX-WS API, which is included in the JDK.

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>java-soap-service</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <!-- No extra dependencies needed for a simple JAX-WS endpoint -->
</project>

Step 2: Create the Service Endpoint Interface (SEI)

This is a Java interface that defines the methods your web service will expose. The @WebService and @WebMethod annotations mark it as a SOAP service.

package com.example;
import jakarta.jws.WebMethod;
import jakarta.jws.WebParam;
import jakarta.jws.WebService;
// @WebService marks this class as a Web Service.
@WebService
public interface HelloWorld {
    // @WebMethod marks this method as a web service operation.
    // @WebParam specifies the name of the parameter in the SOAP message.
    @WebMethod
    String sayHello(@WebParam(name = "name") String name);
}

Step 3: Create the Service Implementation

This is the concrete class that implements the HelloWorld interface.

package com.example;
import jakarta.jws.WebService;
// @WebService specifies the interface this class implements.
@WebService(endpointInterface = "com.example.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
    @Override
    public String sayHello(String name) {
        if (name == null || name.trim().isEmpty()) {
            return "Hello, Stranger!";
        }
        return "Hello, " + name + "!";
    }
}

Step 4: Create the Publisher Class

This class is responsible for publishing your service to a specific URL so clients can access it.

package com.example;
import jakarta.xml.ws.Endpoint;
public class HelloWorldPublisher {
    public static void main(String[] args) {
        // The URL where the service will be published.
        String url = "http://localhost:9999/ws/hello";
        // Publish the implementation.
        Endpoint.publish(url, new HelloWorldImpl());
        System.out.println("SOAP Service published successfully!");
        System.out.println("WSDL is available at: " + url + "?wsdl");
        System.out.println("Press Enter to stop the server...");
        try {
            System.in.read();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Step 5: Run and Test

  1. Run the publisher:

    mvn compile exec:java

    You should see the message indicating the service is published.

  2. View the WSDL: Open your web browser and navigate to http://localhost:9999/ws/hello?wsdl. You will see the XML definition of your service.

  3. Test the service: You can use a tool like SoapUI to create a new project from the WSDL URL and test the sayHello operation.

    • Request: <sayHello><name>World</name></sayHello>
    • Response: <ns2:sayHelloResponse><return>Hello, World!</return></ns2:sayHelloResponse>

Comparison: REST (JAX-RS) vs. SOAP (JAX-WS)

Feature REST (JAX-RS) SOAP (JAX-WS)
Style Architectural style (resource-oriented) Protocol (message-oriented)
Data Format Primarily JSON (also XML, HTML, plain text) Strictly XML (with SOAP envelope)
Standard JAX-RS (Jakarta EE) JAX-WS (Jakarta EE)
WSDL No (OpenAPI/Swagger is used for REST APIs) Yes, mandatory for describing the service contract
Performance Generally faster and lighter due to JSON/less overhead Slower and heavier due to XML/SOAP envelope
Use Cases Public APIs, Mobile apps, Microservices, Web Apps Enterprise systems (e.g., banking, ERP), B2B integrations
Security Relies on HTTPS, OAuth, API Keys Built-in, standardized security (WS-Security)
Tooling Good (Jersey, RESTEasy, Swagger) Excellent (WSDL-first generation, SoapUI)
Example Framework Jersey, RESTEasy Metro, Apache CXF

Which One Should You Choose?

  • Choose REST (JAX-RS) if:

    • You are building a public-facing API.
    • Performance and low overhead are important.
    • You need to support a wide range of clients (web, mobile, etc.).
    • Your team prefers simplicity and flexibility.
  • Choose SOAP (JAX-WS) if:

    • You are integrating with large, established enterprise systems.
    • You require a strict, formal contract (WSDL) between the client and server.
    • You need advanced, standardized security features like WS-Security.
    • Your project is mandated to use SOAP.

For most new projects, REST (JAX-RS) is the recommended choice due to its simplicity, performance, and widespread adoption.

分享:
扫描分享到社交APP
上一篇
下一篇