web-dev-qa-db-fra.com

Utilisation des méthodes PUT et DELETE dans Spring MVC

J'essaie d'utiliser RequestMethod.PUT et RequestMethod.DELETE dans le contrôleur Spring MVC (version 3.0.2). Il existe trois méthodes mappées avec une URL dans la classe de contrôleur Spring comme suit (PUT, GET et POST respectivement, à des fins de démonstration uniquement).

@RequestMapping(method = {RequestMethod.PUT}, value = {"admin_side/Temp"}, headers = {"content-type=multipart/form-data"})
public String update(@ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) {
    if (ServletFileUpload.isMultipartContent(request)) {
        System.out.println("true");
    }

    System.out.println("Request method PUT");
    return "admin_side/Temp";
}

@RequestMapping(method = {RequestMethod.GET}, value = {"admin_side/Temp"})
public String showForm(@ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) {
    System.out.println("Request method GET");
    return "admin_side/Temp";
}

@RequestMapping(method = {RequestMethod.POST}, value = {"admin_side/Temp"})
public String onSubmit(@ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) {
    System.out.println("Request method POST");
    return "admin_side/Temp";
}

Lorsque la page est chargée, la méthode GET est invoquée comme évidente mais dans tous les autres cas (lorsque la page est soumise), la seule méthode à invoquer est POST, la méthode désignée par RequestMethod.PUT n'est jamais invoqué.


Le formulaire Spring contient uniquement un bouton d'envoi et un navigateur d'images,

<form:form id="mainForm"
           name="mainForm"
           method="PUT"
           action="Temp.htm"
           enctype="multipart/form-data"
           commandName="tempBean">

    <input type="file" id="myFile" name="myFile"/>
    <input type="submit" id="btnSubmit" name="btnSubmit" value="Submit"/>
</form:form>

Le code HTML généré est le suivant,

<form id="mainForm"
      name="mainForm"
      action="Temp.htm"
      method="post"
      enctype="multipart/form-data">

    <input type="hidden" name="_method" value="PUT"/>
    <!--This hidden field is implicitly included-->

    <input type="file" id="myFile" name="myFile"/>
    <input type="submit" id="btnSubmit" name="btnSubmit" value="Submit"/>
</form>

Dans mon spring-config.xml (dispatcher-servlet.xml dans mon cas), j'ai ajouté une référence à CommonsMultipartResolver :

<bean id="filterMultipartResolver"
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

et dans mon web.xml fichier, HiddenHttpMethodFilter est configuré comme suit,

<filter>
    <filter-name>MultipartFilter</filter-name>
    <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
    <init-param>
        <param-name>multipartResolverBeanName</param-name>
        <param-value>filterMultipartResolver</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>MultipartFilter</filter-name>
    <servlet-name>/*</servlet-name>
</filter-mapping>

<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <servlet-name>/*</servlet-name>
</filter-mapping>

La méthode PUT (et DELETE aussi) n'est jamais invoquée (sans exception ni erreur). Qu'est-ce que j'oublie ici?


Mise à jour:

Avec la configuration suivante dans web.xml,

<filter>
    <filter-name>MultipartFilter</filter-name>
    <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
    <init-param> <!-- Makes no difference, if excluded. -->
        <param-name>multipartResolverBeanName</param-name>
        <param-value>filterMultipartResolver</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>MultipartFilter</filter-name>
    <servlet-name>dispatcher</servlet-name>  <!--Changed from /* to dispatcher-->
</filter-mapping>

<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <servlet-name>dispatcher</servlet-name> <!--Changed from /* to dispatcher-->
</filter-mapping>

il lève l'exception suivante.

org.springframework.beans.factory.NoSuchBeanDefinitionException: aucun bean nommé 'filterMultipartResolver' n'est défini

Où le nom dispatcher est le nom du servlet - org.springframework.web.servlet.DispatcherServlet déjà mappé dans web.xml comme suit.

<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>

Je ne sais pas quoi d'autre est nécessaire? Le filtre HiddenHttpMethodFilter est-il requis pour implémenter notre propre extension OncePerRequestFilter quelque chose comme celui montré ici ? (c'est une classe intégrée)

Les points importants sont répertoriés ici .

22
Tiny

La plupart des navigateurs ne prennent pas en charge action=PUT dans les formulaires HTML. Ils enverront simplement POST demandes à la place. HiddenHttpMethodFilter vous aidera à contourner le problème, mais vous devez inclure un champ caché _method=PUT dans votre formulaire. Si vous utilisez la balise spring: form, cela se fera automatiquement pour vous, mais votre exemple semble utiliser du HTML simple.

NoSuchBeanDefinitionException est très probablement un problème sans rapport.

16
Guillaume

Vous devez changer votre configuration.

<servlet-name>/*</servlet-name>  

à

<servlet-name>[dispatch servlet name]</servlet-name> 
1
Hlex