Java EE 1.5 Servlet – http 方法 OPTIONS 给出“405 Method Not Allowed”

Posted

技术标签:

【中文标题】Java EE 1.5 Servlet – http 方法 OPTIONS 给出“405 Method Not Allowed”【英文标题】:Java EE 1.5 Servlet – http method OPTIONS gives “405 Method Not Allowed” 【发布时间】:2016-01-13 14:23:44 【问题描述】:

我正在使用“Java EE 1.5,支持 JAX-WS 注释来创建 Web 服务。

可以从 Soap UI 调用我的 Web 服务而不会出现问题。 我正在尝试使用 javascript 和 JQuery 从 chrome 调用它。我遇到了交叉视线安全问题。我对需要添加到调用中的标题感到厌烦,我已经添加了它们并验证了它们是否存在于 Soap UI 中。 查看 chrome 日志,我可以看到它正在向 web 服务发送一个带有“OPTIONS”方法的 http 调用,并得到一个响应“405(不允许的方法)”

据我所知,有些东西是在“OPTIONS”方法到达我的 servlet 之前拦截它。 “POST”请求通过没有任何问题。 有谁知道如何配置 Java EE 1.5 servlett 以接收 OPTIONS HTTP 方法?我用谷歌搜索了这个,但没有运气。

我的 web.xml:

<?xml version = '1.0' encoding = 'UTF-8'?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
  <servlet>
    <servlet-name>connectionInfo</servlet-name>
    <servlet-class>ic.ac.uk.icsoa.wladminserversensor.wsdlgen.Main_ptImpl</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>connectionInfo</servlet-name>
    <url-pattern>/connectionInfo</url-pattern>
  </servlet-mapping>
</web-app>

我的 Java 代码:

package ic.ac.uk.icsoa.wladminserversensor.wsdlgen;

import ic.ac.uk.icsoa.wladminserversensor.WeblogicSensor;
import ic.ac.uk.icsoa.wladminserversensor.wsdlgentypes.ObjectFactory;
import ic.ac.uk.icsoa.wladminserversensor.wsdlgentypes.RequestSOAEndpointsMessageType;
import ic.ac.uk.icsoa.wladminserversensor.wsdlgentypes.ResponseSOAEndpointsMessageType;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.Action;
import javax.xml.ws.BindingType;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.soap.SOAPBinding;

@WebService(name = "main_pt", targetNamespace = "urn:WLAdminServerSensor", serviceName = "connectionInfoService", portName = "connectionInfo", wsdlLocation = "/WEB-INF/wsdl/connectionInfoService.wsdl")
@XmlSeeAlso(  ObjectFactory.class )
@javax.jws.soap.SOAPBinding(style = javax.jws.soap.SOAPBinding.Style.DOCUMENT, parameterStyle = javax.jws.soap.SOAPBinding.ParameterStyle.BARE)
@BindingType(SOAPBinding.SOAP12HTTP_BINDING)
public class Main_ptImpl 
    @Resource
    WebServiceContext ctxt;

    public Main_ptImpl() 
    

    @javax.jws.soap.SOAPBinding(parameterStyle = javax.jws.soap.SOAPBinding.ParameterStyle.BARE)
    @Action(input = "urn:WLAdminServerSensor/querySOAEndpoints", output = "urn:WLAdminServerSensor/main_pt/querySOAEndpointsResponse")
    @WebMethod(action = "urn:WLAdminServerSensor/querySOAEndpoints")
    @WebResult(name = "responseSOAEndpointsMessage", targetNamespace = "http://ic.ac.uk.icdev.rjmtest.wladminserversensor.types", partName = "requestSOAEndpointsOutputPart")
    public ResponseSOAEndpointsMessageType querySOAEndpoints(@WebParam(name = "requestSOAEndpointsMessage", partName = "requestSOAEndpointsInputPart", targetNamespace = "http://ic.ac.uk.icdev.rjmtest.wladminserversensor.types")
        RequestSOAEndpointsMessageType requestSOAEndpointsInputPart) 

        MessageContext mc = ctxt.getMessageContext();

        HttpServletResponse response = (HttpServletResponse) mc.get(MessageContext.SERVLET_RESPONSE);        
        HttpServletRequest request = (HttpServletRequest) mc.get(MessageContext.SERVLET_REQUEST);
        response.addHeader("Access-Control-Allow-Origin", "*");
        if (request.getMethod().equals("OPTIONS")) 
            response.addHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
            response.addHeader("Access-Control-Allow-Methods","GET, POST, PUT");
            return null;
        ;

        return WeblogicSensor.execute(requestSOAEndpointsInputPart);
    

