jetty服务器使用jersey作为Restful框架

使用 Maven 的简单 Java SE 应用程序,从一个现有项目学习尝试搭建一个新的项目。

首先完成最基础的GET POST请求的功能。

1.新建项目 Maven-Java应用程序

2.打开POM,编辑POM.XML,添加jetty,jersey

<project>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey</groupId>
                <artifactId>jersey-bom</artifactId>
                <version>${jersey.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-jetty-servlet</artifactId>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
        </dependency>

        <!-- json support -->
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
        </dependency>
        <!-- moxy for xml -->
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-moxy</artifactId>
        </dependency>
        <!-- jersey-media-multipart for file -->
            <dependency>
	        <groupId>org.glassfish.jersey.media</groupId>
	        <artifactId>jersey-media-multipart</artifactId>
    	</dependency>
        <dependency>
	        <groupId>commons-io</groupId>
	        <artifactId>commons-io</artifactId>
	        <version>2.4</version>
	    </dependency>
        
        <!-- jetty is our HTTP server -->
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>${jetty.version}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-rewrite</artifactId>
            <version>${jetty.version}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-util</artifactId>
            <version>${jetty.version}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>${jetty.version}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlets</artifactId>
            <version>${jetty.version}</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}-${project.version}-${build.specifier}</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>*.properties</include>
                    <include>*.xml</include>
                </includes>
            </resource>
        </resources>
        <plugins>
        <!--打包
            docs:https://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.2</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <!--Setting Manifest Entries with the ManifestResourceTransformer-->
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.test.Main</mainClass>
                                </transformer>
                                <!--  use transformer to handle merge of META-INF/services - see http://java.net/jira/browse/JERSEY-440?focusedCommentId=14822&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_14822 -->
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                            </transformers>
                            <!-- Exclude signature files. Combining all dependencies into one uber jar means that some jars may contribute
                            signature files, which won't be valid for the resulting jar, and will cause the jar to be un-runnable as it
                            won't pass a signature check -->
                            <filters>
                                <filter>
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                            <shadedArtifactAttached>true</shadedArtifactAttached>
                            <shadedClassifierName>${build.specifier}-uber</shadedClassifierName>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <!-- @Inject @Contract @Service-->
            <plugin>  
                <groupId>org.glassfish.hk2</groupId>  
                <artifactId>hk2-inhabitant-generator</artifactId>  
                <version>2.6.1</version>
                <executions>  
                    <execution>  
                        <goals>  
                            <goal>generate-inhabitants</goal>  
                        </goals>  
                    </execution>  
                </executions>  
            </plugin>
        </plugins>
    </build>

    <properties>
        <jetty.version>9.4.35.v20201120</jetty.version>
        <jersey.version>2.32</jersey.version>
        
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.build.timestamp.format>yyyyMMdd-HHmm</maven.build.timestamp.format>
    </properties>
</project>


3.编辑Main.java

package com.test;

import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.glassfish.jersey.servlet.ServletContainer;

/**
 *
 * @author Admin
 */
public class Main {

    public static void main(String[] args) throws Exception {
        startServer();
    }

    /**
     * 服务器 jetty doc https://www.eclipse.org/jetty/documentation.php jetty api
     * https://www.eclipse.org/jetty/javadoc/9.4.35.v20201120/index.html?overview-summary.html
     *
     * @return
     * @throws Exception
     */
    private static Server startServer() throws Exception {
        int maxThreadPool = 50;

        //Set the maximum number of threads.  
        QueuedThreadPool threadPool = new QueuedThreadPool();
        threadPool.setMaxThreads(maxThreadPool);
        threadPool.setMinThreads(maxThreadPool / 10);
        threadPool.setIdleTimeout(30 * 1000);
        Server server = new Server(threadPool);

        //设置connector, http/https连接
        Connector[] connectors = createConnectors(server);
        server.setConnectors(connectors);

        //设置handler, 业务处理
        ContextHandlerCollection handlers = createContextHandlerCollection();
        server.setHandler(handlers);

        server.start();
        server.join();
        return server;
    }

