Java HTTP状态405-请求方法';把';不支持

Java HTTP状态405-请求方法';把';不支持,java,spring,spring-mvc,Java,Spring,Spring Mvc,我有以下控制器: @RestController public class RestaurantController { @Autowired RestaurantService restaurantService; @RequestMapping(value = "/restaurant/", method = RequestMethod.GET) public ResponseEntity<List<Restaurant>> listA

我有以下控制器:

@RestController
public class RestaurantController {
    @Autowired
    RestaurantService restaurantService;
    @RequestMapping(value = "/restaurant/", method = RequestMethod.GET)
    public ResponseEntity<List<Restaurant>> listAllRestaurants() {
        System.out.println("Fetching all restaurants");
        List<Restaurant> restaurants = restaurantService.findAllRestaurants();
        if(restaurants.isEmpty()){
            return new ResponseEntity<List<Restaurant>>(HttpStatus.NO_CONTENT);//You many decide to return HttpStatus.NOT_FOUND
        }
        return new ResponseEntity<List<Restaurant>>(restaurants, HttpStatus.OK);
    }
    @RequestMapping(value = "/restaurant/{id}", method = RequestMethod.PUT)
    public ResponseEntity<Restaurant> updateRestaurant(@PathVariable("id") int id, @RequestBody Restaurant restaurant) {
        System.out.println("Updating Restaurant " + id);

        Restaurant currentRestaurant = restaurantService.findById(id);

        if (currentRestaurant==null) {
            System.out.println("Restaurant with id " + id + " not found");
            return new ResponseEntity<Restaurant>(HttpStatus.NOT_FOUND);
        }

        currentRestaurant.setName(restaurant.getName());
        currentRestaurant.setDescription(restaurant.getDescription());
        currentRestaurant.setIcon(restaurant.getIcon());

        restaurantService.updateRestaurant(currentRestaurant);
        return new ResponseEntity<Restaurant>(currentRestaurant, HttpStatus.OK);
    }
}
编辑2:

2016-02-14 12:30:56调试过滤器ChainProxy:324-/餐厅/1 at 附加过滤器链中的位置1/12;点火过滤器: “WebAsyncManagerIntegrationFilter”

2016-02-14 12:30:56调试 过滤链氧气:324-/restaurant/1位于附加位置12的第2处 过滤链;正在启动筛选器:“SecurityContextPersistenceFilter”

2016-02-14 12:30:56调试HttpSessionSecurityContextRepository:159- 目前不存在HttpSession

2016-02-14 12:30:56调试 HttpSessionSecurityContextRepository:101-未找到SecurityContext 可从HttpSession获得:null。将创建一个新的

2016-02-14 12:30:56调试过滤器ChainProxy:324-/餐厅/1 at 附加过滤器链中12的位置3;点火过滤器: “HeaderWriterFilter”

2016-02-14 12:30:56调试HstsHeaderWriter:128- 未注入HSTS标头,因为它与requestMatcher不匹配 org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@3ded3d8a

2016-02-14 12:30:56调试过滤器ChainProxy:324-/餐厅/1 at 附加过滤器链中12的位置4;点火过滤器: “CsrfFilter”

2016-02-14 12:30:56调试CSRF过滤器:106-无效CSRF 为找到令牌

2016-02-14 12:30:56调试DispatcherServlet:861-DispatcherServlet 名为“dispatcher”的处理PUT请求 [/springsecuritycusotmloginformnotationexample/Access\u Denied]

2016-02-14 12:30:56调试请求映射Handler映射:294-正在查找 路径/访问被拒绝的up handler方法

2016-02-14 12:30:56调试 ExceptionHandlerExceptionResolver:134-从解析异常 处理程序[null]: org.springframework.web.HttpRequestMethodNotSupportedException: 不支持请求方法“PUT”

2016-02-14 12:30:56调试 ResponseStatusExceptionResolver:134-从处理程序解析异常 [null]: org.springframework.web.HttpRequestMethodNotSupportedException: 不支持请求方法“PUT”

2016-02-14 12:30:56调试 DefaultHandlerExceptionResolver:134-从处理程序解析异常 [null]: org.springframework.web.HttpRequestMethodNotSupportedException: 不支持请求方法“PUT”

2016-02-14 12:30:56警告 PageNotFound:198-不支持请求方法“PUT”

2016-02-14 12:30:56调试HttpSessionSecurityContextRepository:337- SecurityContext为空或内容为匿名-上下文不会 存储在HttpSession中

2016-02-14 12:30:56调试 DispatcherServlet:1034-返回到的ModelAndView为空 名为“dispatcher”的DispatcherServlet:假定为HandlerAdapter 已完成请求处理

2016-02-14 12:30:56调试 DispatcherServlet:996-已成功完成请求

2016-02-14 12:30:56调试DefaultListableBeanFactory:248-返回缓存 单例bean“delegatingApplicationListener”的实例

2016-02-14 12:30:56调试HttpSessionSecurityContextRepository:337- SecurityContext为空或内容为匿名-上下文不会 存储在HttpSession中

2016-02-14 12:30:56调试 SecurityContextPersistenceFilter:105-现在是SecurityContextHolder 已清除,因为请求处理已完成


不要将请求发送到
/restaurant/1/
,而是将其发送到
/restaurant/1
尝试将
org.springframework.web
的日志记录级别调到
DEBUG
。这将让您了解Spring如何处理请求。希望它能为您(或我们)提供更多关于如何修复它的线索

如果您使用的是Spring Boot,只需将这一行添加到application.properties文件:

查看其他日志后进行编辑:


“PUT”不受支持的消息有点误导。真正的问题在那之前。您没有有效的CSRF令牌。您是如何提交请求的?看起来您使用的是邮递员工具(但我不熟悉这个工具),而不是直接从网页提交表单。您可以通过某种方式使用该工具将令牌添加到请求中。在没有工具的情况下是否可以工作?直接从网页提交表单?

默认情况下,在
WebMvcAutoConfiguration
中,
HttpPutFormContentFilter
未配置,因此出现问题

它在spring boot
[1.3.0)
版本中已修复,工作正常。因此,您可以尝试更新spring boot版本或手动配置此筛选器以使其正常工作

.


希望能有所帮助。

我也有同样的错误,但对我来说,这是因为我将ID作为URL参数进行了修改。之所以修改,是因为该ID存在于JSON正文中


当我将…/restaurant更改为…/restaurant/1时,错误消失了。

如果您不需要csrf,您可以这样做

@Configuration
@EnableWebSecurity
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
}

}

