使用 Servlet API 作为入参
MVC 的 Handler 方法可以接受哪些 ServletAPI 类型的参数:
HttpServletRequest
HttpServletResponse
HttpSession
java.security.Principal
Locale
InputStream
OutputStream
Reader
Writer
示例
1. 添加JSP页面
<li>使用 Servlet API作为入参 <ul> <li><a href="user/testServletAPI">使用 Servlet API作为入参</a></li> <li><a href="user/testServletAPI2">使用 Servlet API作为入参</a></li> </ul> </li>
2. 添加处理器类
/**
* 可以使用Servlet原生的API作为目标方法的参数 具体支持以下类型
*
* HttpServletRequest
* HttpServletResponse
* HttpSession
* java.security.Principal
* Locale
* InputStream
* OutputStream
* Reader
* Writer
*
*/
@RequestMapping("testServletAPI")
public String testServletAPI(HttpServletRequest request,HttpServletResponse response)
{
System.out.println("------testServletAPI HttpServletRequest: " + request + "------");
System.out.println("------testServletAPI HttpServletResponse: " + response + "------");
return LOGIN;
}
@RequestMapping("testServletAPI2")
public void testServletAPI2(Writer writer) throws IOException
{
System.out.println("------testServletAPI2 Writer: " + writer + "------");
StringBuffer sb = new StringBuffer();
sb.append("<html><body>");
sb.append("<br/><a href='/org.rabbitx.web.spring4mvc/index.jsp'>Back TO Home Page</a>");
sb.append("</body></html>");
writer.write(sb.toString());
}
原理分析
1. 在 testServletAPI方法中打断点并使用debug模式启动服务器;
2. 在浏览器端点击对应连接启动调试;
3. 在调试窗口选中AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker(HandlerMethodInvoker).invokeHandlerMethod(Method, Object, NativeWebRequest, ExtendedModelMap) line: 175
其中,resolveHandlerArguments为解析处理参数方法。
4. 进入resolveHandlerArguments方法;
5. 找到resolveHandlerArguments方法中resolveCommonArgument方法并进入;
6. 找到resolveCommonArgument方法中resolveStandardArgument方法并进入;
7. 在方法resolveStandardArgument上使用Ctrl+T快捷键并选择"ServletHandlerMethodInvoker"进入;
8. 查看方法resolveStandardArgument可以知道SpringMVC本质上还是从原生ServletAPI中获取相应的对象;
@Override
protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest) throws Exception {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
if (ServletRequest.class.isAssignableFrom(parameterType) ||
MultipartRequest.class.isAssignableFrom(parameterType)) {
Object nativeRequest = webRequest.getNativeRequest(parameterType);
if (nativeRequest == null) {
throw new IllegalStateException(
"Current request is not of type [" + parameterType.getName() + "]: " + request);
}
return nativeRequest;
}
else if (ServletResponse.class.isAssignableFrom(parameterType)) {
this.responseArgumentUsed = true;
Object nativeResponse = webRequest.getNativeResponse(parameterType);
if (nativeResponse == null) {
throw new IllegalStateException(
"Current response is not of type [" + parameterType.getName() + "]: " + response);
}
return nativeResponse;
}
else if (HttpSession.class.isAssignableFrom(parameterType)) {
return request.getSession();
}
else if (Principal.class.isAssignableFrom(parameterType)) {
return request.getUserPrincipal();
}
else if (Locale.class.equals(parameterType)) {
return RequestContextUtils.getLocale(request);
}
else if (InputStream.class.isAssignableFrom(parameterType)) {
return request.getInputStream();
}
else if (Reader.class.isAssignableFrom(parameterType)) {
return request.getReader();
}
else if (OutputStream.class.isAssignableFrom(parameterType)) {
this.responseArgumentUsed = true;
return response.getOutputStream();
}
else if (Writer.class.isAssignableFrom(parameterType)) {
this.responseArgumentUsed = true;
return response.getWriter();
}
return super.resolveStandardArgument(parameterType, webRequest);
}