    /**
     * 创建connector,acceptors,selectors都用默认值
     *
     * @param server
     * @param properties
     * @return
     */
    private static Connector[] createConnectors(final Server server) {
        long idleTimeOut = 15 * 1000;
        // Configuration
        HttpConfiguration httpConfig = new HttpConfiguration();
//        httpConfig.setSecureScheme("https");
//        httpConfig.setSecurePort(securePort);
//        httpConfig.setOutputBufferSize(32768);
        httpConfig.setRequestHeaderSize(32768);
        httpConfig.setResponseHeaderSize(32768);
//        httpConfig.setSendServerVersion(true);
//        httpConfig.setSendDateHeader(false);
        httpConfig.setIdleTimeout(idleTimeOut);
        // httpConfig.addCustomizer(new ForwardedRequestCustomizer());

        boolean httpEnabled = true;
        int httpPort = 8080;
        boolean httpsEnabled = true;
        int httpsPort = 8081;
        String SSLKeyStorePath = "aSSL.jks";
        String SSLPassword = "PASSWORD";

        ServerConnector httpConnector = null, httpsConnector = null;
        if (httpEnabled) {
            httpConnector = new ServerConnector(server, new HttpConnectionFactory(httpConfig));
            httpConnector.setPort(httpPort);
            httpConnector.setIdleTimeout(idleTimeOut);
        }

        if (httpsEnabled) {
            HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
            httpsConfig.addCustomizer(new SecureRequestCustomizer());
            // SSL
//            SslContextFactory sslContextFactory = new SslContextFactory();
            SslContextFactory sslContextFactory = new SslContextFactory.Server();
            sslContextFactory.setKeyStorePath(SSLKeyStorePath);
            sslContextFactory.setKeyManagerPassword(SSLPassword);
            sslContextFactory.setKeyStorePassword(SSLPassword);

            httpsConnector = new ServerConnector(server,
                    new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
                    new HttpConnectionFactory(httpsConfig));
            httpsConnector.setPort(httpsPort);
            httpsConnector.setIdleTimeout(idleTimeOut);
        }

        if (httpsConnector != null) {
            if (httpConnector != null) {
                return new Connector[]{httpsConnector, httpConnector};
            } else {
                return new Connector[]{httpsConnector};
            }
        } else if (httpConnector != null) {
            return new Connector[]{httpConnector};
        } else {
            return null;
        }
    }

    /**
     * 创建handler
     *
     * @param properties
     * @return
     * @throws Exception
     */
    private static ContextHandlerCollection createContextHandlerCollection() throws Exception {
        String path = "/hi";
        ContextHandler apiContextHandler = buildContextHandler(path);
        return new ContextHandlerCollection(apiContextHandler);
    }

    /**
     * servlet handler : 实现后端功能
     *
     * @param basePath
     * @return
     */
    private static ContextHandler buildContextHandler(String basePath) {
        //由jersey提供restful web服务
        ServletHolder jerseyServlet = new ServletHolder(ServletContainer.class);
        jerseyServlet.setInitParameter("javax.ws.rs.Application", "com.test.inject.MyJerseyConfig");
        jerseyServlet.setInitOrder(1);

        ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
        contextHandler.setContextPath(basePath);
        contextHandler.addServlet(jerseyServlet, "/*");
        return contextHandler;
    }
}

4.修改MyJerseyConfig.java

package com.test.inject;

import com.test.inject.filter.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import org.glassfish.hk2.api.ActiveDescriptor;
import org.glassfish.hk2.api.DynamicConfigurationService;
import org.glassfish.hk2.api.MultiException;
import org.glassfish.hk2.api.Populator;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Admin
 */
public class MyJerseyConfig extends ResourceConfig {

