[置顶] SpringMVC从request中获取参数的原理
2017-09-27 19:34
218 查看
servlet原生:将查出的数据放在request、session、application域中
测试代码:
地址栏输入:http://localhost/SpringMVC_02_Param_Api/testApi
在DispatherServlet的doDispach方法上打上断点。以Debug模式运行
断点之后进入方法:
DispatcherServlet
调用AnnotationMethodHandlerAdapter.handle方法
调用本类的方法。执行目标方法
调用HandlerMethodInvoker的invokeHandlerMethod方法。方法执行者执行目标方法
调用本类的resolveHandlerArguments方法。解析方法参数
调用本类的resolveCommonArgument方法。解析的细节
调用本类的resolveStandardArgument方法。解析标准参数
这就是解析HttpServletRequest参数的过程。
通过request.getSession()、request.getUserPrincipal()、 request.getInputStream()、request.getReader()解析参数。
测试代码:
@RequestMapping("/testApi") public void testApi(HttpServletRequest request, HttpServletResponse response) { System.out.println(request.getParameter("abc")); try { //注意那个CharacterEncodingFilter只是设置了响应的编码格式, //并没有设置内容类型。所以原生写数据必须使用response.setContentType("text/html"); //解析器解析的响应结果,他会自己设置好一些类型, //原生直接写,是把他都忽略了。 response.setContentType("text/html"); response.getWriter().write("我是直接写的..."); } catch (IOException e) { e.printStackTrace(); } //return "success"; }
地址栏输入:http://localhost/SpringMVC_02_Param_Api/testApi
在DispatherServlet的doDispach方法上打上断点。以Debug模式运行
断点之后进入方法:
DispatcherServlet
//执行目标方法 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
调用AnnotationMethodHandlerAdapter.handle方法
@Override public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ... //执行目标方法 return invokeHandlerMethod(request, response, handler); }
调用本类的方法。执行目标方法
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //根据handle找到方法解析器 ServletHandlerMethodResolver methodResolver = getMethodResolver(handler); //获取目标方法 Method handlerMethod = methodResolver.resolveHandlerMethod(request); //找到方法执行者 ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver); ServletWebRequest webRequest = new ServletWebRequest(request, response); ExtendedModelMap implicitModel = new BindingAwareModelMap(); //方法执行者执行目标方法 Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel); ModelAndView mav = methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest); methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest); return mav; }
调用HandlerMethodInvoker的invokeHandlerMethod方法。方法执行者执行目标方法
public final Object invokeHandlerMethod(Method handlerMethod, Object handler, NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception { Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod); ... //解析方法参数 Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel); ... }
调用本类的resolveHandlerArguments方法。解析方法参数
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler, NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception { Class<?>[] paramTypes = handlerMethod.getParameterTypes(); Object[] args = new Object[paramTypes.length]; ... if (annotationsFound == 0) { //解析细节 Object argValue = resolveCommonArgument(methodParam, webRequest); if (argValue != WebArgumentResolver.UNRESOLVED) { args[i] = argValue; } ... return args; }
调用本类的resolveCommonArgument方法。解析的细节
protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception { // Invoke custom argument resolvers if present... if (this.customArgumentResolvers != null) { for (WebArgumentResolver argumentResolver : this.customArgumentResolvers) { Object value = argumentResolver.resolveArgument(methodParameter, webRequest); if (value != WebArgumentResolver.UNRESOLVED) { return value; } } } // Resolution of standard parameter types... Class<?> paramType = methodParameter.getParameterType(); //解析标准参数 Object value = resolveStandardArgument(paramType, webRequest); if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) { throw new IllegalStateException("Standard argument type [" + paramType.getName() + "] resolved to incompatible value of type [" + (value != null ? value.getClass() : null) + "]. Consider declaring the argument type in a less specific fashion."); } return value; }
调用本类的resolveStandardArgument方法。解析标准参数
@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); }
这就是解析HttpServletRequest参数的过程。
通过request.getSession()、request.getUserPrincipal()、 request.getInputStream()、request.getReader()解析参数。
相关文章推荐
- SpringMVC中使用Ajax POST请求以json格式传递参数服务端通过request.getParameter("name")无法获取参数值问题分析
- springMvc 完美解决 multipart/form-data 方式提交请求 在 Filter 中 ServletRequest.getParameter方法 获取不到参数的问题
- springmvc @RequestParam 获取参数 HTTP Status 400 - Required String parameter 'xx' is not present
- springMVC参数的传递方式(1.通过@PathVariabl获取路径参数,2.@ModelAttribute获取数据,3.HttpServletRequest取参,4@RequestParam)
- 在SpringMVC后台控制层获取参数的方式主要有两种,一种是request.getParameter("name"),另外一种是用注解@RequestParam直接获取。这里主要讲这个注解
- springMVC参数的传递方式(1.通过@PathVariabl获取路径参数,2.@ModelAttribute获取数据,3.HttpServletRequest取参,4@RequestParam)
- springMVC --@RequestParam注解(后台控制器获取参数)
- 注解:SpringMVC中表单参数的限定和获取表单参数以及获取request,response,session+方法返回值讲解
- SpringMVC_RequestContextHolder获取请求参数
- springMvc 完美解决 multipart/form-data 方式提交请求 在 Filter 中 ServletRequest.getParameter方法 获取不到参数的问题
- 4.SpringMVC_@RequestParam和@RequestHeader 、@CookieValue 获取请求参数
- SpringMVC中使用Ajax POST请求以json格式传递参数服务端通过request.getParameter("name")无法获取参数值问题分析
- SpringMVC AOP 里面在invoke方法里面获取request参数
- request.getParameter和SpringMVC后台控制层获取参数的方式
- springMvc 完美解决 multipart/form-data 方式提交请求 在 Filter 中 ServletRequest.getParameter方法 获取不到参数的问题
- Request 接收参数乱码原理解析
- context.Request.QueryString获取中文参数乱码问题
- HttpServletRequest request 获取form参数的两种方式
- 通过SpringAOP获取request中所有参数,记录用户操作日志
- HttpServletRequest获取请求参数