5

次のjQuery1.6を使用して、AJAX経由でSpring( 3.2.0 )のメソッドを呼び出そうとしています。

function updateRoleEnabled(id)
{
    $.ajax({
            datatype:"json",                        
            type: "PUT",
            url: "/wagafashion/ajax/UpdateUserRole.htm",
            data: "id="+id+"&t="+new Date().getTime(),
            success: function(response)
            {
            },
            error: function(e)
            {
                alert('Error: ' + e);
            }
    });
}

Springで次のメソッドを呼び出そうとします。

@RequestMapping(value=("ajax/UpdateUserRole"), method=RequestMethod.PUT)
public @ResponseBody void updateUserRole(@RequestParam(value=("id")) String id)
{
    System.out.println("id = "+id);
}

FireFoxは次のエラーで応答します。

HTTPステータス405-リクエストメソッド「GET」はサポートされていません

タイプステータスレポート

メッセージリクエストメソッド'GET'はサポートされていません

description指定されたHTTPメソッドは、要求されたリソースには許可されていません(要求メソッド'GET'はサポートされていません)。

Apache Tomcat / 6.0.26

これはGETandPOSTメソッドで機能し、JSON(Jackson-2.1.1を使用)はアプリケーションの他の部分でも正常に機能します。


dispatcher-servlet.xmlファイルを見る必要がある場合、完全な内容は次のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"

       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

    <context:component-scan base-package="controller" />
    <context:component-scan base-package="validatorbeans" />

    <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" >
        <mvc:message-converters register-defaults="false">
        <bean id="jacksonMessageConverter" p:supportedMediaTypes="application/json" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
    </mvc:message-converters>
    </mvc:annotation-driven>

    <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
        <property name="favorPathExtension" value="false" />
        <property name="favorParameter" value="false" />
        <property name="ignoreAcceptHeader" value="false" />
        <property name="mediaTypes" >
            <value>
                atom=application/atom+xml
                html=text/html
                json=application/json
                *=*/*
            </value>
        </property>
    </bean>

    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="org.springframework.web.multipart.MaxUploadSizeExceededException">
                    fileUploadingFailure
                </prop>
            </props>
        </property>
    </bean>
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="index.htm">indexController</prop>
            </props>
        </property>
    </bean>

    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/jsp/"
          p:suffix=".jsp" />

    <bean name="indexController"
          class="org.springframework.web.servlet.mvc.ParameterizableViewController"
          p:viewName="index" />
</beans>

Spring 3.2以外のHTTPメソッドを作成し、Spring 3.2で機能させる方法GETPOST


編集:

以下のコメントに基づいて、以下は私のweb.xmlファイル全体です。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 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">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/applicationContext.xml
            /WEB-INF/spring-security.xml
        </param-value>
    </context-param>
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>



    <filter>
        <filter-name>NoCacheFilter</filter-name>
        <filter-class>filter.NoCacheFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>NoCacheFilter</filter-name>
        <url-pattern>/admin_side/*</url-pattern>
    </filter-mapping>


    <filter>
        <filter-name>FileUploadFilter</filter-name>
        <filter-class>com.ckfinder.connector.FileUploadFilter</filter-class>
        <init-param>
            <param-name>sessionCookieName</param-name>
            <param-value>JSESSIONID</param-value>
        </init-param>
        <init-param>
            <param-name>sessionParameterName</param-name>
            <param-value>jsessionid</param-value>
        </init-param>
    </filter>


    <filter-mapping>
        <filter-name>FileUploadFilter</filter-name>
        <url-pattern>
                    /ckfinder/core/connector/java/connector.java
     </url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>multipartFilter</filter-name>
        <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>multipartFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <filter>
        <filter-name>httpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>httpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <filter>
        <filter-name>openSessionInViewFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>singleSession</param-name>
            <param-value>false</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>openSessionInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>





    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <description>ServletContextListener</description>
        <listener-class>listener.UnregisterDatabaseDrivers</listener-class>
    </listener>
    <servlet>
        <servlet-name>ConnectorServlet</servlet-name>
        <servlet-class>com.ckfinder.connector.ConnectorServlet</servlet-class>
        <init-param>
            <param-name>XMLConfig</param-name>
            <param-value>/WEB-INF/config.xml</param-value>
        </init-param>
        <init-param>
            <param-name>debug</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>ConnectorServlet</servlet-name>
        <url-pattern>
                    /ckfinder/core/connector/java/connector.java
            </url-pattern>
    </servlet-mapping>


     <listener>
        <listener-class>
          org.springframework.security.web.session.HttpSessionEventPublisher
        </listener-class>
      </listener>




    <error-page>
        <description>Missing login</description>
        <error-code>401</error-code>
        <location>/WEB-INF/jsp/admin_side/ErrorPage.jsp</location>
    </error-page>

    <error-page>
        <description>Forbidden directory listing</description>
        <error-code>403</error-code>
        <location>/WEB-INF/jsp/admin_side/ErrorPage.jsp</location>
    </error-page>

    <error-page>
        <description>Missing page</description>
        <error-code>404</error-code>
        <location>/WEB-INF/jsp/admin_side/ErrorPage.jsp</location>
    </error-page>

    <error-page>
        <description>Uncaught exception</description>
        <error-code>500</error-code>
        <location>/WEB-INF/jsp/admin_side/ErrorPage.jsp</location>
    </error-page>

    <error-page>
        <description>Unsupported servlet method</description>
        <error-code>503</error-code>
        <location>/WEB-INF/jsp/admin_side/ErrorPage.jsp</location>
    </error-page>



    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>redirect.jsp</welcome-file>
    </welcome-file-list>
</web-app>
4

1 に答える 1

2

パスパラメータのみを使用している場合を除き、通常のHTTPPUTの処理にはさらに作業が必要です。

Spring 3.1以降、データの作業にHttpPutFormContentFilter使用できます。@RequestParamapplication/x-www-form-urlencoded

ServletRequest.getParameter*()HTTP PUTリクエスト中に、フォームでエンコードされたデータを一連のメソッドで利用できるようにするフィルター。

サーブレット仕様では、フォームデータをHTTP POSTで使用できる必要がありますが、HTTPPUTリクエストでは使用できません。このフィルターは、コンテンツタイプが''であるHTTPPUTリクエストをインターセプトしapplication/x-www-form-urlencoded、リクエストの本文からフォームエンコードされたコンテンツを読み取り、HTTP POSTリクエストの場合と同様に、フォームデータをリクエストパラメーターとして使用できるようにするためにServletRequestをラップします。

ただし、このフィルターは要求の入力ストリームを消費するFormHttpMessageConverterため、@RequestBody MultiValueMap<String, String>やなどのコンバーターでは使用できなくなりHttpEntity<MultiValueMap<String, String>>ます。その結果、アプリケーションで上記のフィルターを構成application/x-www-form-urlencodedすると、生のPUTデータも期待する他のコンバーターを使用するメソッドを呼び出すときに、「IOException:ストリームが閉じられました」というメッセージが表示されます。


または、またはを使用してすべてを手動で行うこともできます。@RequestBodyHttpEntity<?>

@RequestMapping(value="ajax/UpdateUserRole", method=RequestMethod.PUT,
    produces = MediaType.TEXT_PLAIN_VALUE)
public @ResponseBody String updateUserRole(
    @RequestBody final MultiValueMap<String, String> data,
    final HttpServletResponse response) {
  Map<String, String> params = data.toSingleValueMap();
  String id = params.get("id");
  String a = params.get("a");
  String b = params.get("b");
  if(id == null || a == null || b == null) {
    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
    return null;
  }
  return "id = " + id;
}

を使用した例WebDataBinderも参照してください。または、次を使用してください。

public ResponseEntity<String> updateUserRole(
    final HttpEntity<MultiValueMap<String, String>> entity) {
  Map<String, String> params = entity.getBody().toSingleValueMap();
  String id = params.get("id");
  ...

テストの場合、MockMvc mockMvc.perform(put(url).param(name, value))を使用すると、サーブレットコンテナで失敗したとしても、実際には質問のコードでも機能することに注意してください。しかし、MockMvcはそのようなサーブレットコンテナで実行されていないため、少しだまされています。

MockMvcは。.param(name, value)でもうまく機能しHttpPutFormContentFilterます。ただし、MockMvcを使用して@RequestBodyまたはをテストする場合は、 PUTコンテンツを手動でHttpEntity<?>作成する必要もあります。application/x-www-form-urlencoded好き:

mockMvc.perform(put(url).content("id=" + URLEncoder.encode(id, "UTF-8")
  + "&a=" + URLEncoder.encode(a, "UTF-8") + "&b=" + ...)

GETやPOSTの場合と同じように、を簡単に使用できるようにするには.param(name, value)、次のように定義できます。

public static RequestPostProcessor convertParameters() {
  return new RequestPostProcessor() {
    @Override
    public MockHttpServletRequest postProcessRequest(
        final MockHttpServletRequest request) {
      if ("PUT".equalsIgnoreCase(request.getMethod()) {
        Map<String, String[]> params = request.getParameterMap();
        if (params != null) {
          StringBuilder content = new StringBuilder();
          for (Entry<String, String[]> es : params.entrySet()) {
            for (String value : es.getValue()) {
              try {
                content.append(URLEncoder.encode(es.getKey(), "UTF-8"))
                  .append("=")
                  .append(URLEncoder.encode(value, "UTF-8"))
                  .append("&");
              }
              catch (UnsupportedEncodingException e) {
                throw new IllegalArgumentException("UTF-8 not supported");
              }
            }
          }
          request.setParameters(new HashMap<String, String[]>());
          request.setContent(content.toString().getBytes());
          request.setContentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE);
        }
      }
      return request;
    }
  };
}

...次に.with(convertParameters())次を使用し.param(name, value)ます:

mockMvc.perform(put(url)
    .with(convertParameters())
    .param("id", id).param("a", a).param("b", b) ...)

上記のすべてを考えると、データに使用HttpPutFormContentFilterするだけでapplication/x-www-form-urlencoded本当に楽になります。

ブラウザがapplication/x-www-form-urlencodedデータを送信していないが、JSONなどを送信している場合、にマップしようとするMultiValueMapと、415のサポートされていないメディアタイプが生成されます。代わりに、JacksonJSONを使用したSpringMVCでのJSONの解析@RequestBody MyDTO dataのようなものまたはHttpEntity<MyDTO> entity説明されているものを使用してください。

于 2013-01-28T19:10:50.483 に答える