    @Inject
    public MyJerseyConfig(
            ServiceLocator serviceLocator
    ) {

        DynamicConfigurationService dcs = serviceLocator.getService(DynamicConfigurationService.class);
        Populator populator = dcs.getPopulator();

        try {
            LoggerFactory.getLogger(getClass()).debug("Populating descriptors...");
            //The default populate() looks in META-INF/hk2-locator  
            List<ActiveDescriptor<?>> descriptors = populator.populate();
            for (ActiveDescriptor<?> desc : descriptors) {
                LoggerFactory.getLogger(getClass()).debug("Added descriptor: " + desc);
            }

            //We also want to check hk2-locator/ because that's where WAR packaging places it  
            descriptors = populator.populate(() -> {
                List<InputStream> streams = new ArrayList<>();
                InputStream stream = getClass().getClassLoader().getResourceAsStream("hk2-locator/default");
                if (stream != null) {
                    streams.add(stream);
                }
                return streams;
            });
            for (ActiveDescriptor<?> desc : descriptors) {
                LoggerFactory.getLogger(getClass()).debug("Added descriptor: " + desc);
            }
        } catch (IOException e) {
            throw new MultiException(e);
        }

        //json转换
        register(JacksonFeature.class);

        // 启用Java Moxy支持xml
        register(MoxyXmlFeature.class);

        //MultiPartFeature 支持文件上传/下载
        register(MultiPartFeature.class);

        //手动处理部分Inject
        register(new Binder());

        //扫描服务类所在的包  
        packages("com.test.rest");

        //继承javax.ws.rs.container.ContainerRequestFilter,在服务开始之前, 处理request
        //javax.ws.rs.container.ContainerResponseFilter,在服务完成以后,处理response
        //报错后本地log输出        
        register(ExceptionLoggerFilter.class);
        //直接处理OPTION请求
        register(OptionsMethodFilter.class);
        //webGL需要的相应头
        register(WebGLHeaderWriterInterceptor.class);

        //输出所有请求与相应
        boolean logAll = true;
        if (logAll) {
            register(CustomLoggingFilter.class);
        }

        //运行报错返回response
        register(MyExceptionMapper.class);
    }
}

部分用到的

package com.test.inject;

import javax.inject.Singleton;
import org.glassfish.hk2.utilities.binding.AbstractBinder;

/**
 *
 * @author Admin
 */
public class Binder extends AbstractBinder {

    @Override
    protected void configure() {
//        //工厂
//        bindFactory(SomeThingFactory.class).to(SomeThing.class).in(Singleton.class);
//        //唯一实例
//        bindAsContract(SomeThing.class).in(Singleton.class);
    }
}
package com.test.inject.filter;

import org.glassfish.jersey.message.internal.ReaderWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import java.io.*;

public class CustomLoggingFilter implements ContainerRequestFilter, ContainerResponseFilter {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append("User: ").append(requestContext.getSecurityContext().getUserPrincipal() == null ? "unknown"
                : requestContext.getSecurityContext().getUserPrincipal());
        sb.append(" - Path: ").append("★").append(requestContext.getUriInfo().getPath()).append("★");
        sb.append(" - Method: ").append(requestContext.getMethod());
        sb.append(" - Header: ").append(requestContext.getHeaders());
        sb.append(" - Entity: ").append(getEntityBody(requestContext));
        logger.info("HTTP REQUEST : " + sb.toString());
    }

    private String getEntityBody(ContainerRequestContext requestContext) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        InputStream in = requestContext.getEntityStream();

        final StringBuilder b = new StringBuilder();
        try {
            ReaderWriter.writeTo(in, out);

            byte[] requestEntity = out.toByteArray();
            if (requestEntity.length == 0) {
                b.append("").append("\n");
            } else {
                b.append(new String(requestEntity)).append("\n");
            }
            requestContext.setEntityStream(new ByteArrayInputStream(requestEntity));

        } catch (IOException ex) {
            //Handle logging error
        }
        return b.toString();
    }

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        if (!"swagger.json".equals(requestContext.getUriInfo().getPath())) {
            StringBuilder sb = new StringBuilder();
            sb.append("Header: ").append(responseContext.getHeaders());
            sb.append(" - Entity: ");
            if (responseContext.getEntity() != null) {
                sb.append(responseContext.getEntity().toString());
//                sb.append(JsonUtil.getObjectMapper().writeValueAsString(responseContext.getEntity()));
            } else {
                sb.append("nothing");
            }
            sb.append('\n');
            //System.out.println("HTTP RESPONSE : " + sb.toString());
            logger.info("HTTP RESPONSE : " + sb.toString());
        } else {
            logger.info("HTTP RESPONSE : " + "swagger");
        }
    }
}
package com.test.inject.filter;

import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Administrator
 */
public class ExceptionLoggerFilter implements ContainerResponseFilter {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        if (responseContext.getStatus() >= 400) {
            logger.error("server error at path:[{}], status:{}", requestContext.getUriInfo().getPath(), responseContext.getStatus());
        }
    }

}
package com.test.inject.filter;

import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.core.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by Administrator
 */
@Provider
public class MyExceptionMapper implements ExceptionMapper<Exception> {

    private final static Logger logger = LoggerFactory.getLogger(MyExceptionMapper.class);
    
    @Override
    public Response toResponse(Exception exception) {
//        exception.printStackTrace();
        logger.error("exception:", exception);
        return Response.serverError().entity(exception.getMessage()).build();
    }
}
package com.test.inject.filter;

