Learn from: Shang Silicon Valley
Use of Rest requests
Change of access method
The original access is to write get, post, delete and put separately, and the Rest request combines them to some extent.
Previous: / getUser get user / deleteUser delete user / editUser modify user / saveUser save user
Now: / user - > (get delete put post)
Implementation of core methods
Core Filter: OrderedHiddenHttpMethodFilter.class
Properties to configure
spring.mvc.hiddenmethod.filter=true
In the modified form, we add a line of input to the form, but we write a name and its value for this input, and then we hide it.
html code:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user" method="get"> <input value="REST-GET" type="submit"> </form> <form action="/user" method="post"> <input value="REST-POST" type="submit"> </form> <form action="/user" method="post"> <input name="_method" type="hidden" value="delete"> <input value="REST-DELETE" type="submit"> </form> <form action="/user" method="post"> <input name="_method" type="hidden" value="put"> <input value="REST-PUT" type="submit"> </form> </body> </html>
Our Controller reads:
@RequestMapping(value = "/user", method = RequestMethod.GET) public String getUser(){ return "GET-Zhang San"; } @RequestMapping(value = "/user", method = RequestMethod.POST) public String postUser(){ return "POST-Zhang San"; } @RequestMapping(value = "/user", method = RequestMethod.DELETE) public String deleteUser(){ return "DELETE-Zhang San"; } @RequestMapping(value = "/user", method = RequestMethod.PUT) public String putUser(){ return "PUT-Zhang San"; }
This configuration is correct, but we found that clicking the following two will still return the post request.
We can check it in webmvcoautoconfiguration.class.
Find the OrderedHiddenHttpMethodFilter filter.
This Filter intercepts our http requests, and we see that this Filter can be enabled only when the property of spring.mvc.hiddenmethod.filter is enabled.
Let's configure this attribute in yaml:
spring: mvc: hiddenmethod: filter: enabled: true #Enable the Rest function of page form
In this way, the delete request and put request can take effect.
How Rest requests work
We know that the core of the Rest request is Filter: OrderedHiddenHttpMethodFilter.class
So let's go to this class to see what the reason is.
We found that this class inherits another HiddenHttpMethodFilter.class
We click in and find a new method, doFilterInternal()
We can see that only when the method is POST and there are no errors will we enter this Filter, and then get the param with the name of this.methodParam. And the name is the same as the html setting before.
This is why the method of our form is POST.
We first open the previous form page, and then set a breakpoint for this method to run.
Click the delete method in the web page. We calculate it in the code and find it as a Post request.
Going down, we will find that the value of this paramValue is delete, that is, the value set in our html form.
We can see that this value will be set to uppercase later, so the value set in the form form is case sensitive.
Then judge whether our request exists in our list, and we wrap the requests.
We can see that requestswipper inherits HttpServletRequestWrapper, and this class inherits httpServletRequest, which is the native request interface, so this Wrapper is also a request interface. It means that our method is packaged.
We know that the RequestWrapper writes a getMethod method and returns the value of our custom method.
Then the method of calling Request later is the value of the method defined by ourselves.
We can also see that it supports not only put and delete, but also patch
Custom Filter
We can also define our own Filter.
We create a HiddenHttpMethodFilter by ourselves, and then call the setMethodParam("_m") method to modify the value of MethodParam.
Don't forget @ Bean
@Bean public HiddenHttpMethodFilter hiddenHttpMethodFilter(){ HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter(); methodFilter.setMethodParam("_m"); return methodFilter; }
New annotation requested
Direct @ {methodname}+Mapping