当前位置:网站首页>Application and principle of handlermethodargumentresolver

Application and principle of handlermethodargumentresolver

2020-11-07 17:19:42 LBJ Yu

HandlerMethodArgumentResolver Policy interface for parsing method parameters to parameter values , What we often call a custom parameter parser , Source code is as follows  

/**
 * Strategy interface for resolving method parameters into argument values in
 * the context of a given request.
 *
 * @author Arjen Poutsma
 * @since 3.1
 * @see HandlerMethodReturnValueHandler
 */
public interface HandlerMethodArgumentResolver {

   /**
    * Whether the given {@linkplain MethodParameter method parameter} is
    * supported by this resolver.
    * @param parameter the method parameter to check
    * @return {@code true} if this resolver supports the supplied parameter;
    * {@code false} otherwise 
    */
   boolean supportsParameter(MethodParameter parameter);

   /**
    * Resolves a method parameter into an argument value from a given request.
    * A {@link ModelAndViewContainer} provides access to the model for the
    * request. A {@link WebDataBinderFactory} provides a way to create
    * a {@link WebDataBinder} instance when needed for data binding and
    * type conversion purposes.
    * @param parameter the method parameter to resolve. This parameter must
    * have previously been passed to {@link #supportsParameter} which must
    * have returned {@code true}.
    * @param mavContainer the ModelAndViewContainer for the current request
    * @param webRequest the current request
    * @param binderFactory a factory for creating {@link WebDataBinder} instances
    * @return the resolved argument value, or {@code null} if not resolvable
    * @throws Exception in case of errors with the preparation of argument values
    */
   @Nullable
   Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
         NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;

}

Here's my little example , It is mainly through the custom parameter parser to change the paging parameters , Extract them and encapsulate them into entity objects

1. First, customize an annotation

/**
 * @Author:  Yu Yunbo (18088704)
 * @Date: 2020/11/7 10:18
 * @Description:
 */
@Target(ElementType.PARAMETER)
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomArgumentPage {
}

2. Write a custom parameter parser implementation class

import com.suning.logistics.jwms.on.base.vo.PageBean;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author:  Yu Yunbo (18088704)
 * @Date: 2020/11/7 10:14
 * @Description:
 */
public class CustomArgumentResolvers implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(CustomArgumentPage.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        String page = request.getParameter("page");
        String pageSize = request.getParameter("pageSize");
        PageBean pageBean = new PageBean();
        if (StringUtils.isNotEmpty(page)) {
            pageBean.setCurrentPage(Integer.valueOf(page).intValue());
        }
        if (StringUtils.isNotEmpty(pageSize)) {
            pageBean.setPageSize(Integer.valueOf(pageSize).intValue());
        }
        pageBean.setStartPage((pageBean.getCurrentPage()-1)*pageBean.getPageSize());
        return pageBean;
    }
}

3. Inject a custom parser into IOC in

@Bean
public CustomArgumentResolvers initCustomArgumentResolvers(){
    return new CustomArgumentResolvers();
}

4. Will custom parameter parser , Injection into MvcConfigure in

@Configuration
public class WebMvcCustomConfigurer implements WebMvcConfigurer {


    @Autowired
    private CustomArgumentResolvers customArgumentResolvers;

    /**
     * Add resolvers to support custom controller method argument types.
     * <p>This does not override the built-in support for resolving handler
     * method arguments. To customize the built-in support for argument
     * resolution, configure {@link RequestMappingHandlerAdapter} directly.
     *
     * @param resolvers initially an empty list
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(customArgumentResolvers);
    }
}

5. Write tests Controller 

@RequestMapping("/queryPageConfigList")
@ResponseBody
public Object getWarehouseCodeReadyonly(@CustomArgumentPage PageBean pageBean){
    return warehouseConfigService.queryPage(pageBean,null);
}

6. The effect is as follows

The following source code analysis of a wave , Tell me about the whole process ,

1. stay Springboot  AutoConfiguration Will automatically inject   WebMvcAutoConfiguration

2. stay WebMvcAutoConfiguration in Static inner class  EnableWebMvcConfiguration It inherited DelegatingWebMvcConfiguration This class , This is very important , Medium   requestMappingHandlerAdapter Method , initialization HandlerAdapter 

super.requestMappingHandlerAdapter()

3. In the parent class WebMvcConfigurationSupport in , Here's the picture 565 Line code , Will give HandlerAdapter Set custom parameter parser

4. Get into getArgumentResolvers Method , The core approach   addArgumentResolvers

5. It's an empty method ???, Source tracking is into its subclass  DelegatingWebMvcConfiguration In this class

6. Continue to code trace the next step , Will arrive WebMvcConfigurerComposite in addArgumentResolvers Method , Cycle WebMvcConfigurer List  Call the  addArgumentResolvers As for this this.delegates How to initialize , You can study for yourself

7. Finally, it will be transferred to our customized WebMvcCustomConfigurer in , Will our custom parameter parser , Add to the entire parameter resolution List in

8. Analyze the number parameter List Set to HandlerAdapter in

9. When called , The whole call chain is shown in the figure below , Just interested students can analyze it by themselves

 

版权声明
本文为[LBJ Yu]所创,转载请带上原文链接,感谢