As it says in the Spring REST guide,
@RequestMapping
maps all HTTP operations by default
but if, as they suggest, you added a specification of the allowable http methods:
@RequestMapping(method=GET)
then only GETs will be allowed. POSTs will be disallowed.
If you want to allow both GET and POST, but disallow all other http methods, then annotate your controller method thusly:
@RequestMapping(value = "/greeting", method = {RequestMethod.GET, RequestMethod.POST})
public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
When you start the application, all the request handler mappings are logged out. You should see a line like this in your log (in the IDE console or command line window):
s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped «{[/greeting],methods=[GET || POST]}» onto public hello.Greeting hello.GreetingController.greeting(java.lang.String)
Also, how are you POSTing? I can recommend the Advanced REST client for Google Chrome. If you’re posting from a form in your browser, try hitting f12 and examining the Network tab to check that you are POSTing exactly what you think you’re POSTing.
POSTing to the wrong URL, e.g. http://localhost:8080/greetings
instead of http://localhost:8080/greeting
will result in a Method Not Allowed error, although really the error is a typo in the URL, not the choice of HTTP method.
To see more detailed logging for the request processing, create a src/main/resources folder alongside your src/main/java folder, and create an application.properties file in there. Add this line to that file
logging.level.org.springframework.web=DEBUG
Then, if you try to POST to an unmapped URL, e.g. /greetings
instead of /greeting
, you’ll see these lines in you log:
RequestMappingHandlerMapping : Looking up handler method for path /greetings
RequestMappingHandlerMapping : Did not find handler method for [/greetings]
Enum Constant Details
-
CONTINUE
100 Continue
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.2.1
-
SWITCHING_PROTOCOLS
public static final HttpStatus SWITCHING_PROTOCOLS
101 Switching Protocols
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.2.2
-
PROCESSING
public static final HttpStatus PROCESSING
102 Processing
.- See Also:
-
- WebDAV
-
EARLY_HINTS
public static final HttpStatus EARLY_HINTS
103 Early Hints
.- Since:
- 6.0.5
- See Also:
-
- An HTTP Status Code for Indicating Hints
-
CHECKPOINT
103 Checkpoint
.- See Also:
-
- A proposal for supporting
resumable POST/PUT HTTP requests in HTTP/1.0
- A proposal for supporting
-
OK
200 OK
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.3.1
-
CREATED
201 Created
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.3.2
-
ACCEPTED
202 Accepted
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.3.3
-
NON_AUTHORITATIVE_INFORMATION
public static final HttpStatus NON_AUTHORITATIVE_INFORMATION
203 Non-Authoritative Information
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.3.4
-
NO_CONTENT
public static final HttpStatus NO_CONTENT
204 No Content
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.3.5
-
RESET_CONTENT
public static final HttpStatus RESET_CONTENT
205 Reset Content
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.3.6
-
PARTIAL_CONTENT
public static final HttpStatus PARTIAL_CONTENT
206 Partial Content
.- See Also:
-
- HTTP/1.1: Range Requests, section 4.1
-
MULTI_STATUS
public static final HttpStatus MULTI_STATUS
207 Multi-Status
.- See Also:
-
- WebDAV
-
ALREADY_REPORTED
public static final HttpStatus ALREADY_REPORTED
208 Already Reported
.- See Also:
-
- WebDAV Binding Extensions
-
IM_USED
226 IM Used
.- See Also:
-
- Delta encoding in HTTP
-
MULTIPLE_CHOICES
public static final HttpStatus MULTIPLE_CHOICES
300 Multiple Choices
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.4.1
-
MOVED_PERMANENTLY
public static final HttpStatus MOVED_PERMANENTLY
301 Moved Permanently
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.4.2
-
FOUND
302 Found
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.4.3
-
MOVED_TEMPORARILY
302 Moved Temporarily
.- See Also:
-
- HTTP/1.0, section 9.3
-
SEE_OTHER
303 See Other
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.4.4
-
NOT_MODIFIED
public static final HttpStatus NOT_MODIFIED
304 Not Modified
.- See Also:
-
- HTTP/1.1: Conditional Requests, section 4.1
-
USE_PROXY
305 Use Proxy
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.4.5
-
TEMPORARY_REDIRECT
public static final HttpStatus TEMPORARY_REDIRECT
307 Temporary Redirect
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.4.7
-
PERMANENT_REDIRECT
public static final HttpStatus PERMANENT_REDIRECT
308 Permanent Redirect
.- See Also:
-
- RFC 7238
-
BAD_REQUEST
public static final HttpStatus BAD_REQUEST
400 Bad Request
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.1
-
UNAUTHORIZED
public static final HttpStatus UNAUTHORIZED
401 Unauthorized
.- See Also:
-
- HTTP/1.1: Authentication, section 3.1
-
PAYMENT_REQUIRED
public static final HttpStatus PAYMENT_REQUIRED
402 Payment Required
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.2
-
FORBIDDEN
403 Forbidden
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.3
-
NOT_FOUND
404 Not Found
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.4
-
METHOD_NOT_ALLOWED
public static final HttpStatus METHOD_NOT_ALLOWED
405 Method Not Allowed
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.5
-
NOT_ACCEPTABLE
public static final HttpStatus NOT_ACCEPTABLE
406 Not Acceptable
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.6
-
PROXY_AUTHENTICATION_REQUIRED
public static final HttpStatus PROXY_AUTHENTICATION_REQUIRED
407 Proxy Authentication Required
.- See Also:
-
- HTTP/1.1: Authentication, section 3.2
-
REQUEST_TIMEOUT
public static final HttpStatus REQUEST_TIMEOUT
408 Request Timeout
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.7
-
CONFLICT
409 Conflict
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.8
-
GONE
410 Gone
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.9
-
LENGTH_REQUIRED
public static final HttpStatus LENGTH_REQUIRED
411 Length Required
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.10
-
PRECONDITION_FAILED
public static final HttpStatus PRECONDITION_FAILED
412 Precondition failed
.- See Also:
-
- HTTP/1.1: Conditional Requests, section 4.2
-
PAYLOAD_TOO_LARGE
public static final HttpStatus PAYLOAD_TOO_LARGE
413 Payload Too Large
.- Since:
- 4.1
- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.11
-
REQUEST_ENTITY_TOO_LARGE
413 Request Entity Too Large
.- See Also:
-
- HTTP/1.1, section 10.4.14
-
URI_TOO_LONG
public static final HttpStatus URI_TOO_LONG
414 URI Too Long
.- Since:
- 4.1
- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.12
-
REQUEST_URI_TOO_LONG
414 Request-URI Too Long
.- See Also:
-
- HTTP/1.1, section 10.4.15
-
UNSUPPORTED_MEDIA_TYPE
public static final HttpStatus UNSUPPORTED_MEDIA_TYPE
415 Unsupported Media Type
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.13
-
REQUESTED_RANGE_NOT_SATISFIABLE
public static final HttpStatus REQUESTED_RANGE_NOT_SATISFIABLE
416 Requested Range Not Satisfiable
.- See Also:
-
- HTTP/1.1: Range Requests, section 4.4
-
EXPECTATION_FAILED
public static final HttpStatus EXPECTATION_FAILED
417 Expectation Failed
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.5.14
-
I_AM_A_TEAPOT
public static final HttpStatus I_AM_A_TEAPOT
418 I'm a teapot
.- See Also:
-
- HTCPCP/1.0
-
INSUFFICIENT_SPACE_ON_RESOURCE
-
METHOD_FAILURE
-
DESTINATION_LOCKED
-
UNPROCESSABLE_ENTITY
public static final HttpStatus UNPROCESSABLE_ENTITY
422 Unprocessable Entity
.- See Also:
-
- WebDAV
-
LOCKED
423 Locked
.- See Also:
-
- WebDAV
-
FAILED_DEPENDENCY
public static final HttpStatus FAILED_DEPENDENCY
424 Failed Dependency
.- See Also:
-
- WebDAV
-
TOO_EARLY
425 Too Early
.- Since:
- 5.2
- See Also:
-
- RFC 8470
-
UPGRADE_REQUIRED
public static final HttpStatus UPGRADE_REQUIRED
426 Upgrade Required
.- See Also:
-
- Upgrading to TLS Within HTTP/1.1
-
PRECONDITION_REQUIRED
public static final HttpStatus PRECONDITION_REQUIRED
428 Precondition Required
.- See Also:
-
- Additional HTTP Status Codes
-
TOO_MANY_REQUESTS
public static final HttpStatus TOO_MANY_REQUESTS
429 Too Many Requests
.- See Also:
-
- Additional HTTP Status Codes
-
UNAVAILABLE_FOR_LEGAL_REASONS
public static final HttpStatus UNAVAILABLE_FOR_LEGAL_REASONS
451 Unavailable For Legal Reasons
.- Since:
- 4.3
- See Also:
-
- An HTTP Status Code to Report Legal Obstacles
-
INTERNAL_SERVER_ERROR
public static final HttpStatus INTERNAL_SERVER_ERROR
500 Internal Server Error
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.6.1
-
NOT_IMPLEMENTED
public static final HttpStatus NOT_IMPLEMENTED
501 Not Implemented
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.6.2
-
BAD_GATEWAY
public static final HttpStatus BAD_GATEWAY
502 Bad Gateway
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.6.3
-
SERVICE_UNAVAILABLE
public static final HttpStatus SERVICE_UNAVAILABLE
503 Service Unavailable
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.6.4
-
GATEWAY_TIMEOUT
public static final HttpStatus GATEWAY_TIMEOUT
504 Gateway Timeout
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.6.5
-
HTTP_VERSION_NOT_SUPPORTED
public static final HttpStatus HTTP_VERSION_NOT_SUPPORTED
505 HTTP Version Not Supported
.- See Also:
-
- HTTP/1.1: Semantics and Content, section 6.6.6
-
VARIANT_ALSO_NEGOTIATES
public static final HttpStatus VARIANT_ALSO_NEGOTIATES
506 Variant Also Negotiates
- See Also:
-
- Transparent Content Negotiation
-
INSUFFICIENT_STORAGE
public static final HttpStatus INSUFFICIENT_STORAGE
507 Insufficient Storage
- See Also:
-
- WebDAV
-
LOOP_DETECTED
public static final HttpStatus LOOP_DETECTED
508 Loop Detected
- See Also:
-
- WebDAV Binding Extensions
-
BANDWIDTH_LIMIT_EXCEEDED
public static final HttpStatus BANDWIDTH_LIMIT_EXCEEDED
509 Bandwidth Limit Exceeded
-
NOT_EXTENDED
public static final HttpStatus NOT_EXTENDED
510 Not Extended
- See Also:
-
- HTTP Extension Framework
-
NETWORK_AUTHENTICATION_REQUIRED
public static final HttpStatus NETWORK_AUTHENTICATION_REQUIRED
511 Network Authentication Required
.- See Also:
-
- Additional HTTP Status Codes
Method Details
-
values
Returns an array containing the constants of this enum class, in
the order they are declared.- Returns:
- an array containing the constants of this enum class, in the order they are declared
-
valueOf
Returns the enum constant of this class with the specified name.
The string must match exactly an identifier used to declare an
enum constant in this class. (Extraneous whitespace characters are
not permitted.)- Parameters:
name
— the name of the enum constant to be returned.- Returns:
- the enum constant with the specified name
- Throws:
IllegalArgumentException
— if this enum class has no constant with the specified nameNullPointerException
— if the argument is null
-
value
public int value()
Return the integer value of this status code.
- Specified by:
value
in interfaceHttpStatusCode
-
series
Return the HTTP status series of this status code.
- See Also:
-
HttpStatus.Series
-
getReasonPhrase
public String getReasonPhrase()
Return the reason phrase of this status code.
-
is1xxInformational
public boolean is1xxInformational()
Whether this status code is in the Informational class (
1xx
).- Specified by:
is1xxInformational
in interfaceHttpStatusCode
- See Also:
-
- RFC 2616
-
is2xxSuccessful
public boolean is2xxSuccessful()
Whether this status code is in the Successful class (
2xx
).- Specified by:
is2xxSuccessful
in interfaceHttpStatusCode
- See Also:
-
- RFC 2616
-
is3xxRedirection
public boolean is3xxRedirection()
Whether this status code is in the Redirection class (
3xx
).- Specified by:
is3xxRedirection
in interfaceHttpStatusCode
- See Also:
-
- RFC 2616
-
is4xxClientError
public boolean is4xxClientError()
Whether this status code is in the Client Error class (
4xx
).- Specified by:
is4xxClientError
in interfaceHttpStatusCode
- See Also:
-
- RFC 2616
-
is5xxServerError
public boolean is5xxServerError()
Whether this status code is in the Server Error class (
5xx
).- Specified by:
is5xxServerError
in interfaceHttpStatusCode
- See Also:
-
- RFC 2616
-
isError
public boolean isError()
Whether this status code is in the Client or Server Error class
- Specified by:
isError
in interfaceHttpStatusCode
- See Also:
-
- RFC 2616
- RFC 2616
(4xx
or5xx
). HttpStatusCode.is4xxClientError()
HttpStatusCode.is5xxServerError()
-
toString
Return a string representation of this status code.
- Overrides:
toString
in classEnum<HttpStatus>
-
valueOf
public static HttpStatus valueOf(int statusCode)
Return the
HttpStatus
enum constant with the specified numeric value.- Parameters:
statusCode
— the numeric value of the enum to be returned- Returns:
- the enum constant with the specified numeric value
- Throws:
IllegalArgumentException
— if this enum has no constant for the specified numeric value
-
resolve
Resolve the given status code to an
HttpStatus
, if possible.- Parameters:
statusCode
— the HTTP status code (potentially non-standard)- Returns:
- the corresponding
HttpStatus
, ornull
if not found - Since:
- 5.0
1. Overview
This quick article is focused on a common error – ‘Request Method not Supported – 405′ – that developers face while exposing their APIs for specific HTTP verbs, with Spring MVC.
Naturally, we’ll also discuss the common causes of this error.
2. Request Method Basics
Before moving towards the common problem, if you’re just starting to learn about Spring MVC, here’s a good intro article to start with.
Let’s also have a very quick look at the basics – and understand the request methods supported by Spring and some of the common classes of interest here.
In a highly simplified way, MVC HTTP methods are basic operations that a request can trigger on the server. For example, some methods fetch the data from the server, some submit data to the server, some might delete the data etc.
The @RequestMapping annotation specifies the supported methods for the request.
Spring declares all the supported request methods under an enum RequestMethod; it specifies the standard GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE verbs.
The Spring DispatcherServlet supports all of them by default except OPTIONS and TRACE; @RequestMapping uses the RequestMethod enum to specifies which methods are supported.
3. Simple MVC Scenario
Now, let’s have a look at a code example that maps all HTTP methods:
@RestController
@RequestMapping(value="/api")
public class RequestMethodController {
@Autowired
private EmployeeService service;
@RequestMapping(value = "/employees", produces = "application/json")
public List<Employee> findEmployees()
throws InvalidRequestException {
return service.getEmployeeList();
}
}
Notice how the example declares findEmployee() method. It doesn’t specify any specific request method, which means this URL supports all default methods.
We can request the API using different supported methods, for example, using curl:
$ curl --request POST http://localhost:8080/api/employees
[{"id":100,"name":"Steve Martin","contactNumber":"333-777-999"},
{"id":200,"name":"Adam Schawn","contactNumber":"444-111-777"}]
Naturally, we can send the request in multiple ways – via a simple curl command, Postman, AJAX, etc.
And, of course, we’re expecting to get the 200 OK response, if the request is correctly mapped and successful.
4. Problem Scenario – the HTTP 405
But, what we’re discussing here is – of course – the scenarios when the request won’t be successful.
‘405 Method Not Allowed’ is one of the most common errors we observe while working with Spring requests.
Let’s have a look at what happens if we specifically define and handle GET requests in Spring MVC, like this:
@RequestMapping(
value = "/employees",
produces = "application/json",
method = RequestMethod.GET)
public List<Employee> findEmployees() {
...
}
// send the PUT request using CURL
$ curl --request PUT http://localhost:8080/api/employees
{"timestamp":1539720588712,"status":405,"error":"Method Not Allowed",
"exception":"org.springframework.web.HttpRequestMethodNotSupportedException",
"message":"Request method 'PUT' not supported","path":"/api/employees"}
[[Not Support – Reason, Solution
[[What we’re getting in this previous scenario is the HTTP response with the 405 Status Code – a client error that indicates that the server doesn’t support the method/verb sent in the request.
As the name suggests here, the reason for this error is sending the request with a non-supported method.
As you can expect, we can solve this by defining an explicit mapping for PUT, in the existing method mapping:
@RequestMapping(
value = "/employees",
produces = "application/json",
method = {RequestMethod.GET, RequestMethod.PUT}) ...
Alternatively, we can define the new method/mapping separately:
@RequestMapping(value = "/employees",
produces = "application/json",
method=RequestMethod.PUT)
public List<Employee> postEmployees() ...
6. Conclusion
The request method/verb is a critical aspect in HTTP communication, and we need to be careful with the exact semantics of the operations we define on the server side, and then with the exact requests we’re sending in.
And as always, the examples shown in this article are available on over on GitHub.
The HTTP 405 error is a common error encountered when building RESTful APIs with the Spring Web MVC framework. This error occurs when a client sends an HTTP request to a server with an unsupported HTTP method for the requested resource. Spring Web MVC provides a default handling mechanism for this error, however, in some cases, it may be desirable to provide a custom handling mechanism. In this article, we will discuss how to fix the custom handling of the HTTP 405 error with Spring Web MVC.
Method 1: Override handleMethodNotAllowed
To override the handleMethodNotAllowed
method in Spring Web MVC, you need to create a custom DefaultHandlerExceptionResolver
and register it in your application context. Here’s how you can do it:
- Create a custom
HandlerExceptionResolver
by extendingDefaultHandlerExceptionResolver
:
public class CustomHandlerExceptionResolver extends DefaultHandlerExceptionResolver {
@Override
protected ModelAndView handleMethodNotAllowed(HttpRequestMethodNotSupportedException ex, HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
// your custom handling logic here
return super.handleMethodNotAllowed(ex, request, response, handler);
}
}
- Register the custom
HandlerExceptionResolver
in your application context:
<bean id="handlerExceptionResolver" class="org.springframework.web.servlet.handler.HandlerExceptionResolverComposite">
<property name="order" value="0" />
<property name="exceptionResolvers">
<list>
<bean class="com.example.CustomHandlerExceptionResolver" />
<ref bean="defaultHandlerExceptionResolver" />
</list>
</property>
</bean>
- Test your custom handling logic by triggering a
405 Method Not Allowed
error in your application.
With this setup, any 405
errors thrown by Spring Web MVC will be handled by your custom logic in the handleMethodNotAllowed
method.
Method 2: Use @ExceptionHandler
To handle 405 error with Spring Web MVC using @ExceptionHandler
, you can follow these steps:
- Create a custom exception class, for example,
MethodNotAllowedException
:
public class MethodNotAllowedException extends RuntimeException {
public MethodNotAllowedException(String message) {
super(message);
}
}
- Add
@ExceptionHandler
method in your controller to handleMethodNotAllowedException
:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodNotAllowedException.class)
public ResponseEntity<String> handleMethodNotAllowed(MethodNotAllowedException ex) {
return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).body(ex.getMessage());
}
}
- In your controller method, throw
MethodNotAllowedException
when the request method is not allowed:
@RequestMapping(value = "/example", method = RequestMethod.POST)
public ResponseEntity<String> exampleMethod() {
// some logic here
if (requestMethodNotAllowed) {
throw new MethodNotAllowedException("Method not allowed");
}
return ResponseEntity.ok("Success");
}
In the above example, when the request method is not allowed, MethodNotAllowedException
will be thrown and handled by the @ExceptionHandler
method in GlobalExceptionHandler
class. It will return a response with HTTP status code 405 and the error message.
Note that the @ControllerAdvice
annotation is used to make the GlobalExceptionHandler
class a global exception handler for all controllers in the application.
By using @ExceptionHandler
, you can customize the error handling logic for specific exceptions in your Spring Web MVC application.
Method 3: Customize the ResponseStatusExceptionResolver
To customize the handling of a 405 error with Spring Web MVC, you can customize the ResponseStatusExceptionResolver
. This can be done by extending the ResponseStatusExceptionResolver
class and overriding its handleNoSuchRequestHandlingMethod
method.
Here’s an example code snippet:
public class CustomResponseStatusExceptionResolver extends ResponseStatusExceptionResolver {
@Override
protected ModelAndView handleNoSuchRequestHandlingMethod(NoSuchRequestHandlingMethodException ex, HttpServletRequest request, HttpServletResponse response) throws IOException {
if (ex.getMethod().equals("POST")) {
response.setStatus(HttpStatus.METHOD_NOT_ALLOWED.value());
response.getWriter().write("Custom error message for POST method not allowed");
response.getWriter().flush();
return new ModelAndView();
} else {
return super.handleNoSuchRequestHandlingMethod(ex, request, response);
}
}
}
In this example, we’re checking if the HTTP method for the request is POST
. If it is, we’re setting the response status to 405 Method Not Allowed
and writing a custom error message to the response body. If it’s not a POST
request, we’re calling the parent handleNoSuchRequestHandlingMethod
method to handle the error.
To use this custom resolver, you can configure it in your Spring context file:
<bean id="handlerExceptionResolver" class="com.example.CustomResponseStatusExceptionResolver"/>
That’s it! Now, when a POST
request is made to a non-existent endpoint, the custom error message will be returned in the response body with a 405 Method Not Allowed
status.
-
REST
Spring MVC
Метод запроса не поддерживается (405) весной
1. обзор
Эта небольшая статья посвящена распространенной ошибке — «Метод запроса не поддерживается» — 405 ‘, с которой сталкиваются разработчики, выставляя свои API-интерфейсы для определенных HTTP-глаголов в Spring MVC.
Естественно, мы также обсудим общие причины этой ошибки.
2. Основы метода запроса
Прежде чем перейти к общей проблеме, если вы только начинаете знакомиться с Spring MVC, вот хорошийintro article для начала.
Давайте также очень быстро рассмотрим основы — и разберемся с методами запроса, поддерживаемыми Spring, а также с некоторыми интересующими здесь общими классами.
Упрощенно, методы MVC HTTP — это основные операции, которые запрос может инициировать на сервере. Например, некоторые методыfetch данные с сервера, некоторыеsubmit данные на сервер, некоторые могутdelete данные и т. Д.
@RequestMapping annotation указывает поддерживаемые методы для запроса.
Spring объявляет все поддерживаемые методы запроса в перечисленииRequestMethod; он определяет стандартные глаголыGET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE.
Spring DispatcherServlet по умолчанию поддерживает их все, кромеOPTIONS иTRACE; @RequestMapping используетRequestMethod enum, чтобы указать, какие методы поддерживаются.
3. Простой сценарий MVC
Теперь давайте посмотрим на пример кода, который отображает все методы HTTP:
@RestController
@RequestMapping(value="/api")
public class RequestMethodController {
@Autowired
private EmployeeService service;
@RequestMapping(value = "/employees", produces = "application/json")
public List findEmployees()
throws InvalidRequestException {
return service.getEmployeeList();
}
}
Обратите внимание, как в примере объявляется методfindEmployee(). В нем не указан какой-либо конкретный метод запроса, что означает, что этот URL поддерживает все методы по умолчанию.
Мы можем запросить API, используя различные поддерживаемые методы, например, используя curl:
$ curl --request POST http://localhost:8080/api/employees
[{"id":100,"name":"Steve Martin","contactNumber":"333-777-999"},
{"id":200,"name":"Adam Schawn","contactNumber":"444-111-777"}]
Естественно, мы можем отправить запрос несколькими способами — с помощью простой командыcurl, Postman, AJAX и т. Д.
И, конечно же, мы ожидаем получить ответ200 OK, если запрос правильно сопоставлен и успешен.
4. Сценарий проблемы — HTTP 405
Но то, что мы здесь обсуждаем, — это, конечно, сценарии, когда запрос не будет успешным.
«405 Method Not Allowed» — одна из наиболее распространенных ошибок, которые мы наблюдаем при работе с запросами Spring.
Давайте посмотрим, что произойдет, если мы специально определим и обработаем запросы GET в Spring MVC, например:
@RequestMapping(
value = "/employees",
produces = "application/json",
method = RequestMethod.GET)
public List findEmployees() {
...
}
// send the PUT request using CURL
$ curl --request PUT http://localhost:8080/api/employees
{"timestamp":1539720588712,"status":405,"error":"Method Not Allowed",
"exception":"org.springframework.web.HttpRequestMethodNotSupportedException",
"message":"Request method 'PUT' not supported","path":"/api/employees"}
5. 405 Не поддерживается — причина, решение
В этом предыдущем сценарии мы получили ответ HTTP с кодом состояния 405 —a client error that indicates that the server doesn’t support the method/verb sent in the request.
Как следует из названия, причиной этой ошибки является отправка запроса неподдерживаемым методом.
Как вы можете ожидать, мы можем решить эту проблему, определив явное отображение для PUT в существующем отображении метода:
@RequestMapping(
value = "/employees",
produces = "application/json",
method = {RequestMethod.GET, RequestMethod.PUT}) ...
В качестве альтернативы, мы можем определить новый метод / отображение отдельно:
@RequestMapping(value = "/employees",
produces = "application/json",
method=RequestMethod.PUT)
public List postEmployees() ...
6. Заключение
Метод / команда запроса является критическим аспектом в HTTP-коммуникации, и нам нужно быть осторожными с точной семантикой операций, которые мы определяем на стороне сервера, а затем с точными запросами, которые мы отправляем.
И, как всегда, примеры, показанные в этой статье, доступны наover on GitHub.