我认为您的模型应该实现可序列化接口,并且应该有一个默认构造函数


对于我来说,通过将上述内容添加到我的模型类中,并将@RequestBody添加到控制器方法参数中,问题得以解决。

HTTP 405如果无法反序列化对象,也会返回错误代码,例如,对于没有默认构造函数的对象,会出现这种情况

以这项服务为例:

import javax.ws.rs.*;
import com.sun.jersey.spi.resource.Singleton;

@Singleton
@Path("root")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class SampleRestService { ..
  @PUT
  @Path("sample")
  public void update(Sample whitelist) throws SampleException {
    // do some
}
和对象示例,覆盖默认构造函数:

class Sample{
 int x,y;
 public sample(int x, int y){
   // boring stuff
 }
}
在这种情况下,解组无法反序列化请求内容,并触发405。或者,这就是glassfish 3.5和javax.ws.rs-api-2.0.1.jar以及jersey-xxx-2.25.1.jar的工作方式


修复方法实际上是将默认构造函数(即不带参数的构造函数)添加到通过API传递的对象中。

在我的情况下,我必须为修补程序控制器使用带有
@RequestBody
的模型类。

因此基本上就是这样
@Configuration
@EnableWebSecurity
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
}
import javax.ws.rs.*;
import com.sun.jersey.spi.resource.Singleton;

@Singleton
@Path("root")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class SampleRestService { ..
  @PUT
  @Path("sample")
  public void update(Sample whitelist) throws SampleException {
    // do some
}
class Sample{
 int x,y;
 public sample(int x, int y){
   // boring stuff
 }
}