springMVC除了给我们参数位值传输一些简单注解(@PathVariable,@RequesrHeader,@MedelAttibute,@RequestParam,@MatrixVariable,@cookievalue,@RequestBody)能参数解析外。我们方法位值也允许传入一些Servlet API(WebRequest,ServetRequest,MultipartRequest,HttpSession,javax.servlet.http.PushBuilder,Principal,ImputStream,Reader,HttpMethod,Locale,TimeZone,Zoneld)作为参数,
比如我们写个RequestController.java:
@Controller //普通的Controller,它只是我们的一个控制器
public class RequestController {
//如果是控制器我们默认方法的返回时进行页面跳转的
@GetMapping("/goto")
public String goToPage(HttpServletRequest request){
request.setAttribute("msg","成功了");
request.setAttribute("code",200);
return "forward:/success"; //转发到 /success请求
}
}
里面有一个/goto方法,传入了原生的request对象。request.setAttribute("msg","成功了");我们打上断点Debug一下,我们来看一下我们的request对象是用哪个参数解析器来进行处理的;我们发送localhost:8080/goto请求:一路step over来到我们WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);,Resume Program(F9)到我们执行方法的Object returnValue = invokeforRequest(webRequest,mavContainer,providedArgs);(获取我们的参数值)steo into 拿到我们所有参数(MethodParamrter[] parameters = getMethodParameters();)然后拿到我们所有参数,拿到我们的第一个参数(parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);)我们接下来看resolvers supports parameter(if(!resolvers.supportsParameter(parameter)))接下来就要看我们这些解析器能不能解析我这个类型(com.huihu.boot.controller.goToPage(javax.servlrt.http.Servlet.http.HttpServletRequest))的参数,这个类型的参数能够明显看到这个参数是HttpServletRequest,我们看它能不能解析(step into):
我们这所有的参数解析器挨个遍历断点打到(for(HadlerMethodArgumentResolver resolver : this.argumentResolvers)中的if(resolver.supportParameter(parameter)))遍历的第一个
是叫RequestParamMethodArgumentRequest,放行到ServletRequestMethodArgumentResolver支持。
拿到这个解析器(HandlerMethodArrgumentResolver resolver = getArgumentResolver(parameter);)调用解析(if(resolver == null))它怎么把原生的Request传过来
在HandlerMethodArgumentResolverComposite.java里有一个方法public Object resolveArgument(MethodParameter parameter,@Nullable ModelAndViewContainer mavCon...,
NativeWebRequest webRequest,...)throws Exception{
}的一个形参webRequest相当于把Request和response原生的这俩个东西全部组合放到了这个对象里面(NativeWebRequest webRequest)然后解析参数的时候,我们现在想要拿到原生的Request对象(Class> paramType = paramter.getParameterType();)它就在这判断(if(WebRequest.class.isAssignableFrom(paramType)))对象类型(paramType)是不是WebRequest,我们不是,而我们是ServletRequest就对了(if(ServletRequest.class.isAssignableFrom(paramType)))然后他给我们解析step into(他把webRequest(return resolveNativeRequest(webRequest,paramType))传进来)也就是webRequest把我们这个原生的request请求拿到(T nativeRequest = webRequest.getNativeRequest(requiredType);)然后把原生的request请求往回一返(return nativeRequest;)就行了
WebRequest,ServetRequest,MultipartRequest,HttpSession,javax.servlet.http.PushBuilder,Principal,ImputStream,Reader,HttpMethod,Locale,TimeZone,Zoneld
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) && !parameter.hasParameterAnnotations()) ||
InputStream.class.isAssignableFrom(paramType) ||
Reader.class.isAssignableFrom(paramType) ||
HttpMethod.class == paramType ||
Locale.class == paramType ||
TimeZone.class == paramType ||
ZoneId.class == paramType);
}