import java.io.IOException;
import javax.inject.Inject;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Response;

/**
 *
 * @author Administrator
 */
public class OptionsMethodFilter implements ContainerRequestFilter {
    

    @Inject
    public OptionsMethodFilter(
    ) {
    }
    
    @Override
    public void filter(ContainerRequestContext containerRequestContext) throws IOException {
        if("OPTIONS".equals(containerRequestContext.getMethod())){
            containerRequestContext.abortWith(
                    Response.status(Response.Status.OK)
                    .entity("ok")
                    .header("Access-Control-Max-Age", "3600")
//                    .header("Access-Control-Allow-Origin", "*")
//                    .header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
//                    .header("Access-Control-Allow-Credentials", "true")
//                    .header("Access-Control-Allow-Headers", "Accept, X-Access-Token, X-Application-Name, X-Request-Sent-Time, content-type, content-encoding")
                    .build());
        }
    }
}
package com.test.inject.filter;

import java.io.IOException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;

/**
 * @author Administrator
 */
public class WebGLHeaderWriterInterceptor implements WriterInterceptor {

    @Override
    public void aroundWriteTo(WriterInterceptorContext context)
            throws IOException, WebApplicationException {
        
        MultivaluedMap<String,Object> headers = context.getHeaders();
        headers.add("Access-Control-Allow-Origin", "*");
        headers.add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
        headers.add("Access-Control-Allow-Credentials", "true");
        headers.add("Access-Control-Allow-Headers", "Accept, X-Access-Token, X-Application-Name, X-Request-Sent-Time, content-type, content-encoding");
        
        context.proceed();
    }
}

5.rest包添加服务类

5.1 GET

package com.test.rest.gettest;

import javax.inject.Inject;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.CookieParam;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

/**
 *
 * @author Admin
 */
@Path("gett")
public class GetTestResource {

    @Inject
    public GetTestResource() {

    }

    @GET
    @Path("a")
    @Produces(MediaType.TEXT_HTML)
    public String a(
            @DefaultValue("0") @QueryParam("f") int f,
            @DefaultValue("0") @QueryParam("t") int t
    ) {
        return t + "/" + f;
    }
    //>>curl localhost:8080/hi/gett/a?f=12
    //0/12

    @GET
    @Path("b")
    @Produces(MediaType.APPLICATION_JSON)
    public GetTestResponse b() {
        GetTestResponse response = new GetTestResponse();
        response.setVal(123);
        return response;
    }
    //>>curl localhost:8080/hi/gett/b
    //{"val":123}

    @GET
    @Path("c")
    @Produces(MediaType.TEXT_HTML)
    public String c(
            @CookieParam("session") String session,
            @DefaultValue("0") @QueryParam("t") int t
    ) {
        return "s:" + session;
    }
    //>>curl --cookie "session=aSession" localhost:8080/hi/gett/c?t=44
    //s:aSession

    @GET
    @Path("d")
    @Produces(MediaType.TEXT_HTML)
    public String d(
            @Context HttpServletRequest request
    ) {
        Cookie[] c = request.getCookies();
        return request.getContextPath() + request.getPathInfo();
    }
    //>>curl --cookie "session=aSession" -H "h: 1" localhost:8080/hi/gett/d
    ///hi/gett/d
}


package com.test.rest.gettest;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
 *
 * @author Admin
 */
public class GetTestResponse {

    @JsonProperty("val")
    private int val;

    public int getVal() {
        return val;
    }

    public void setVal(int val) {
        this.val = val;
    }
}

5.2 JSON

-H 'Content-Type: application/json'

-H 'Accept:application/json'

package com.test.rest.posttest;

import com.test.rest.posttest.sub.SubResource;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
 *
 * @author Admin
 */
@Path("postt")
public class PostTestResource {

    @Inject
    public PostTestResource() {

    }

    @POST
    @Path("a")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public PostTestResponse a(PostTestRequest request) {
        PostTestResponse response = new PostTestResponse();
        response.setVal(request.getAInt());
        return response;
    }
    //>>curl -H "Content-Type: application/json" -X POST -d {\"aInt\":3} localhost:8080/hi/postt/a
    //{"val":3}

    @Path("b")
    public SubResource b() {
        return new SubResource();
    }
    //>curl -H "Content-Type: application/json" -X POST -d {\"aInt\":3} localhost:8080/hi/postt/b
    //{"val":3}
}


