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/1/23 16:20:41