java 在 REST 服务中实现方法 OPTIONS 的最佳方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32356151/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to implement method OPTIONS in REST services
提问by Eduardo Vendruscolo
I'm doing a REST application. I have made the GET
method without issues, however, when I implement the POST
method, it says that I don't have the OPTIONS
method implemented for it. I am doing the OPTIONS
method for URI:
我正在做一个 REST 应用程序。我制作的GET
方法没有问题,但是,当我实施该POST
方法时,它说我没有OPTIONS
为它实施该方法。我正在做OPTIONS
URI的方法:
http://192.168.1.26:8080/sellAppWeb/api/object/
http://192.168.1.26:8080/sellAppWeb/api/object/
I have the POST
and OPTIONS
methods:
我有POST
和OPTIONS
方法:
@OPTIONS
@Produces("application/json; charset=UTF-8")
public Response options() {
return Response.ok().build();
}
@Override
@POST
public Response save(CervejaDTO cervejaDTO) {
cervejaController.register(cervejaDTO);
return Response.ok(cervejaDTO).build();
}
Then I am made the DELETE
method and again it says that I don't have a OPTIONS
method. Then I need to make another OPTIONS
method, which has an ID
in the URI end. For example to delete a object with id = 3
:
然后我得到了DELETE
方法,它再次说我没有OPTIONS
方法。然后我需要创建另一个OPTIONS
方法,它ID
在 URI 端有一个。例如删除一个对象id = 3
:
http://192.168.1.26:8080/sellAppWeb/api/object/3
http://192.168.1.26:8080/sellAppWeb/api/object/3
I need to have another OPTIONS
with same structure of DELETE
URI:
我需要另一个OPTIONS
具有相同DELETE
URI结构的:
@OPTIONS
@Path("/{id}")
@Produces("application/json; charset=UTF-8")
public Response optionsDelete(@PathParam("id") Integer id) {
return Response.ok().build();
}
@Override
@POST
public Response save(CervejaDTO cervejaDTO) {
cervejaController.register(cervejaDTO);
return Response.ok(cervejaDTO).build();
}
Does anyone have a way to do a generic OPTIONS
for all REST requests?
有没有人有办法OPTIONS
对所有 REST 请求进行泛型处理?
the web.xml:
web.xml:
<display-name>Testes de servi?os REST</display-name>
<description>Testes de servi?os REST</description>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/api</param-value>
</context-param>
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>br.com.sell.app.exception.handler.DefaultExceptionHandler</param-value>
</context-param>
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
回答by Buhake Sindi
You don't need to implements the OPTIONS
HTTP VERB in this case. Since you're using RESTEasy, which is the JAX-RS implementation used by Wildfly, the issue I encountered was due to the servlet-mapping on web.xml
.
OPTIONS
在这种情况下,您不需要实现HTTP 动词。由于您使用的是 RESTEasy,它是 Wildfly 使用的 JAX-RS 实现,因此我遇到的问题是由于web.xml
.
I have encountered this when I added the JAX-RS facet on Eclipse and tell it to update the web.xml
. The default generated web.xml
containing the Restful application mapping doesn't map your application properly to your RESTful resource path.
当我在 Eclipse 上添加 JAX-RS 方面并告诉它更新web.xml
. web.xml
包含 Restful 应用程序映射的默认生成不会将您的应用程序正确映射到您的 RESTful 资源路径。
This is how the web.xml should look like, provided you have not created your own custom Application
.
这就是 web.xml 的样子,前提是您尚未创建自己的自定义Application
.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>My REST API</display-name>
<description>My REST API</description>
<servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/jaxrs/*</url-pattern>
</servlet-mapping>
</web-app>
Make sure that your <servlet-name>
and <servlet-mapping>
are mapped as in the example above. If you extended the Application
class, just specify it in your web.xml
instead of the default Application
as shown above.
确保您的<servlet-name>
和<servlet-mapping>
已按照上面的示例进行映射。如果您扩展了Application
类,只需在您的web.xml
而不是Application
如上所示的默认值中指定它。
Also, your @POST
resource method, it's recommended to specify the resource type of your RESTful data (in your case, your DTO) using @Consumes
annotation.
此外,您的@POST
资源方法,建议使用@Consumes
注释指定您的 RESTful 数据(在您的情况下,您的 DTO)的资源类型。
Eg.
例如。
@POST
@Path("/save")
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response save(CervejaDTO cervejaDTO)
}
回答by Paul Samsotha
"however, when I implement the POST method, it says that I don't have the OPTIONS method implemented for it."
"When i make a POST or DELTE request, the application make automatically a OPTIONS request before"
“但是,当我实现 POST 方法时,它说我没有为它实现 OPTIONS 方法。”
“当我发出 POST 或 DELTE 请求时,应用程序会在之前自动发出 OPTIONS 请求”
This definitely sound like a CORS (Cross Origin Resource Sharing) problem. You can read more about it at HTTP access control (CORS). Basically the OPTIONS request is preflight request before the actual request. This will happen for certain types of AJAX requests.
这绝对听起来像是 CORS(跨源资源共享)问题。您可以在HTTP 访问控制 (CORS) 中阅读有关它的更多信息。基本上 OPTIONS 请求是实际请求之前的预检请求。这对于某些类型的 AJAX 请求会发生。
For this, RESTeasy has the CorsFilter
you can register. You need to configure the filter to the settings you want to allow. Also see an example herefor one way to configure it.
为此,RESTeasy 具有CorsFilter
您可以注册的功能。您需要将过滤器配置为您想要允许的设置。另请参阅此处的示例,了解配置它的一种方法。
回答by otonglet
I tried RestEasy's CorsFilterbut calls made with the OPTIONS method were returning
我尝试了RestEasy 的 CorsFilter,但使用 OPTIONS 方法进行的调用正在返回
RESTEASY003655: No resource method found for options, return OK with Allow header
RESTEASY003655:找不到选项的资源方法,返回 OK 并带有 Allow 标头
I wrote a simple filter that:
我写了一个简单的过滤器:
- Makes sure the CORS header you need are applied to the response.
- Returns the HTTP status code 200 when calling an endpoint with the OPTIONS method. You just tell the client that its CORS preflight requests was accepted.
- 确保您需要的 CORS 标头应用于响应。
- 使用 OPTIONS 方法调用端点时返回 HTTP 状态代码 200。您只需告诉客户端其 CORS 预检请求已被接受。
Here is the code. This is a simplified version, ditry - yet efficient. Feel free to refine the filter if you only want to send back a 200 when querying a "real" endpoint.
这是代码。这是一个简化版本,繁琐 - 但高效。如果您只想在查询“真实”端点时发回 200,请随意优化过滤器。
@Provider
public class CorsFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
MultivaluedMap<String, Object> headers = responseContext.getHeaders();
headers.add("Access-Control-Allow-Origin", "*"); // If you want to be more restrictive it could be localhost:4200
headers.add("Access-Control-Allow-Methods", "GET, PUT, POST, OPTIONS"); // You can add HEAD, DELETE, TRACE, PATCH
headers.add("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept, Accept-Language"); // etc
if (requestContext.getMethod().equals("OPTIONS"))
responseContext.setStatus(200);
}}
From this postand my preferred CORS explanation.
从这篇文章和我喜欢的 CORS 解释。
回答by melli-182
I recommend you to use Spring Controllers and RequestMapping annotations, they are really easy to use:
我推荐你使用 Spring Controllers 和 RequestMapping 注解,它们真的很容易使用:
@RequestMapping(value="/method0", method="POST")
@ResponseBody
public String method0(){
return "method0";
}
You dont need to implement OPTIONS methods, just declare your method and use the annotation to define it as a POST/GET/PUT/DELETE request method. Hereare lots of examples.
您不需要实现 OPTIONS 方法,只需声明您的方法并使用注释将其定义为 POST/GET/PUT/DELETE 请求方法。 这里有很多例子。
回答by Felipe SS
For me that was the only way to do work.
对我来说,这是唯一的工作方式。
Create the class in your java restclient project.
在您的 java restclient 项目中创建该类。
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import org.jboss.resteasy.spi.DefaultOptionsMethodException;
@Provider
public class OptionsHander implements
ExceptionMapper<DefaultOptionsMethodException> {
private static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";
private static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method";
private static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
private static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
private static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
private static final String ACCESS_CONTROL_ALLOW_ORIGIN_ANYONE = "*";
@Context HttpHeaders httpHeaders;
@Override
public Response toResponse(DefaultOptionsMethodException exception) {
final ResponseBuilder response = Response.ok();
String requestHeaders = httpHeaders.getHeaderString(ACCESS_CONTROL_REQUEST_HEADERS);
String requestMethods = httpHeaders.getHeaderString(ACCESS_CONTROL_REQUEST_METHOD);
if (requestHeaders != null)
response.header(ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders);
if (requestMethods != null)
response.header(ACCESS_CONTROL_ALLOW_METHODS, requestMethods);
// TODO: development only, too permissive
response.header(ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_ALLOW_ORIGIN_ANYONE);
return response.build();
}
}
回答by lianjm
You can use @Path("{path:.*}").
您可以使用@Path("{path:.*}")。
@OPTIONS
@Path("{path:.*}")
public Response handleCORSRequest() throws Exception {
Response.ResponseBuilder builder = Response.ok();
return builder.build();
}