使用 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
}
手动序列化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());
}
}
}