handler method parameter binding

handler method commonly used parameter binding annotations, we divided depending on the content part of the Request of the four categories they deal mainly on :( common type)

A, requet uri processing portion (referred to herein as the uri template variable, excluding queryString portion) notes: @PathVariable;

B, the processing request header portion annotation: @RequestHeader, @CookieValue;

C, annotation processing request body portion: @RequestParam, @RequestBody;

D, the processing attribute type annotation: @SessionAttributes, @ModelAttribute;

 

1, @PathVariable

When using @RequestMapping URI template style mapping, i.e. someUrl / {paramId}, at this time may be bound by @Pathvariable paramId annotations on process parameter values ​​to pass over it.

@Controller 
@RequestMapping("/owners/{ownerId}") 
public class RelativePathUriTemplateController { 
 
  @RequestMapping("/pets/{petId}") 
  public void findPet(@PathVariable String ownerId,@PathVariable String petId, Model model) {     
    // implementation omitted 
  } 
} 

The code above and petId values ​​of variables ownerId the URI template, bound to the parameters of the method. If the uri template variable name and the name of the method parameters need to bind not, you need to specify the name uri template in the @PathVariable ( "name").

 

2、 @RequestHeader、@CookieValue

@RequestHeader annotations can request value Request header portion bound to the parameters of the method.

This is the header part of a Request:

Host                    localhost:8080 
Accept                  text/html,application/xhtml+xml,application/xml;q=0.9 
Accept-Language         fr,en-gb;q=0.7,en;q=0.3 
Accept-Encoding         gzip,deflate 
Accept-Charset          ISO-8859-1,utf-8;q=0.7,*;q=0.7 
Keep-Alive              300 
@RequestMapping("/displayHeaderInfo.do") 
public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding, 
                              @RequestHeader("Keep-Alive")long keepAlive)  { 
 
  //... 
 
}

The above code, the value of the Accept-Encoding request header portion, bound to the encoding parameters, and Keep-Alive header value is bound to the parameter keepAlive.

 

@CookieValue can Request header value on the cookie bound to the parameters of the method. Such as:

JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84 

Parameter binding code:

@RequestMapping("/displayHeaderInfo.do") 
public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie)  { 
 
  //... 
 
} 

 

3、@RequestParam, @RequestBody

@RequestParam 

A) used to process the simple type of binding, by Request.getParameter () String obtained can be converted directly to the case of simple type (String -> a simple type of switching operation done by the configuration of the converter ConversionService); for use request.getParameter () mode acquisition parameters, it is possible to get processed value queryString embodiment, the embodiment may be post processed value of the body data;

B) for processing Content-Type: for the  application/x-www-form-urlencodedencoded contents, submission GET, POST;

C) The annotation has two attributes: value, required; value is used to specify the value to be passed id name, required to indicate whether the parameter must be bound;

@Controller 
@RequestMapping("/pets") 
@SessionAttributes("pet") 
public class EditPetForm { 

    @RequestMapping(method = RequestMethod.GET) 
    public String setupForm(@RequestParam("petId")int petId, ModelMap model) { 
        Pet pet = this.clinic.loadPet(petId); 
        model.addAttribute("pet", pet); 
        return "petForm"; 
    } 

 

@RequestBody

The annotation process used to Content-Type: not application/x-www-form-urlencodedencoded contents, for example, application / json, application / xml like;

It is through the use of HandlerAdapter configured HttpMessageConvertersto parse post data body, and then bound to the appropriate bean.

Because equipped with FormHttpMessageConverter, so it can be used to process the  application/x-www-form-urlencodedcontent of the results processed on a MultiValueMap <String, String> where, in this case the use of some special needs, Detail View FormHttpMessageConverter api;

@RequestMapping(value ="/something", method = RequestMethod.PUT) 
public void handle(@RequestBody String body, Writer writer)throws IOException { 
  writer.write(body); 
} 

 

4、@SessionAttributes, @ModelAttribute

@SessionAttributes:

The annotation for the attribute value of the object HttpSession bindings, easy to use in the process parameters in.

The notes have value, types two properties, you can specify an attribute object to be used by name and type;

. 4 , @ SessionAttributes, @ModelAttribute 
@SessionAttributes: 

the annotation to the object attribute value HttpSession bindings, easy to use in the process parameters in. 

The notes have value, types two properties, you can specify an attribute object to be used by name and type;

 

@ModelAttribute

The annotation has two uses, a method for the one for the parameter;

When used on a method: before processing usually used @RequestMapping, model binding need, request from the background;

When the parameters used: by name to a corresponding, binds the value corresponding to the parameter name annotation bean; values ​​to be bound from:

On A) @SessionAttributes enabled attribute object;

