/** Resolves the given {@link RequestBody @RequestBody} annotation. */ @SuppressWarnings("unchecked") protected Object resolveRequestBody( MethodParameter methodParam, NativeWebRequest webRequest, Object handler) throws Exception { HttpInputMessage inputMessage = createHttpInputMessage(webRequest); Class paramType = methodParam.getParameterType(); MediaType contentType = inputMessage.getHeaders().getContentType(); if (contentType == null) { StringBuilder builder = new StringBuilder(ClassUtils.getShortName(methodParam.getParameterType())); String paramName = methodParam.getParameterName(); if (paramName != null) { builder.append(' '); builder.append(paramName); } throw new HttpMediaTypeNotSupportedException( "Cannot extract @RequestBody parameter (" + builder.toString() + "): no Content-Type found"); } List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>(); if (this.messageConverters != null) { for (HttpMessageConverter<?> messageConverter : this.messageConverters) { allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes()); if (messageConverter.canRead(paramType, contentType)) { return messageConverter.read(paramType, inputMessage); } } } throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes); }
private UriComponents applyContributers( UriComponentsBuilder builder, Method method, Object[] argumentValues, Map<String, Object> uriVars) { if (this.contributors.isEmpty()) { return builder.buildAndExpand(uriVars); } int paramCount = method.getParameters().length; int argCount = argumentValues.length; Assert.isTrue( paramCount == argCount, "Number of method parameters " + paramCount + " does not match number of argument values " + argCount); for (int i = 0; i < paramCount; i++) { MethodParameter param = new MethodParameter(method, i); param.initParameterNameDiscovery(parameterNameDiscoverer); for (UriComponentsContributor c : this.contributors) { if (c.supportsParameter(param)) { c.contributeMethodArgument( param, argumentValues[i], builder, uriVars, this.conversionService); break; } } } return builder.buildAndExpand(uriVars); }
private boolean isHypermediaDisabled(MethodParameter returnType) { return AnnotationUtils.findAnnotation(returnType.getMethod(), HypermediaDisabled.class) != null || AnnotationUtils.findAnnotation( returnType.getMethod().getDeclaringClass(), HypermediaDisabled.class) != null; }
private String getDetailedErrorMessage(String message, MethodParameter param) { StringBuilder sb = new StringBuilder(message); sb.append("argument [" + param.getParameterIndex() + "] "); sb.append("of type [" + param.getParameterType().getName() + "] "); sb.append("on method [" + getBridgedMethod().toGenericString() + "]"); return sb.toString(); }
/** * Extension point to setBasicInfoForCreate the model attribute if not found in the model. The * default implementation uses the default constructor. * * @param attributeName the name of the attribute, never {@code null} * @param parameter the method parameter * @param binderFactory for creating WebDataBinder instance * @param request the current request * @return the created model attribute, never {@code null} */ protected Object createAttribute( String attributeName, MethodParameter parameter, WebDataBinderFactory binderFactory, NativeWebRequest request) throws Exception { String value = getRequestValueForAttribute(attributeName, request); if (value != null) { Object attribute = createAttributeFromRequestValue(value, attributeName, parameter, binderFactory, request); if (attribute != null) { return attribute; } } Class<?> parameterType = parameter.getParameterType(); if (parameterType.isArray() || List.class.isAssignableFrom(parameterType)) { return ArrayList.class.newInstance(); } if (Set.class.isAssignableFrom(parameterType)) { return HashSet.class.newInstance(); } if (MapWapper.class.isAssignableFrom(parameterType)) { return MapWapper.class.newInstance(); } return BeanUtils.instantiateClass(parameter.getParameterType()); }
/** * Whether to raise a {@link org.springframework.validation.BindException} on bind or validation * errors. The default implementation returns {@code true} if the next method argument is not of * type {@link org.springframework.validation.Errors}. * * @param binder the data binder used to perform data binding * @param parameter the method argument */ protected boolean isBindExceptionRequired(WebDataBinder binder, MethodParameter parameter) { int i = parameter.getParameterIndex(); Class<?>[] paramTypes = parameter.getMethod().getParameterTypes(); boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1])); return !hasBindingResult; }
/** * Whether to raise a {@link MethodArgumentNotValidException} on validation errors. * * @param parameter the method argument * @return {@code true} if the next method argument is not of type {@link Errors} */ private boolean isBindingErrorFatal(MethodParameter parameter) { int i = parameter.getParameterIndex(); Class<?>[] paramTypes = parameter.getMethod().getParameterTypes(); boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1])); return !hasBindingResult; }
@Override public Object resolveArgument(MethodParameter param, NativeWebRequest request) throws Exception { if (request.getNativeRequest() instanceof ClientDataRequest && param.hasParameterAnnotation(PortletRequestBody.class)) { String value = param.getParameterAnnotation(PortletRequestBody.class).value(); ClientDataRequest clientDataRequest = request.getNativeRequest(ClientDataRequest.class); if (!PortletRequestBody.DEFAULT.equals(value)) { if (isMethod(clientDataRequest, RequestMethod.POST)) { String json = JSON_MAPPER.readTree(getRequestBody(clientDataRequest)).get(value).toString(); return JSON_MAPPER.readValue(json, param.getParameterType()); } else if (isMethod(clientDataRequest, RequestMethod.GET)) { return JSON_MAPPER.readValue(request.getParameter(value), param.getParameterType()); } throw new RuntimeException( MessageFormat.format( "REST Method {0} for values not supported.", clientDataRequest.getMethod())); } if (isMethod(clientDataRequest, RequestMethod.POST)) { return JSON_MAPPER.readValue(clientDataRequest.getReader(), param.getParameterType()); } throw new RuntimeException( MessageFormat.format( "REST Method {0} for body not supported.", clientDataRequest.getMethod())); } return WebArgumentResolver.UNRESOLVED; }
/* * (non-Javadoc) * * @see org.springframework.web.method.support.HandlerMethodArgumentResolver#resolveArgument( * org.springframework.core.MethodParameter, * org.springframework.web.method.support.ModelAndViewContainer, * org.springframework.web.context.request.NativeWebRequest, * org.springframework.web.bind.support.WebDataBinderFactory) */ @Override public Object resolveArgument( MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { return null; } Object details = authentication.getDetails(); if (details != null && !parameter.getParameterType().isAssignableFrom(details.getClass())) { AuthenticationDetails authenticationDetails = findMethodAnnotation(AuthenticationDetails.class, parameter); if (authenticationDetails.errorOnInvalidType()) { throw new ClassCastException( details + " is not assiable to " + parameter.getParameterType()); } else { return null; } } return details; }
private Boolean getAnnotatedRequired(MethodParameter methodParameter) { System.out.println("*** methodParameter: " + methodParameter.getParameterName()); Set<Boolean> requiredSet = new HashSet<Boolean>(); Annotation[] methodAnnotations = methodParameter.getParameterAnnotations(); // when the type is Optional, the required property of @RequestParam/@RequestHeader doesn't // matter, // since the value is always a non-null Optional after conversion boolean optional = isOptional(methodParameter); for (Annotation annotation : methodAnnotations) { if (annotation instanceof RequestParam) { requiredSet.add(!optional && isRequired((RequestParam) annotation)); } else if (annotation instanceof RequestHeader) { requiredSet.add(!optional && ((RequestHeader) annotation).required()); } else if (annotation instanceof PathVariable) { requiredSet.add(true); } else if (annotation instanceof RequestBody) { requiredSet.add(!optional && ((RequestBody) annotation).required()); } else if (annotation instanceof RequestPart) { requiredSet.add(!optional && ((RequestPart) annotation).required()); } else if (annotation instanceof NotNull) { System.out.println("*** FOUND NOTNULL ANNOTATION"); requiredSet.add(true); } } System.out.println("required: " + requiredSet.contains(true)); return requiredSet.contains(true); }
/** * Resolve the argument from the model or if not found instantiate it with its default if it is * available. The model attribute is then populated with request values via data binding and * optionally validated if {@code @java.validation.Valid} is present on the argument. * * @throws org.springframework.validation.BindException if data binding and validation result in * an error and the next method parameter is not of type {@link * org.springframework.validation.Errors}. * @throws Exception if WebDataBinder initialization fails. */ public final Object resolveArgument( MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest request, WebDataBinderFactory binderFactory) throws Exception { String name = parameter.getParameterAnnotation(FormModel.class).value(); Object target = (mavContainer.containsAttribute(name)) ? mavContainer.getModel().get(name) : createAttribute(name, parameter, binderFactory, request); WebDataBinder binder = binderFactory.createBinder(request, target, name); target = binder.getTarget(); if (target != null) { bindRequestParameters(mavContainer, binderFactory, binder, request, parameter); validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors()) { if (isBindExceptionRequired(binder, parameter)) { throw new BindException(binder.getBindingResult()); } } } target = binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType()); mavContainer.addAttribute(name, target); return target; }
private String determineHeaderExpression( Header headerAnnotation, MethodParameter methodParameter) { methodParameter.initParameterNameDiscovery(PARAMETER_NAME_DISCOVERER); String headerName = null; String relativeExpression = ""; String valueAttribute = headerAnnotation.value(); if (!StringUtils.hasText(valueAttribute)) { headerName = methodParameter.getParameterName(); } else if (valueAttribute.indexOf('.') != -1) { String tokens[] = valueAttribute.split("\\.", 2); headerName = tokens[0]; if (StringUtils.hasText(tokens[1])) { relativeExpression = "." + tokens[1]; } } else { headerName = valueAttribute; } Assert.notNull( headerName, "Cannot determine header name. Possible reasons: -debug is " + "disabled or header name is not explicitly provided via @Header annotation."); String headerRetrievalExpression = "headers['" + headerName + "']"; String fullHeaderExpression = headerRetrievalExpression + relativeExpression; String fallbackExpression = (headerAnnotation.required()) ? "T(org.springframework.util.Assert).isTrue(false, 'required header not available: " + headerName + "')" : "null"; return headerRetrievalExpression + " != null ? " + fullHeaderExpression + " : " + fallbackExpression; }
@Override public boolean supportsParameter(MethodParameter parameter) { Class<?> paramType = parameter.getParameterType(); return ((parameter.hasParameterAnnotation(Headers.class) && Map.class.isAssignableFrom(paramType)) || MessageHeaders.class.equals(paramType) || MessageHeaderAccessor.class.isAssignableFrom(paramType)); }
@Override public boolean supports( MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { returnType.increaseNestingLevel(); Type nestedType = returnType.getNestedGenericParameterType(); returnType.decreaseNestingLevel(); return ResourceSupport.class.isAssignableFrom(returnType.getParameterType()) || TypeUtils.isAssignable(ResourceSupport.class, nestedType); }
/** * Return {@code true} if there is a method-level {@code @ModelAttribute} or if it is a non-simple * type when {@code annotationNotRequired=true}. */ @Override public boolean supportsReturnType(MethodParameter returnType) { if (returnType.getMethodAnnotation(ModelAttribute.class) != null) { return true; } else if (this.annotationNotRequired) { return !BeanUtils.isSimpleProperty(returnType.getParameterType()); } else { return false; } }
/** * Determine whether the given dependency carries a value annotation. * * @see Value */ public Object getSuggestedValue(DependencyDescriptor descriptor) { Object value = findValue(descriptor.getAnnotations()); if (value == null) { MethodParameter methodParam = descriptor.getMethodParameter(); if (methodParam != null) { value = findValue(methodParam.getMethodAnnotations()); } } return value; }
/** * @return true if the parameter is annotated with {@link ModelAttribute} or in default resolution * mode also if it is not a simple type. */ @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; } }
private String getRequiredParameterName(MethodParameter methodParam) { String name = methodParam.getParameterName(); if (name == null) { throw new IllegalStateException( "No parameter name specified for argument of type [" + methodParam.getParameterType().getName() + "], and no parameter name information found in class file either."); } return name; }
@Override public boolean supportsReturnType(MethodParameter returnType) { if (ResponseBodyEmitter.class.isAssignableFrom(returnType.getParameterType())) { return true; } else if (ResponseEntity.class.isAssignableFrom(returnType.getParameterType())) { Class<?> bodyType = ResolvableType.forMethodParameter(returnType).getGeneric(0).resolve(); return (bodyType != null && ResponseBodyEmitter.class.isAssignableFrom(bodyType)); } return false; }
/** * Gets parameter name of this action input parameter. * * @return name */ public String getParameterName() { String ret; String parameterName = methodParameter.getParameterName(); if (parameterName == null) { methodParameter.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer()); ret = methodParameter.getParameterName(); } else { ret = parameterName; } return ret; }
@Override public boolean supportsParameter(MethodParameter parameter) { if (!parameter.hasParameterAnnotation(PathVariable.class)) { return false; } if (Map.class.isAssignableFrom(parameter.getParameterType())) { String paramName = parameter.getParameterAnnotation(PathVariable.class).value(); return StringUtils.hasText(paramName); } return true; }
@Override protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest webRequest) throws Exception { Object arg = super.resolveName(name, parameter, webRequest); arg = tryUnJson(parameter, arg); if (createValidators(parameter.getMethod())) { validate(parameter.getMethod(), parameter.getParameterIndex(), arg); } return arg; }
@Override public Mono<Object> resolveArgument( MethodParameter param, BindingContext bindingContext, ServerWebExchange exchange) { ResolvableType entityType = ResolvableType.forMethodParameter(param); MethodParameter bodyParameter = new MethodParameter(param); bodyParameter.increaseNestingLevel(); return readBody(bodyParameter, false, bindingContext, exchange) .map(body -> createHttpEntity(body, entityType, exchange)) .defaultIfEmpty(createHttpEntity(null, entityType, exchange)); }
@Override public ModelAndView resolveException( HttpServletRequest request, HttpServletResponse response, Object handler, Exception exp) { Map<String, Object> errorMap = new HashMap<>(2); if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; MethodParameter[] methodParameters = handlerMethod.getMethodParameters(); if (methodParameters != null && methodParameters.length > 0) { MethodParameter methodParameter = methodParameters[0]; Class<?> controllerClass = methodParameter.getContainingClass(); if (controllerClass.isAnnotationPresent(Channel.class)) { String channel = controllerClass.getAnnotation(Channel.class).value(); if (ChannelSet.QUNAR.equals(channel)) { log.error("QUNAR异常处理:", exp); if (exp instanceof SQLException) { errorMap.put(QunarResultKey.errorCode.name(), QunarErrorCode.ERR_SQL.code()); errorMap.put(QunarResultKey.errorMsg.name(), QunarErrorCode.ERR_SQL.value()); } if (exp instanceof TradeException) { TradeException ex = (TradeException) exp; errorMap.put(QunarResultKey.errorCode.name(), ex.getReturnCode()); errorMap.put(QunarResultKey.errorMsg.name(), ex.getReturnMessage()); } else { errorMap.put(QunarResultKey.errorCode.name(), QunarErrorCode.ERR_PARAM.code()); errorMap.put(QunarResultKey.errorMsg.name(), QunarErrorCode.ERR_PARAM.value()); } log.error("去哪儿返回异常:" + JSON.toJSONString(errorMap)); return new ModelAndView(new MappingJackson2JsonView(), errorMap); } else if (ChannelSet.CTRIP.equals(channel)) { log.error("CTRIP异常处理:", exp); if (exp instanceof TradeException) { TradeException ex = (TradeException) exp; errorMap.put(CTripResultKey.MsgCode.name(), ex.getReturnCode()); errorMap.put(CTripResultKey.Message.name(), ex.getReturnMessage()); } else { errorMap.put(CTripResultKey.MsgCode.name(), CTripErrorCode.ERROR.name()); errorMap.put(CTripResultKey.Message.name(), CTripErrorCode.ERROR.value); } log.error("携程返回异常:" + JSON.toJSONString(errorMap)); return new ModelAndView(new MappingJackson2JsonView(), errorMap); } } } } // do as default log.error("HBC标准异常处理:", exp); errorMap.put(StandardResultKey.status.name(), Integer.valueOf(RspStatus.ERROR.toString())); errorMap.put(StandardResultKey.message.name(), exp.toString()); return new ModelAndView(new MappingJackson2JsonView(), errorMap); }
private String getPartName(MethodParameter parameter) { RequestPart annot = parameter.getParameterAnnotation(RequestPart.class); String partName = (annot != null ? annot.value() : ""); if (partName.length() == 0) { partName = parameter.getParameterName(); Assert.notNull( partName, "Request part name for argument type [" + parameter.getParameterType().getName() + "] not specified, and parameter name information not found in class file either."); } return partName; }
/** * Obtains the specified {@link Annotation} on the specified {@link MethodParameter}. * * @param annotationClass the class of the {@link Annotation} to find on the {@link * MethodParameter} * @param parameter the {@link MethodParameter} to search for an {@link Annotation} * @return the {@link Annotation} that was found or null. */ private <T extends Annotation> T findMethodAnnotation( Class<T> annotationClass, MethodParameter parameter) { T annotation = parameter.getParameterAnnotation(annotationClass); if (annotation != null) { return annotation; } Annotation[] annotationsToSearch = parameter.getParameterAnnotations(); for (Annotation toSearch : annotationsToSearch) { annotation = AnnotationUtils.findAnnotation(toSearch.annotationType(), annotationClass); if (annotation != null) { return annotation; } } return null; }
@Override public boolean supportsParameter(MethodParameter parameter) { if (parameter.hasParameterAnnotation(FormModel.class)) { return true; } return false; }
private WebDataBinder resolveModelAttribute( String attrName, MethodParameter methodParam, ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception { // Bind request parameter onto object... String name = attrName; if ("".equals(name)) { name = Conventions.getVariableNameForParameter(methodParam); } Class<?> paramType = methodParam.getParameterType(); Object bindObject; if (implicitModel.containsKey(name)) { bindObject = implicitModel.get(name); } else if (this.methodResolver.isSessionAttribute(name, paramType)) { bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name); if (bindObject == null) { raiseSessionRequiredException( "Session attribute '" + name + "' required - not found in session"); } } else { bindObject = BeanUtils.instantiateClass(paramType); } WebDataBinder binder = createBinder(webRequest, bindObject, name); initBinder(handler, name, binder, webRequest); return binder; }
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; }
private ServletRequest prepareServletRequest( Object target, NativeWebRequest request, MethodParameter parameter) { String modelPrefixName = parameter.getParameterAnnotation(FormModel.class).value(); HttpServletRequest nativeRequest = (HttpServletRequest) request.getNativeRequest(); MultipartRequest multipartRequest = WebUtils.getNativeRequest(nativeRequest, MultipartRequest.class); MockHttpServletRequest mockRequest = null; if (multipartRequest != null) { MockMultipartHttpServletRequest mockMultipartRequest = new MockMultipartHttpServletRequest(); for (MultipartFile file : multipartRequest.getFileMap().values()) { mockMultipartRequest.addFile( new MultipartFileWrapper(getNewParameterName(file.getName(), modelPrefixName), file)); } mockRequest = mockMultipartRequest; } else { mockRequest = new MockHttpServletRequest(); } for (Entry<String, String> entry : getUriTemplateVariables(request).entrySet()) { String parameterName = entry.getKey(); String value = entry.getValue(); if (isFormModelAttribute(parameterName, modelPrefixName)) { mockRequest.setParameter(getNewParameterName(parameterName, modelPrefixName), value); } } for (Object parameterEntry : nativeRequest.getParameterMap().entrySet()) { Entry<String, String[]> entry = (Entry<String, String[]>) parameterEntry; String parameterName = entry.getKey(); String[] value = entry.getValue(); if (isFormModelAttribute(parameterName, modelPrefixName)) { mockRequest.setParameter(getNewParameterName(parameterName, modelPrefixName), value); } } return mockRequest; }