package com.test.rest.posttest;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
 *
 * @author Admin
 */
public class PostTestRequest {
    private int aInt;
    
    @JsonProperty("aInt")
    public int getAInt(){
        return aInt;
    }
    
    public void setAInt(int aInt){
        this.aInt = aInt;
    }
}


package com.test.rest.posttest;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
 *
 * @author Admin
 */
public class PostTestResponse {

    @JsonProperty("val")
    private int val;

    public int getVal() {
        return val;
    }

    public void setVal(int val) {
        this.val = val;
    }


    //手动序列化mysql的json类型, (jooq 3.17.0以后有提供jooq-jackson-extensions)
    @ApiModelProperty(value = "datas")
    @JsonProperty("datas")
    @JsonSerialize(using = MyJooqJsonSerializer.class)
    private org.jooq.JSON datas;

    public org.jooq.JSON getDatas() {
        return datas;
    }

    @Column(name = "datas")
    public void setDatas(org.jooq.JSON datas) {
        this.datas = datas;
    }
}



package com.test.rest.posttest.sub;

import com.test.rest.posttest.PostTestRequest;
import com.test.rest.posttest.PostTestResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
 *
 * @author Admin
 */
public class SubResource {

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public PostTestResponse a(PostTestRequest request) {
        PostTestResponse response = new PostTestResponse();
        response.setVal(request.getAInt());
        return response;
    }
}

5.3 XML

-H 'Content-type: application/xml'

-H 'Accept: application/xml'

import io.swagger.annotations.Api;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("xml")
@Api("xml格式.")
public class XmlResource {

    @GET
    @Path("tt")
    @Produces(MediaType.APPLICATION_XML)
    public XmlResponse person() {
        var r = new XmlResponse();

        r.setAge(123);
        r.setName("xiaohei");

        return r;
    }

    @POST
    @Path("te")
    @Consumes(MediaType.APPLICATION_XML)
    @Produces(MediaType.APPLICATION_XML)
    public XmlResponse p2(XmlRequest request) {
        var r = new XmlResponse();

        r.setAge(123);
        r.setName(request.getName());

        return r;
    }

    /*
    curl --location 'http://localhost:8080/hi/xml/te' \
--header 'Content-Type: application/xml' \
--data '<?xml version="1.0" encoding="UTF-8"?>
<request>
<name>heihei</name>
</request>'
     */
}



import java.io.Serializable;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="response")
public class XmlResponse implements Serializable{

    private String name;
    private int age;

    // Getters and setters

    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;
    }
}

import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement(name = "request")
public class XmlRequest {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

5.4 文件


import io.swagger.annotations.Api;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import org.apache.commons.io.FileUtils;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;

/**
 *
 * @author yaozhen
 */
@Path("file")
@Api("文件.")
public class FileResource {

    @POST
    @Path("upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.TEXT_PLAIN)
    public String uploadimage1(
            @FormDataParam("file") InputStream fileInputStream,
            @FormDataParam("file") FormDataContentDisposition disposition,
            @Context ServletContext ctx
    ) {

        //设置保存的路径和文件名
        var upload = new File(ctx.getRealPath("/files"),
                disposition.getFileName());

        try {
            FileUtils.copyInputStreamToFile(fileInputStream, upload);
        } catch (Exception ex) {
            return "failed";
        }

        return "success";
    }

    /*
    curl --location 'http://localhost:8080/hi/file/upload' \
    --form 'file=@"~/image.jpg"'
     */
    @GET
    @Path("/images/{name}.{type}")
    public void showImg(
            @PathParam("name") String imageName,
            @PathParam("type") String type,
            @Context ServletContext ctx,
            @Context HttpServletResponse response
    ) {
        try {
            var file = new File(ctx.getRealPath("/files"), imageName + "." + type);
            FileUtils.copyFile(file, response.getOutputStream());
        } catch (Exception ex) {

        }
    }

    //http://localhost:8080/hi/file/images/image.jpg
}

javax.ws.rs-api 常用注解

手动序列化org.jooq.JSON

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;

/**
 *
 * @author yaozhen
 */
public class MyJooqJsonSerializer extends JsonSerializer<org.jooq.JSON> {

    @Override
    public void serialize(org.jooq.JSON value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (value == null) {
            gen.writeNull();
        } else {
            gen.writeRawValue(value.data());
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值