Spring: ArgumentResolver

复制代码
package io.jot.memento;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockPart;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver;
import org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver;
import org.springframework.web.method.annotation.RequestParamMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.method.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Venal{
  public static void main(String[] args) throws Exception{
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Venal.class);
    DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
    HttpServletRequest request = mockRequest();
    // 1. 控制器方法被封装为HandlerMethod
    HandlerMethod handlerMethod = new HandlerMethod(new Controller(), Controller.class.getMethod("test", String.class, String.class, int.class, String.class, MultipartFile.class, int.class, String.class, String.class, String.class, HttpServletRequest.class, User.class, User.class, User.class));
    // 2. 准备对象绑定与类型转换
    ServletRequestDataBinderFactory dataBinderFactory = new ServletRequestDataBinderFactory(null, null);
    // 3. 准备 ModelAndViewContainer 用来存储中间 Model 结果
    ModelAndViewContainer container = new ModelAndViewContainer();

    for(MethodParameter methodParameter : handlerMethod.getMethodParameters()){
      String annotations = Arrays.stream(methodParameter.getParameterAnnotations()).map(a -> a.annotationType().getSimpleName()).collect(Collectors.joining());
      annotations = annotations.length() > 0 ? "@" + annotations : annotations;
      methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
      Object v = null;

      HandlerMethodArgumentResolverComposite argumentResolverComposite = new HandlerMethodArgumentResolverComposite();
      argumentResolverComposite.addResolvers(
        new RequestParamMethodArgumentResolver(beanFactory, false),
        new PathVariableMethodArgumentResolver(),
        new ServletCookieValueMethodArgumentResolver(beanFactory),
        new RequestHeaderMethodArgumentResolver(beanFactory),
        new ExpressionValueMethodArgumentResolver(beanFactory),
        new ServletRequestMethodArgumentResolver(),
        new ServletModelAttributeMethodProcessor(false),
        new RequestResponseBodyMethodProcessor(List.of(new MappingJackson2HttpMessageConverter())),
        new ServletModelAttributeMethodProcessor(true),
        new RequestParamMethodArgumentResolver(true)
      );


      if(argumentResolverComposite.supportsParameter(methodParameter)){
        v = argumentResolverComposite.resolveArgument(methodParameter, container, new ServletWebRequest(request), dataBinderFactory);
        // System.out.println("v.getClass() = " + v.getClass());
        System.out.printf("\033[37;7m [%02d] %-15s %-20s %-10s --> %s \033[0m\n", methodParameter.getParameterIndex(), annotations, methodParameter.getParameterType().getSimpleName(), methodParameter.getParameterName(), v);
        System.out.println("container.getModel() = " + container.getModel());
      }else{
        System.out.printf("\033[37;7m [%02d] %-15s %-20s %-10s --> %s \033[0m\n", methodParameter.getParameterIndex(), annotations, methodParameter.getParameterType().getSimpleName(), methodParameter.getParameterName(), v);
      }


    }
  }

  private static HttpServletRequest mockRequest(){
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.setParameter("name1", "zhangsan");
    request.setParameter("name2", "lisi");
    request.addPart(new MockPart("file", "abc", "hello".getBytes(StandardCharsets.UTF_8)));
    Map<String, String> map = new AntPathMatcher().extractUriTemplateVariables("/test/{id}", "/test/123");
    System.out.println(map);
    request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, map);
    request.setContentType("application/json");
    request.setCookies(new Cookie("token", "123456"));
    request.setParameter("name", "张三");
    request.setParameter("age", "18");
    request.setContent("""
          {
              "name":"李四",
              "age":20
          }
      """.getBytes(StandardCharsets.UTF_8));

    return new StandardServletMultipartResolver().resolveMultipart(request);
  }

  static class Controller{
    public void test(
      @RequestParam("name1") String name1, // name1=张三
      String name2,                        // name2=李四
      @RequestParam("age") int age,        // age=18
      @RequestParam(name = "home", defaultValue = "${JAVA_HOME}") String home1, // spring 获取数据
      @RequestParam("file") MultipartFile file, // 上传文件
      @PathVariable("id") int id,               //  /test/124   /test/{id}
      @RequestHeader("Content-Type") String header,
      @CookieValue("token") String token,
      @Value("${JAVA_HOME}") String home2, // spring 获取数据  ${} #{}
      HttpServletRequest request,          // request, response, session ...
      @ModelAttribute("abc") User user1,          // name=zhang&age=18
      User user2,                          // name=zhang&age=18
      @RequestBody User user3              // json
    ){

    }
  }

  static class User{
    private String name;
    private int age;

    public String getName(){
      return name;
    }

    public void setName(String name){
      this.name = name;
    }

    public int getAge(){
      return age;
    }

    public void setAge(int age){
      this.age = age;
    }

    @Override
    public String toString(){
      return "User{" +
        "name='" + name + '\'' +
        ", age=" + age +
        '}';
    }
  }
}
复制代码

 

posted @   ascertain  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
历史上的今天:
2020-06-01 miscellanea
点击右上角即可分享
微信分享提示