Javascript(使用 JQuery)在 Chrome 中运行以调用 servlet:

soapRequest = "<soap:Envelopexmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\"xmlns:ic=\"http://ic.ac.uk.icdev.rjmtest.wladminserversensor.types\"><soap:Header/><soap:Body><ic:requestSOAEndpointsMessage><ic:Input>CallviaJQuery</ic:Input><ic:Credentials><ic:Username>weblogic</ic:Username><ic:Password>*****</ic:Password></ic:Credentials></ic:requestSOAEndpointsMessage></soap:Body></soap:Envelope>";

var jqxhr = $.ajax(
        type: 'POST',
        url: param.endpoint,
        data: soapRequest,
        dataType: 'xml',
        contentType: 'application/soap+xml;charset=UTF-8;action="urn:WLAdminServerSensor/querySOAEndpoints"'
).done(function(data) 
    alert("TODO");
).fail(function(data) 
    alert("TODO - FAIL");
);

【问题讨论】:

【参考方案1】:

我找到了解决方案,所以我发布它是为了他人的利益。

我必须创建自己的 CORS 过滤器。我通过创建一个实现“javax.servlet.Filter”的类来做到这一点。我通过逆向工程 org.apache.catalina.filters.CorsFilter tomcat-catalina-8.0.0-rc1.jar.zip 构建了 thie。我必须创建自己的版本,而不仅仅是包含 apache 版本,因为我是从我机器上的本地文件而不是从另一个网站运行我的 javascript。这使得站点来源被报告为空。即使过滤器配置了允许的来源为 *,来自本地文件的来源(我认为是 null)被拒绝。

在我自己的版本中调整代码(更改 checkRequestType 函数)后,我得到了它的工作。

然后我有一个 web.xml 如下:

<?xml version = '1.0' encoding = 'UTF-8'?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
  <servlet>
    <servlet-name>connectionInfo</servlet-name>
    <servlet-class>ic.ac.uk.icsoa.wladminserversensor.wsdlgen.Main_ptImpl</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>connectionInfo</servlet-name>
    <url-pattern>/connectionInfo</url-pattern>
  </servlet-mapping>
<filter>
    <filter-name>CorsFilter</filter-name>
    <filter-class> ic.ac.uk.icsoa.wladminserversensor.RJMCorsFilter</filter-class>
    <init-param>
        <param-name>cors.allowed.origins</param-name>
        <param-value>*</param-value>
    </init-param>
    <init-param>
        <param-name>cors.allowed.methods</param-name>
        <param-value>GET,POST,HEAD,OPTIONS,PUT,DELETE,PATCH</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CorsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>  
</web-app>

并简化了我的 servlet:

public ResponseSOAEndpointsMessageType querySOAEndpoints(@WebParam(name = "requestSOAEndpointsMessage", partName = "requestSOAEndpointsInputPart", targetNamespace = "http://ic.ac.uk.icdev.rjmtest.wladminserversensor.types")
    RequestSOAEndpointsMessageType requestSOAEndpointsInputPart) 
    return WeblogicSensor.execute(requestSOAEndpointsInputPart);

一切都奏效了。

【讨论】:

以上是关于Java EE 1.5 Servlet – http 方法 OPTIONS 给出“405 Method Not Allowed”的主要内容,如果未能解决你的问题,请参考以下文章

终极Java版本表(J2EE、Java EE、Servlet、JSP、JSTL)

Java EE javax.servlet中的Servlet接口

Java EE之Servlet技术

Java EE - Servlet 小结

Java EE Servlet 几个path

使用 java EE 6 注释的 Servlet 过滤?