Servlet-API 参数解析原理
# 240.Servlet-API 参数解析原理
除了给方法参数中加一些注解,来绑定前端的参数之外,我们还可以传入一些原生的 Servlet-API 对象,那么其底层又是如何实现的呢?
比如之前我们的 /goto
路径,就传入了一个 request 对象:
@GetMapping("/goto")
public String goToPage(HttpServletRequest request) {
request.setAttribute("msg", "成功了");
request.setAttribute("code", 200);
return "forward:/success"; //转发到 /success请求
}
1
2
3
4
5
6
2
3
4
5
6
我们在 InvocableHandlerMethod
类的 getMethodArgumentValues
方法上打一个断点,然后以 debug 的方式启动,访问 http://localhost: 8888/goto (opens new window)
然后我们一点点的步入,到最后还是遍历所有的解析器集合(上节课讲过如何 debug 到这一步)
我们逐个遍历,直到遍历到解析器 ServletRequestMethodArgumentResolver
,然后我们步入进去:
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> paramType = parameter.getParameterType();
return (WebRequest.class.isAssignableFrom(paramType) ||
ServletRequest.class.isAssignableFrom(paramType) ||
MultipartRequest.class.isAssignableFrom(paramType) ||
HttpSession.class.isAssignableFrom(paramType) ||
(pushBuilder != null && pushBuilder.isAssignableFrom(paramType)) ||
Principal.class.isAssignableFrom(paramType) ||
InputStream.class.isAssignableFrom(paramType) ||
Reader.class.isAssignableFrom(paramType) ||
HttpMethod.class == paramType ||
Locale.class == paramType ||
TimeZone.class == paramType ||
ZoneId.class == paramType);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
可以看到,其 supports 方法会判断是否 Servlet-API 的类型;因此我们的 Servlet 类型的方法参数是支持的,返回该解析器。
然后我们步出到前面几步,就是调用返回的解析器里的方法来赋值:我们步入进去
步入后,可以看到方法上有个参数叫 webRequest,其实就是 request+response 对象的组合(也是上一个方法传入进来的)
然后再步入最后一行的方法:
这会执行到判断 ServletRequest 对象的 if 分支里,我们再步入:
然后其里面,就是返回原生的 Servlet 对象:
private <T> T resolveNativeRequest(NativeWebRequest webRequest, Class<T> requiredType) {
T nativeRequest = webRequest.getNativeRequest(requiredType);
if (nativeRequest == null) {
throw new IllegalStateException("Current request is not of type [" + requiredType.getName() + "]: " + webRequest);
}
return nativeRequest;
}
1
2
3
4
5
6
7
2
3
4
5
6
7
上次更新: 2024/10/3 10:01:52