/ / Spring 3.2のAJAXを使用したPUTメソッドが機能しない-json、spring、jquery、jackson、put

Spring 3.2でAJAXを使用したPUTメソッドが機能しない-json、spring、jquery、jackson、put

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

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」はサポートされていません

説明指定されたHTTPメソッドは、要求されたものには許可されていません リソース(リクエストメソッド「GET」はサポートされていません)。

Apache Tomcat / 6.0.26

それはで動作します GET そして POST メソッドとJSON(ジャクソンと-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>

以外のHTTPメソッドの作成方法 GET そして POST Spring 3.2で動作しますか?


編集:

以下のコメントに基づいて、以下は私の全体です 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>

回答:

回答№1は2

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

以来 春3.1、 HttpPutFormContentFilter 作るために使用することができます @RequestParam のために働く application/x-www-form-urlencoded データ:

フォームでエンコードされたデータを ServletRequest.getParameter*() HTTPPUTリクエスト中のメソッドのファミリー。

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

ただし:このフィルター 消費する リクエストの入力ストリーム。次のようなコンバータでは利用できません。 FormHttpMessageConverter@RequestBody MultiValueMap<String, String> または HttpEntity<MultiValueMap<String, String>>。その結果、 設定された アプリケーションで上記のフィルターを使用すると、rawを期待する他のコンバーターを使用するメソッドを呼び出すと、「IOException:streamclosed」が発生します。 application/x-www-form-urlencoded PUTデータ。


あるいは、 すべて 手動で、 @RequestBody または HttpEntity<?>

@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 または HttpEntity<?>、1つも作成する必要があります application/x-www-form-urlencoded コンテンツを手動で配置します。お気に入り:

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

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

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のサポートされていないメディアタイプが生成されます。代わりに、次のようなものを使用してください @RequestBody MyDTO data または HttpEntity<MyDTO> entity で説明されているように JacksonJSONを使用したSpringMVCでのJSONの解析.