【spring-mvc】最常用的参数解析讲解
来源:互联网 发布:知乎客厅地板还是地砖 编辑:程序博客网 时间:2024/06/06 07:09
spring-mvc为我们提供了20多种默认的参数解析器。但是我们最常用的还是不加任何注解,直接得到我们的对象的一张参数解析方式。如下方法中的registerUser参数,spring-mvc是如何为我们创建这个有属性的对象。
/** * 注册 * * @return */ @ResponseBody @RequestMapping(value = "/register", method = RequestMethod.POST) public Result register(@Valid RegisterUser registerUser,HttpServletRequest request, HttpServletResponse response) { if (!RegularUtils.isPhone(registerUser.getUsername()) && !RegularUtils.isEmail(registerUser.getUsername())) { throw new BizException("请输入有效的用户名或者邮箱"); } if (registerService.findByName(registerUser.getUsername()) > 0) { throw new BizException("用户名已经被注册"); } if (!StringUtils.equals(registerUser.getPassword(), registerUser.getConfirmPassword())) { throw new BizException("输入的密码不一致"); } Result result = new Result(); //第二次加密 boolean flag = registerService.saveRegisterUser(registerUser); result.setSuccess(flag); if (flag) { //模拟用户登陆 try { UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( registerUser.getUsername(), registerUser.getPassword()); authRequest.setDetails(userDetailsService); Authentication authentication = authenticationManager.authenticate(authRequest); SecurityContextHolder.getContext().setAuthentication(authentication); //context最终会存储在session中 request.getSession().setAttribute("SPRING_SECURITY_CONTEXT",SecurityContextHolder.getContext()); } catch (AuthenticationException e) { result.setSuccess(false); result.setMessage("注册失败"); } } return result; }
直接进入参数解析处,其他的转发可以看我其他篇章的讲解。
RequestMappingHandlerAdapter中有个HandlerMethodArgumentResolverComposite参数复合类。
/** * Find a registered {@link HandlerMethodArgumentResolver} that supports the given method parameter. */ private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); if (result == null) { for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) { if (logger.isTraceEnabled()) { logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" + parameter.getGenericParameterType() + "]"); } if (methodArgumentResolver.supportsParameter(parameter)) { result = methodArgumentResolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; }
spring用到了大量的cache缓存,提高效率。暂时不讲解,主要看methodArgumentResolver.supportsParameter(parameter)
,此处就是遍历系统提供的参数解析器,当遍历到ServletModelAttributeMethodProcessor
时,
@Override public boolean supportsParameter(MethodParameter parameter) { if (parameter.hasParameterAnnotation(ModelAttribute.class)) { return true; } else if (this.annotationNotRequired) { return !BeanUtils.isSimpleProperty(parameter.getParameterType()); } else { return false; } }
this.annotationNotRequired会返回true,因为我们并未提供注解,并且该参数不是简单类型,所以此方法会返回true,即RequestMappingHandlerAdapter会将此参数交给ServletModelAttributeMethodProcessor
来解析,如下是解析过程:
@Override public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { String name = ModelFactory.getNameForParameter(parameter); Object attribute = (mavContainer.containsAttribute(name) ? mavContainer.getModel().get(name) : createAttribute(name, parameter, binderFactory, webRequest)); WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name); if (binder.getTarget() != null) { bindRequestParameters(binder, webRequest); validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) { throw new BindException(binder.getBindingResult()); } } // Add resolved attribute and BindingResult at the end of the model Map<String, Object> bindingResultModel = binder.getBindingResult().getModel(); mavContainer.removeAttributes(bindingResultModel); mavContainer.addAllAttributes(bindingResultModel); return binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter); }
其中WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
是创建一个绑定工厂,其中会含有一个validator验证器等,
protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) { ServletRequest servletRequest = (ServletRequest)request.getNativeRequest(ServletRequest.class); ServletRequestDataBinder servletBinder = (ServletRequestDataBinder)binder; servletBinder.bind(servletRequest); }
//绑定过程public void bind(ServletRequest request) { //此处是利用Web MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request); MultipartRequest multipartRequest = WebUtils.getNativeRequest(request, MultipartRequest.class); if (multipartRequest != null) { bindMultipart(multipartRequest.getMultiFileMap(), mpvs); } addBindValues(mpvs, request); doBind(mpvs);}//获取参数的过程。public ServletRequestParameterPropertyValues(ServletRequest request, String prefix, String prefixSeparator) { super(WebUtils.getParametersStartingWith( request, (prefix != null ? prefix + prefixSeparator : null)));}public MutablePropertyValues(Map<?, ?> original) { if(original != null) { this.propertyValueList = new ArrayList(original.size()); Iterator var2 = original.entrySet().iterator(); while(var2.hasNext()) { Entry entry = (Entry)var2.next(); this.propertyValueList.add(new PropertyValue(entry.getKey().toString(), entry.getValue())); } } else { this.propertyValueList = new ArrayList(0); }}
获取参数的方法WebUtils.getParametersStartingWith(request, (prefix != null ? prefix + prefixSeparator : null))
回归上述代码,就是MutablePropertyValues mpvs
中的mpvs会通过一系列构造函数得到一个含有属性和名称的properties.
protected void doBind(MutablePropertyValues mpvs) { checkAllowedFields(mpvs); checkRequiredFields(mpvs); applyPropertyValues(mpvs); }
applyPropertyValues(mpvs)就是将参数绑定到target对象上。
- 【spring-mvc】最常用的参数解析讲解
- Spring mvc 参数解析
- 【spring mvc】Spring MVC 的参数解析器ArgumentResolver阐述
- Spring MVC 思想的讲解
- spring MVC 接受表单参数常用的五种方法
- 常用Spring MVC获取请求参数的几种方法
- 最简单的 spring MVC
- Spring的常用注解讲解
- Spring的IOC和MVC的讲解
- Spring MVC 拦截器的讲解
- spring MVC 的 web.xml 配置讲解
- spring mvc的配置文件解析
- spring mvc的配置文件解析
- 使用XML解析器(TinyXML)编程之常用参数讲解-------转载的原版资料2
- spring mvc常用的注解:
- spring mvc常用的注解:
- spring mvc常用的注解:
- Spring MVC常用的注解
- R语言中基本图形的绘制
- 1012. The Best Rank (25)
- MySQL的嵌套事务实现
- Eclipse右击工程菜单中没有Android Tools选项
- LeetCode Binary Tree Level Order Traversal II
- 【spring-mvc】最常用的参数解析讲解
- apache root权限的获取
- 时间
- 子类调用父类默认构造函数
- Android Volley完全解析
- JavaScript中OpenTextFile函数 - JavaScript手册
- EL表达式
- javadoc 的注解
- 人工智能机器学习统计学数据挖掘之间有什么区别?