作者:伊倓 | 来源:互联网 | 2023-05-25 12:00
我有以下GETREST方法:importjava.time.OffsetDateTime;importjavax.ws.rs.Consumes;importjavax.ws.rs.
我有以下GET REST方法:
import java.time.OffsetDateTime;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import com.product.rest.api.TransactionsApi;
import com.product.rest.model.Transaction;
@Path("/transactions")
@Api(description = "the transactions API")
@Consumes({ "application/json" })
@Produces({ "application/json" })
public class TransactionsApiImpl extends TransactionsApi {
@GET
@Consumes({ "application/json" })
@Produces({ "application/json" })
@ApiOperation(value = "", notes = "Get all transactions", respOnse= Transaction.class, respOnseContainer= "List", tags = {})
@ApiResponses(
value = { @ApiResponse(code = 200, message = "OK", respOnse= Transaction.class, respOnseContainer= "List"),
@ApiResponse(code = 400, message = "Bad Request", respOnse= Transaction.class, respOnseContainer= "List"),
@ApiResponse(code = 404, message = "Not Found", respOnse= Transaction.class, respOnseContainer= "List"),
@ApiResponse(code = 500, message = "Internal Server Error", respOnse= Transaction.class, respOnseContainer= "List") })
@Override
public Response transactionsGet(
@HeaderParam("tok") String tok,
@QueryParam("param1") Integer param1,
@QueryParam("param2") String param2,
@QueryParam("param3") OffsetDateTime param3,
@QueryParam("param4") OffsetDateTime param4,
@QueryParam("param5") Integer param5,
@QueryParam("param6") Integer param6,
@QueryParam("param7") String param7) {
return Response.ok().entity("Success!").build();
}
TransactionsApi是使用Swagger Codegen生成的实现,Transaction模型类也是如此.我在这个类中有其他几个函数,但每当我将GET / transactions函数取消注释时,我都会收到以下错误:
WARN [Thread-1] (ContextHandler.java:2175) - unavailable
org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.
[[FATAL] No injection source found for a parameter of type public javax.ws.rs.core.Response
com.product.rest.impl.v1.TransactionsApiImpl.transactionsGet(java.lang.String,java.lang.Integer,java.lang.String,java.time.OffsetDateTime,java.time.OffsetDateTime,java.lang.Integer,java.lang.Integer,java.lang.String) at index 3.; source='ResourceMethod{httpMethod=GET, cOnsumedTypes=[application/json], producedTypes=[application/json], suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class com.product.rest.impl.v1.TransactionsApiImpl, handlerCOnstructors=[org.glassfish.jersey.server.model.HandlerConstructor@7df78e88]}, definitiOnMethod=public javax.ws.rs.core.Response
我发现的所有其他类似问题都与MultiPart Data和文件上传有关,而我正在做一个简单的GET请求.其他也使用javax.ws.rs.code.Response类的函数没有此问题,服务器正常启动.
我注意到只要OffsetDateTime类在参数(即param3和param4)中就会出现问题,但我一直无法找到原因.此外,由Swagger Codegen选择OffsetDateTime,我不愿意改变它,看看每当我重新生成源时我将如何更改每个派生文件.
有没有人在使用REST服务和OffsetDateTime之前遇到过这个问题?
解决方法:
All other similar questions I have found had to do with MultiPart Data and file uploading
这是相关的.当Jersey无法验证资源模型时,该错误是您遇到的一般错误.资源模型的一部分是方法参数.泽西有一个系统,用于了解它将能够处理哪些参数以及哪些参数不能处理.在您的情况下,它不知道如何处理OffsetDateTime.
为了能够使用非基本类型作为@QueryParam
(以及所有其他@XxxParams,如@PathParam和@FormParam等),您需要遵循一组规则:
>是一种原始类型
>有一个接受单个String参数的构造函数
>有一个名为valueOf或fromString的静态方法接受单个String参数(例如,参见Integer.valueOf(String))
>具有ParamConverterProvider JAX-RS扩展SPI的注册实现,该SPI返回能够为该类型进行“从字符串”转换的ParamConverter实例.
> Be List,Set或者SortedSet,其中T满足上面的2,3或4.生成的集合是只读的.
所以在这种OffsetDateTime的情况下,沿着列表向下;它不是原始的;它没有String构造函数;它没有静态valueOf或fromString
基本上,剩下的唯一选择是为它实现ParamConverter / ParamConverterProvider.基本设置看起来像
@Provider
public class OffsetDateTimeProvider implements ParamConverterProvider {
@Override
public ParamConverter getConverter(Class clazz, Type type, Annotation[] annotations) {
if (clazz.getName().equals(OffsetDateTime.class.getName())) {
return new ParamConverter() {
@SuppressWarnings("unchecked")
@Override
public T fromString(String value) {
OffsetDateTime time = ...
return (T) time;
}
@Override
public String toString(T time) {
return ...;
}
};
}
return null;
}
}
Jersey会传递查询参数的String值,创建它并返回它是你的工作.
然后只需在应用程序中注册OffsetDateTimeProvider.如果您正在使用包扫描,则应从@Provider注释中自动拾取并注册.
我不使用Swagger,所以我不知道他们是否已经提供了已经实现的这样的东西,但是它们会为你生成这个并且没有办法让它工作似乎很奇怪.我知道Jersey 3将支持Java 8,但是谁知道什么时候会发布.