B) @ModelAttribute model object for specified when the method;

C) above two cases are sometimes no, a new new bean objects to be bound, and the request by name in a corresponding manner to bind the values ​​to the bean.

 

@ModelAttribute sample code used in the methods of:

@ModelAttribute  
public Account addAccount(@RequestParam String number) {  
    return accountManager.findAccount(number);  
} 

The actual effect of this approach is the method invocation before @RequestMapping of, model for the request object's put ( "account", Account);

 

@ModelAttribute sample code used in the parameters:

@RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)  
public String processSubmit(@ModelAttribute Pet pet) {  
     
} 

The first query the Pet objects @SessionAttributes whether the binding of, if not the query on whether the method level @ModelAttribute bound Pet objects, if there is no value will be URI template in accordance with the corresponding name of the object bound to the Pet of each attribute .

 

 

Supplementary explanation:

Question: without the annotation of a given parameter is how binding?

AnnotationMethodHandlerAdapter and RequestMappingHandlerAdapter source code found by analyzing the parameters of the methods without given parameter:

To bind the object is a simple type: Call @RequestParam handled.  

To bind complex type of an object: Call @ModelAttribute handled.

Simple type here refers to Java primitive types (boolean, int, etc.), the original type of object (Boolean, Int etc.), String, Date, etc. ConversionService where you can directly convert String target object type;

 

AnnotationMethodHandlerAdapter bound parts of the source parameters:

