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 + '}'; } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2020-06-01 miscellanea