This is the fourth day of my participation in the First Challenge 2022.
HTML forms only support GET and POST requests. Other request methods, such as PUT and DELETE, cannot be sent directly through HTML. The value of the method attribute can only be GET, POST, or Dialog (dialog is used to close the dialog when submitting if the form is in a
To address this problem, Spring 3.0 added a filter, HiddenHttpMethodFilter. The filter overrides the original HTTP request method (that is, POST) using the _method value in the form, and then sends it to the HandlerMapping to find the corresponding Controller method.
<form action="..." method="post">
<input type="hidden" name="_method" value="put" />.</form>
Copy the code
doFilterInternal
methods
HiddenHTTPMethodFilter inherits from OncePerRequestFilter and implements the abstract method doFilterInternal.
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
HttpServletRequest requestToUse = request;
if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") = =null) {
String paramValue = request.getParameter(this.methodParam);
if (StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
if (ALLOWED_METHODS.contains(method)) {
requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
}
}
}
filterChain.doFilter((ServletRequest)requestToUse, response);
}
Copy the code
From the above several ifs, we can clearly understand that only when…
- The request method is
POST
; javax.servlet.error.exception
Properties fornull
(You can ignore it for the moment. It’s generally truenull
);methodParam
The value of theALLOW_METHODS
In (i.ePUT
,DELETE
和PATCH
), case insensitive;private static finalList<String> ALLOWED_METHODS; .static { ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name())); } Copy the code
The request is wrapped in the HttpMethodRequestWrapper class.
Note: Stringutils. haslength is a Spring utility method used to ensure that paramValue is not null and contains at least one non-whitespace character.
HttpMethodRequestWrapper
A wrapper class
HiddenHTTPMethodFilter within defined a private static class – HttpMethodRequestWrapper, rewrite the HttpServletRequestWrapper getMethod method of a class.
The original HttpMethodRequestWrapper returns the default getMethod method of the wrapped HttpServletRequest request object.
public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest {...private HttpServletRequest _getHttpServletRequest(a) {
return (HttpServletRequest)super.getRequest(); }...public String getMethod(a) {
return this._getHttpServletRequest().getMethod(); }... }Copy the code
HttpMethodRequestWrapper source code:
private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
private final String method;
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
super(request);
this.method = method;
}
public String getMethod(a) {
return this.method; }}Copy the code
With the method constructor above, the return value of getMethod is fixed to the value given at initialization. Simply PUT, the wrapper “takes a different approach” by assigning the Method property to the doFilterInternal method above to a value (that is, PUT, PATCH, or DELETE). And that’s what we’re going to use when we look for controllers.
To change the_method
Parameter names
Method parameter names can be set with setMethodParam.
public void setMethodParam(String methodParam) {
Assert.hasText(methodParam, "'methodParam' must not be empty");
this.methodParam = methodParam;
}
Copy the code
Note: Assert.hasText is also a Spring utility method that calls Stringutils. hasText (mentioned above) in the source code, but adds assertion functionality.
public static void hasText(@Nullable String text, String message) { if(! StringUtils.hasText(text)) {throw newIllegalArgumentException(message); }}Copy the code
The resources
- Docs. Spring. IO/spring – fram…
- Blog.csdn.net/geloin/arti…
- Developer.mozilla.org/zh-CN/docs/…