private Object[] resolveHandlerArguments(Method handlerMethod, Object handler, 
            NativeWebRequest webRequest, ExtendedModelMap implicitModel)throws Exception { 
 
        Class[] paramTypes = handlerMethod.getParameterTypes(); 
        Object[] args = new Object[paramTypes.length]; 
 
        for (int i =0; i < args.length; i++) { 
            MethodParameter methodParam = new MethodParameter(handlerMethod, i); 
            methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer); 
            GenericTypeResolver.resolveParameterType(methodParam, handler.getClass()); 
            String paramName = null; 
            String headerName = null; 
            boolean requestBodyFound =false; 
            String cookieName = null; 
            String pathVarName = null; 
            String attrName = null; 
            boolean required =false; 
            String defaultValue = null; 
            boolean validate =false; 
            Object[] validationHints = null; 
            int annotationsFound =0; 
            Annotation[] paramAnns = methodParam.getParameterAnnotations(); 
 
            for (Annotation paramAnn : paramAnns) { 
                if (RequestParam.class.isInstance(paramAnn)) { 
                    RequestParam requestParam = (RequestParam) paramAnn; 
                    paramName = requestParam.value(); 
                    required = requestParam.required(); 
                    defaultValue = parseDefaultValueAttribute(requestParam.defaultValue()); 
                    annotationsFound++; 
                } 
                else if (RequestHeader.class.isInstance(paramAnn)) { 
                    RequestHeader requestHeader = (RequestHeader) paramAnn; 
                    headerName = requestHeader.value(); 
                    required = requestHeader.required(); 
                    defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue()); 
                    annotationsFound++; 
                } 
                else if (RequestBody.class.isInstance(paramAnn)) { 
                    requestBodyFound = true; 
                    annotationsFound++; 
                } 
                else if (CookieValue.class.isInstance(paramAnn)) { 
                    CookieValue cookieValue = (CookieValue) paramAnn; 
                    cookieName = cookieValue.value(); 
                    required = cookieValue.required(); 
                    defaultValue = ParseDefaultValueAttribute (cookieValuedefaultValue ()); 
                    annotationsFound ++ ; 
                } 
                Else  the if (PathVariable. Class isInstance (paramAnn)) { 
                    PathVariable pathVar = (PathVariable) paramAnn; 
                    pathVarName = pathVarvalue (); 
                    annotationsFound ++ ; 
                } 
                Else  the if (ModelAttribute. Class isInstance (paramAnn)) { 
                    ModelAttribute attr =  (ModelAttribute) paramAnn;
                    attrName= attr.value(); 
                    annotationsFound++; 
                } 
                else if (Value.class.isInstance(paramAnn)) { 
                    defaultValue = ((Value) paramAnn).value(); 
                } 
                else if (paramAnn.annotationType().getSimpleName().startsWith("Valid")) { 
                    validate = true; 
                    Object value = AnnotationUtils.getValue(paramAnn); 
                    validationHints = (value the instanceofObject [] (Object []) value:? New new Object [] {value}); 
                } 
            } 
 
            IF (annotationsFound>. 1 ) { 
                 the throw  new new IllegalStateException ( "Handler Parameter Annotations are exclusive choices -" + 
                        "do Not the Specify More Within last One annotation The Same parameter ON SUCH: "+ HandlerMethod); 
            } 
 
            iF (annotationsFound == 0) { // if not found annotation 
                Object argValue = resolveCommonArgument (methodParam, WebRequest);    // determines whether WebRquest parameter may be assigned to 
                iF (argValue! = WebArgumentResolver.UNRESOLVED) {
                    args[i] = argValue; 
                } 
                else if (defaultValue !=null) { 
                    args[i] = resolveDefaultValue(defaultValue); 
                } 
                else { 
                    Class<?> paramType = methodParam.getParameterType(); 
                    if (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) { 
                        if (!paramType.isAssignableFrom(implicitModel.getClass())) { 
                            thrownew IllegalStateException("Argument [" + paramType.getSimpleName() +"] is of type " + 
                                    "Model or Map but is not assignable from the actual model. You may need to switch " + 
                                    "newer MVC infrastructure classes to use this argument."); 
                        } 
                        args[i] = implicitModel; 
                    } 
                    elseif (SessionStatus.class.isAssignableFrom(paramType)) { 
                        args[i] = this.sessionStatus; 
                    } 
                    else if (HttpEntity.class.isAssignableFrom (paramType)) { 
                        args [I] = resolveHttpEntityRequest (methodParam, WebRequest); 
                    } 
                    . ELSEIF (the Errors class .isAssignableFrom (paramType)) { 
                         the throw  new new IllegalStateException ( "the Errors / the BindingResult declared argument" + 
                                "the without PRECEDING Model attribute. Method Signature your Handler the Check "! ); 
                    } 
                    ELSEIF (BeanUtils.isSimpleProperty (paramType)) { //Determining whether the parameter type is a simple type, if used in the manner @RequestParam process, otherwise the @ModelAttribute manner  
                        paramName =" "; 
                    } 
                    the else { 
                        attrName = "" ; 
                    } 
                } 
            } 
 
            IF (! = ParamName null ) { 
                args [I] = resolveRequestParam (paramName, required, defaultValue, methodParam, WebRequest, Handler); 
            } 
            the else  IF (headerName =! null ) { 
                args [I] = resolveRequestHeader (headerName, required, defaultValue, methodParam, WebRequest, Handler);
            } 
            else if (requestBodyFound) { 
                args[i] = resolveRequestBody(methodParam, webRequest, handler); 
            } 
            else if (cookieName != null) { 
                args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler); 
            } 
            else if (pathVarName !=null) { 
                args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler); 
            } 
            else if (attrName != null) { 
                WebDataBinder binder = 
                        resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler); 
                boolean assignBindingResult = (args.length > i +1 && Errors.class.isAssignableFrom(paramTypes[i +1])); 
                if (binder.getTarget() !=null) { 
                    doBind(binder, webRequest, validate, validationHints, !assignBindingResult); 
                } 
                args[i] = binder.getTarget(); 
                if (assignBindingResult) { 
                    args[i + 1] = binder.getBindingResult(); 
                    i++; 
                } 
                implicitModel.putAll(binder.getBindingResult().getModel()); 
            } 
        } 
 
        return args; 
    } 

RequestMappingHandlerAdapter parameters used in the binding, the code is slightly different, interested colleagues can be analyzed, the results of the last process is the same.

 

Example:

    @RequestMapping ({"/","/home"}) 
    public String showHomePage(String key){ 
         
        logger.debug("key="+key); 
         
        return "home"; 
    } 

In this case, call the default @RequestParam to deal with.

 

@RequestMapping (method = RequestMethod.POST) 
public String doRegister(User user){ 
    if(logger.isDebugEnabled()){ 
        logger.debug("process url[/user], method[post] in "+getClass()); 
        logger.debug(user); 
    } 
 
    return "user"; 
} 

In this case, it calls @ModelAttribute to deal with.

 

Original: https: //blog.csdn.net/truong/article/details/28097837#

Guess you like

Origin www.cnblogs.com/yrjns/p/11285452.html