Spring boot:不支持请求方法'PUT'

时间:2014-04-03 20:00:06

标签: rest put spring-boot

我在使用restful API上的 PUT 方法上传文件时遇到Request method 'PUT' not supported错误。

以下是上传到此故障单的信息。

  1. 客户端日志
  2. RestController
  3. Spring Boot App配置
  4. Tomcat日志
  5. 的pom.xml

  6. 1。客户端日志

    $ curl -X PUT -T  "/cygdrive/c/a/documents/test.pptx" http://localhost:8080/piranha-storage-service/buckets/gnaval.bucket1/test.pptx
    <html><head><title>Apache Tomcat/7.0.52 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 405 - Request method 'PUT' not supported</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Request method 'PUT' not supported</u></p><p><b>description</b> <u>The specified HTTP method is not allowed for the requested resource.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/7.0.52</h3></body></html>
    

    2。 RestController

    package com.acme.piranha.api.impl;
    
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.tomcat.util.http.fileupload.IOUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import com.amazonaws.services.s3.model.Bucket;
    import com.amazonaws.services.s3.model.S3ObjectSummary;
    import com.acme.piranha.api.PiranhaStorageService;
    import com.acme.piranha.dto.TransferStream;
    import com.acme.piranha.exception.PiranhaDataAccessException;
    import com.acme.piranha.s3.svc.S3;
    
    @RestController
    @RequestMapping(value = "/piranha-storage-service")
    public class PiranhaStorageServiceRESTImpl implements PiranhaStorageService {
    
        @Autowired
        S3 s3;
    
        @RequestMapping(value = "/buckets/{bucketName}/{objectName:.+}", method = RequestMethod.PUT, headers="{Accept=*/*, content-type=multipart/form-data}")
        public @ResponseBody
        String upload(@PathVariable final String bucketName,
                @PathVariable final String objectName,
                @RequestParam("file") MultipartFile file) {
    
            LOG.info("Reached upload. uploading object.");
    
            try {
                File uploadedFile = new File(file.getOriginalFilename());
                try {
                    byte[] bytes = file.getBytes();
                    BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(uploadedFile));
                    stream.write(bytes);
                    stream.close();
                } catch (IOException e) {
                    throw new RuntimeException("Failed to upload file!", e);
                }
                final FileInputStream fileUpload = new FileInputStream(uploadedFile);
                final String objectTag = s3.upload(bucketName, objectName, fileUpload);
    
                LOG.info("Successfully uploaded object to S3, assigned object tag="
                        + objectTag);
                return objectTag;
    
            } catch (final IOException ioe) {
                LOG.error("Failed upload operation, returning empty string");
                // in case of exception flow return a empty stream.
                return "";
    
            } catch (final PiranhaDataAccessException pdae) {
                LOG.error("Failed upload operation, returning empty string");
                // in case of exception flow return a empty stream.
                return "";
            }
    
        }
    }
    

    3。 Spring Boot App Config

    package com.acme.piranha.config;
    
    import javax.servlet.MultipartConfigElement;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.boot.context.embedded.MultiPartConfigFactory;
    import org.springframework.boot.context.web.SpringBootServletInitializer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.multipart.MultipartResolver;
    import org.springframework.web.multipart.commons.CommonsMultipartResolver;
    
    @Configuration
    @EnableAutoConfiguration
    @ComponentScan("com.acme.piranha")
    public class PiranhaStorageServiceApplication extends SpringBootServletInitializer {
    
        @Override
        protected SpringApplicationBuilder configure(
                final SpringApplicationBuilder application) {
            return application.sources(PiranhaStorageServiceApplication.class);
        }
    
        public static void main(final String[] args) throws Exception {
            SpringApplication.run(PiranhaStorageServiceApplication.class, args);
        }
    
        @Bean
        public MultipartConfigElement multipartConfigElement() {
            MultiPartConfigFactory factory = new MultiPartConfigFactory();
            factory.setMaxFileSize("2MB");
            factory.setMaxRequestSize("2MB");
            return factory.createMultipartConfig();
        }
    
        @Bean
        public MultipartResolver multipartResolver() {
            return new CommonsMultipartResolver();
        }
    }
    

    4。 Tomcat日志

    2014-04-03 12:44:37.159  INFO 5592 --- [lication.main()] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080/http
    2014-04-03 12:44:37.168  INFO 5592 --- [lication.main()] c.p.p.c.PiranhaStorageServiceApplication : Started PiranhaStorageServiceApplication in 5.423 seconds (JVM running for 11.60
    8)
    2014-04-03 12:44:51.995 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing servlet 'dispatcherServlet'
    2014-04-03 12:44:51.997  INFO 5592 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
    2014-04-03 12:44:51.998  INFO 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
    2014-04-03 12:44:51.999 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Using MultipartResolver [org.springframework.web.multipart.support.StandardServl
    etMultipartResolver@1c15b988]
    2014-04-03 12:44:52.007 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Unable to locate LocaleResolver with name 'localeResolver': using default [org.s
    pringframework.web.servlet.i18n.AcceptHeaderLocaleResolver@30ab6fdf]
    2014-04-03 12:44:52.014 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Unable to locate ThemeResolver with name 'themeResolver': using default [org.spr
    ingframework.web.servlet.theme.FixedThemeResolver@3696a572]
    2014-04-03 12:44:52.025 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Unable to locate RequestToViewNameTranslator with name 'viewNameTranslator': usi
    ng default [org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@57dc2acc]
    2014-04-03 12:44:52.032 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Unable to locate FlashMapManager with name 'flashMapManager': using default [org
    .springframework.web.servlet.support.SessionFlashMapManager@5e2cc0ac]
    2014-04-03 12:44:52.033 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Published WebApplicationContext of servlet 'dispatcherServlet' as ServletContext
     attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcherServlet]
    2014-04-03 12:44:52.033  INFO 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 34 ms
    2014-04-03 12:44:52.037 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Servlet 'dispatcherServlet' configured successfully
    2014-04-03 12:44:52.060 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing PUT request for [/pir
    anha-storage-service/buckets/gnaval.bucket1/PivotalInstall.pptx]
    2014-04-03 12:44:52.065 DEBUG 5592 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /piranha-storage-service/buckets/gnaval.bucke
    t1/PivotalInstall.pptx
    2014-04-03 12:44:52.073 DEBUG 5592 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Did not find handler method for [/piranha-storage-service/buckets/gnaval.bucket1
    /PivotalInstall.pptx]
    2014-04-03 12:44:52.075 DEBUG 5592 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Matching patterns for request [/piranha-storage-service/buckets/gnaval.bucket1/P
    ivotalInstall.pptx] are [/**]
    2014-04-03 12:44:52.076 DEBUG 5592 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : URI Template variables for request [/piranha-storage-service/buckets/gnaval.buck
    et1/test.pptx] are {}
    2014-04-03 12:44:52.080 DEBUG 5592 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapping [/piranha-storage-service/buckets/gnaval.bucket1/test.pptx] to
     HandlerExecutionChain with handler [org.springframework.web.servlet.resource.ResourceHttpRequestHandler@19db7f7e] and 1 interceptor
    2014-04-03 12:44:52.083 DEBUG 5592 --- [nio-8080-exec-1] .w.s.m.a.ResponseStatusExceptionResolver : Resolving exception from handler [org.springframework.web.servlet.resource.Resou
    rceHttpRequestHandler@19db7f7e]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'PUT' not supported
    2014-04-03 12:44:52.086 DEBUG 5592 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolving exception from handler [org.springframework.web.servlet.resource.Resou
    rceHttpRequestHandler@19db7f7e]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'PUT' not supported
    2014-04-03 12:44:52.089  WARN 5592 --- [nio-8080-exec-1] o.s.web.servlet.PageNotFound             : Request method 'PUT' not supported
    2014-04-03 12:44:52.096 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': a
    ssuming HandlerAdapter completed request handling
    2014-04-03 12:44:52.098 DEBUG 5592 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Successfully completed request
    

    5。的pom.xml

        <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.0.0.RELEASE</version>
    </parent><dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>core</artifactId>
                <version>0.9.3</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-service-connector</artifactId>
                <version>0.9.3</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>cloudfoundry-connector</artifactId>
                <version>0.9.3</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>commons-lang</groupId>
                <artifactId>commons-lang</artifactId>
                <version>2.3</version>
            </dependency>
            <dependency>
                <groupId>commons-collections</groupId>
                <artifactId>commons-collections</artifactId>
                <version>3.0</version>
            </dependency>
            <dependency>
                <groupId>com.amazonaws</groupId>
                <artifactId>aws-java-sdk</artifactId>
                <version>1.0.002</version>
            </dependency>
        </dependencies>
    </project>
    

5 个答案:

答案 0 :(得分:1)

要启用PUT动词,您必须在响应头中添加允许该方法的拦截器。

类似的东西:

public class SasAllowOriginInterceptor extends HandlerInterceptorAdapter {

  @Override
  public boolean preHandle(HttpServletRequest request,
                           HttpServletResponse response, Object handler)
    throws Exception {
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods",
                       "GET, POST, PUT, DELETE, OPTIONS");
    return true;
  }
}

虽然我不知道如何使用弹簧靴添加拦截器,但我知道它会引起注意:)

答案 1 :(得分:1)

Chek你请求映射

如果您在班级@RequestMapping("/api/users")中声明请求映射 然后,如果您在方法级@RequestMapping("/api/users/{id}")中声明映射,则可能会发生此错误。

<强>正确

@RequestMapping("/api/users")
 public class {.....

   @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
   update(....)

} 

不正确,可能导致PUT不支持错误

@RequestMapping("/api/users")
 public class {.....

   @RequestMapping(value = "/api/users/{id}", method = RequestMethod.PUT)
   update(....)

} 

答案 2 :(得分:0)

简单地说:您的@RequestMapping与请求不符。正则表达式可能需要一些工作。

答案 3 :(得分:0)

这个错误也发生在我身上,我刚刚重新启动服务器并且错误消失了,你提出的RequestMapping与请求匹配。

答案 4 :(得分:0)

用于添加拦截器 你应该做的是实现WebMvcConfigurer并重写addInterceptors方法。

@Configuration
public class WebMvcConfigAdapter implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new yourInterceptor());
    }
}